什么是分库分表?它有哪些实现类型?

假如你正在使用关系型数据库开发一款健康类系统。业务发展很好,系统有很多活跃的新老用户,这些用户会和平台的医生团队进行交互,每天可能会生成数万甚至数十万级别的业务数据。这样的话,随着数据量越来越大,系统中的某些数据表的访问就会出现瓶颈,最典型的就是用于保存用户和医生日常交流数据的健康咨询表:


虽然从理论上讲,像健康咨询表这样位于关系型数据库中的单个表可以存储的数据能够达到亿条级别,但这时候访问性能就会变得很差。业界普遍认为,诸如MySQL这样的主流数据库,单表容量在千万以下是一项最佳实践,一旦超过这个量级,就需要考虑采用其他方案。那么问题就来了,我们如何应对日益增长的数据量呢?有没有成熟的解决方案呢?

答案是肯定的,这就是我们接下来要引入的分库分表技术。所谓分库分表,你可以简单理解为:将原来独立的数据库拆分成若干数据库,将原来数据量大的单个表拆分成若干个数据表,使得单一数据库、单一数据表的数据量变得足够小,从而达到提升数据库性能的效果。有时候,我们也把分库分表统称为是一种数据分片技术,因为从概念上讲,无论是分库还是分表,都是把一定数据划分成不同的数据片,并存储在不同的目标对象中。

讲到这里,你实际上已经明确了一点,无论是分库还是分表,本质上体现的都是一种对现有数据进行拆分的思想,而这种拆分思想又有两种不同的实现策略,即垂直拆分和水平拆分:


相比水平拆分,垂直拆分相对比较容易理解和实现,所以我们先来讨论这种拆分策略。在健康类系统中,用户在查看健康咨询表数据时,位于健康咨询首页的诸如咨询编号、医生编号等基础数据的访问频率显然要比咨询详情等明细数据更高,因为用户总是先定位到基础数据,然后再选择某一个咨询记录并查看明细。基于这两种数据的不同访问特性,我们可以把健康咨询这种单表进行拆分,根据访问频次来把咨询数据分别放在两张表中,如下所示:


由此可以,垂直分表的处理方式就是将一个表按照字段分成多张表,每个表存储其中一部分字段。在实现上,我们通常会把诸如详情类的低热度数据放在一张独立的表中。

通过垂直分表能得到来一定程度的性能提升,但毕竟拆分后的数据仍然都是位于同一个数据库实例中,每个表还是会竞争同一台数据库服务器中的CPU、内存、网络IO等资源,性能的提升限制很多。基于这一考虑,在有了垂直分表之后,我们就可以进一步引入垂直分库。

让我们回到案例,针对前面介绍的场景,分表之后的健康咨询表同样还是跟健康用户表等其他数据表存放在同一台服务器中。基于垂直分库思想,这时候,我们就可以把健康咨询相关的数据表单独拆分出来,放在一个独立的数据库中,如下图所示:


上图的效果就是垂直分库。从定义上讲,垂直分库是指将表进行分类,然后分布到不同的数据库实例上。显然,在高并发场景下,垂直分库能够一定程度的提升IO访问效率和数据库连接数,并降低单机硬件资源的瓶颈。

从前面的分析中我们不难明白,垂直拆分尽管实现起来比较简单,但并不能解决单表数据量过大这一核心问题。所以,现实中我们往往需要在垂直拆分的基础上再添加水平拆分机制。例如,我们可以对健康咨询库中的健康咨询表数据按照用户编号进行取模,然后分别存储在不同的数据库中,这就是水平分库的常见做法,如下所示:


可以看到,水平分库是把同一个表的数据按一定规则拆分到不同的数据库实例中。如果采用了上图中的水平分库方案,系统复杂度就会比垂直分库要高很多,因为我们就不得不面临一个问题,即如何知道目标数据位于哪一个数据库中呢?这就需要引入路由规则的概念。像上图中根据“用户编号以3取模”就是一条路由规则。

那么,我们如何来设计并实现这些路由规则呢?业界也存在一系列路由算法,常见的包括范围限定算法、预定义算法以及前面介绍的取模算法:


参照水平分库的思路,我们也可以对用户库中的用户表进行水平拆分,效果如下所示。也就是说,水平分表是在同一个数据库内,把同一个表的数据按一定规则拆到多个表中。


到现在为止,我们已经把分库分表的基本概念梳理了一遍。你会发现这些概念理解起来并不是很复杂,但如何实现这些概念呢?你可以自己从零开始打造一套分库分表的实现工具,但显然并没有看上去那么简单,而我也不推荐你重复造轮子。幸好,目前业界已经存在一批分库分表的实现方案,主要分成客户端类分库分表和代理服务类分库分表两大类,接下去我也来介绍一下。


所谓客户端类分库分表,相当于在使用数据库的客户端应用程序中就完成了数据分片的实现。针对这种方案,因为没有独立的服务器组件,所以结构上比较简单。在Java世界中,通常做法会把客户端分片相关的处理逻辑单独抽离出来封装成一个独立的工具包,从而避免业务代码和分库分表逻辑过于耦合。而这个独立工具包的构建方法通常就是覆写现有的JDBC规范,这样,业务开发人员还是使用与JDBC规范完全兼容的一套API来操作数据库,但这套API的背后却自动完成了分库分表操作,效果如下:


这种解决方案的优势在于分库分表操作对于业务而言是完全透明的。这样,普通业务开发人员只需要理解JDBC规范就可以自行实现分库分表,开发难度以及代码维护成本得到降低。

另一方面,代理服务类分库分表的解决方案也比较明确,顾名思义,就是采用了代理机制,也就是说在应用层和数据库层之间添加一个代理层。有了代理层之后,对内我们就可以把分片规则集中维护在这个代理层中,对外则同样提供与JDBC兼容的API给到应用层,其效果如下所示:


显然,代理服务器分库分表方案的优点在于解放了业务开发人员对分库分表规则的管理工作,而缺点就是添加了一层代理层,一方面会因为新增了一层网络传输而对性能产生一定的影响;另一方面,通常也需要专门的运维人员来确保代理服务器本身的稳定性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/39823.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

被⽹络罪犯利⽤的5⼤ChatGPT越狱提⽰

⾃ChatGPT发布的近18个月以来,⽹络罪犯们已经能够利⽤⽣成式AI进⾏攻击。OpenAI在其内容政策中制定了限制措施,以阻⽌⽣成恶意内容。作为回应,攻击者们创建了⾃⼰的⽣成式AI平台,如 WormGPT和FraudGPT,并且他们还分享了…

IP地址定位中多源数据融合的应用

IP地址定位如今在诸如网络安全、地理信息服务、智能交通等领域发挥着关键作用。然而,传统的基于单一数据源(如IP数据库)的定位方法往往存在精度有限、可靠性不足等问题。多源数据融合技术的出现为解决这些问题提供了新的思路和方法。今天我们…

石墨烯分散液制备方法众多 应用领域广泛

石墨烯分散液制备方法众多 应用领域广泛 石墨烯分散液指将石墨烯纳米片均匀分散在特定溶剂中制成的溶液。石墨烯分散液具有化学稳定性好、生物相容性好、热稳定性好等优势,未来有望在涂料、纤维制品、电池制造、油墨等领域获得广泛应用。 石墨烯分散液以石墨…

绝区零卡顿严重、延迟高的解决方法提前看

绝区零这款游戏背后是一个错综复杂的架空世界,仿佛一幅波澜壮阔的史诗画卷缓缓展开。在这个世界中,神秘莫测的“空洞”灾害如影随形,给大地带来了无尽的破坏和混沌。经过米哈游团队的精心雕琢,无论是画面UI的细腻呈现,…

灌区量测水管理系统是如何实现灌区节水?

随着全球水资源日益紧张,节水已成为农业生产中不可忽视的一环。在灌区管理中,量测水管理系统以其精准的数据监测和科学的灌溉管理,为实现灌区节水提供了强有力的技术支持。 灌区量测水管理系统是一套集成了自动化监测、数据传输、数据分析和…

Springboot交流论坛网站00304

Springboot交流论坛网站 摘要 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了交流论坛网站的开发全过程。通过分析交流论坛网站管理的不足,创建了一个计算机管理交流论坛网站的方案。文章介绍了交流论坛…

elementui中table组件合并行(看就懂)

做一个动态合并的table表格, 如下图 1.首先定义需要合并的字段及合并后的对象 data(){return {mergeFields: [name, amount3],mergeObj: {}} }2.分配合并项函数, data为数据源 //获取合并序号getSpanArr(data []) {this.mergeFields.forEach(key > {// 用来记录合并行的起…

为什么我感觉 C 语言在 Linux 下执行效率比 Windows 快得多?

在开始前刚好我有一些资料,是我根据网友给的问题精心整理了一份「Linux的资料从专业入门到高级教程」, 点个关注在评论区回复“888”之后私信回复“888”,全部无偿共享给大家!!!Windows的终端或者叫控制台…

时间12小时和24时转换方法

24小时时间转为12小时制 function convertTo12Hour(time24h){let [hours, minutes] time24h.split(:);let modifier 上午;if (parseInt(hours, 10) > 12) {modifier 下午;hours (parseInt(hours, 10) - 12).toString();}if (parseInt(hours, 10) 12) {modifier 下午;}…

新手入门:无服务器函数和FaaS简介

无服务器(Serverless)架构的价值在于其成本效益、弹性和扩展性、简化的开发和部署流程、高可用性和可靠性以及使开发者能够专注于业务逻辑。通过自动化资源调配和按需计费,无服务器架构能够降低成本并适应流量变化,同时简化开发流…

《昇思25天学习打卡营第01天|sun65535》

开始 昇思25天打卡训练营,让我第一次了解了华为昇思的平台,之前也有自己本地使用4060训练了一些“小模型”,但是都是比较皮毛的知识,只是根据教程去搭建。很少了解到具体的过程。昇思25天打卡训练营给了一个比较全面的训练课程。…

大数据基础知识【大数据导论】

各位大佬好 ,这里是阿川的博客,祝您变得更强 个人主页:在线OJ的阿川 大佬的支持和鼓励,将是我成长路上最大的动力 阿川水平有限,如有错误,欢迎大佬指正 大数据基础知识前 必看 【大数据导论】—大数据序言…

Golang | Leetcode Golang题解之第206题反转链表

题目: 题解: func reverseList(head *ListNode) *ListNode {if head nil || head.Next nil {return head}newHead : reverseList(head.Next)head.Next.Next headhead.Next nilreturn newHead }

【1.1】动态规划求解不同的子序列

一、题目 给定一个字符串s和一个字符串t,计算在s的子序列中t出现的个数。 字符串的一个子序列是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置 所组成的新字符串。(例如,"ACE"是…

6.2、函数的定义

代码 #include <iostream> using namespace std; #include <string>//函数定义//语法&#xff1a;//返回值类型 函数名(参数列表) {函数体语句 return表达式}//加法函数 int add(int num1, int num2) {int sum num1 num2;return sum; } int main() {cout <&l…

聊聊Redis持久化策略RDB

写在文章开头 为避免服务器宕机着情况导致redis内存数据库数据丢失&#xff0c;redis默认出通过rdb保证可靠性&#xff0c;本文将从源码的角度带读者了解rdb读写时机和写入流程。 Hi&#xff0c;我是 sharkChili &#xff0c;是个不断在硬核技术上作死的 java coder &#xff…

刷代码随想录有感(124):动态规划——最长公共子序列

题干&#xff1a; 代码&#xff1a; class Solution { public:int findLength(vector<int>& nums1, vector<int>& nums2) {vector<vector<int>>dp(nums1.size() 1, vector<int>(nums2.size() 1, 0));int res 0;for(int i 1; i <…

数据集采样策略对模型性能的影响问题

数据集采样策略对模型性能的影响问题&#xff0c;需要具体代码示例 随着机器学习和深度学习的快速发展&#xff0c;数据集的质量和规模对于模型性能的影响变得越来越重要。在实际应用中&#xff0c;我们往往面临着数据集规模过大、样本类别不平衡、样本噪声等问题。这时&#…

lnternet 发展史

一&#xff0c;lnternet 发展史 ARPA net &#xff08;上世纪50年代二战结束&#xff09; 无线 战场指挥通信协议落后 TCP/IP 包交换 WEB (70年代 ) 80年代 90年代 二&#xff0c;互联网的典型应用&#xff1a; 96年到2008年 第一代技术…

AJAX的概述 ,同步和异步的区别 ,AJAX 的交互模型和传统交互模型的区别

一. AJAX的概述 1.1 什么是ajax 同步&#xff1a; 异步&#xff1a; 1.AJAX Asynchronous JavaScript and XML&#xff08;异步的 JavaScript 和 XML&#xff09;。 ​ 说明&#xff1a;异步&#xff1a;就是不同步。例如我们向后台发送请求&#xff0c;同步的方式是后台必…