这是一个可能对您有用的社区
一对一沟通/面试手册/简历优化/求职问题,欢迎加入“知识星球”。 以下是提供的部分信息:
这是一个开源项目,可能对您有用
国内Star是一个10万+的开源项目。 前端包括管理后端+微信小程序,后端支持单体和微服务架构。
功能涵盖RBAC权限、SaaS多租户、数据权限、商城、支付、工作流、大屏报表、微信公众号、CRM等功能:
【国内首批】支持JDK 21+ 3.2.2、JDK 8 + Boot 2.7.18双版本
没想到大家对分库分表这个话题这么感兴趣。 可能很多人的工作内容和业务量都比较小,很难获得这方面的技能。 这个系列在我心里已经筹划很久了,但是奈何寿什么也没说,什么也没做,所以就一直拖到现在。
其实网上有很多关于数据库分片和分片的文章,但是我还是坚持写这个系列,主要是自己学习研究,顺便分享一下。 不同的人从不同的角度对一门知识的理解是不同的。
网上好像资料很多,但是你要仔细挑选那些值得学习的。 很多时候在筛选的过程中,你低落的学习热情逐渐丧失。 抄袭、雷同的东西太多,而且知识点比较碎片化,原理的详细实践案例也很少。 对于新手来说,从头开始放弃是合适的,即使系统看了几篇之后就基本停产了。
我不喜欢堆积名词和概念。 熟悉我的朋友很容易发现,我的文章总是在讲解一波实际操作所遵循的原理。 学习技术原理一定要与实际操作相结合,否则不到三天半的时间你就会忘记一切。 它纯粹基于经验。
知识点梳理
上图是我的初步轮廓。 我根据官网文档补充了很多基础知识。 本系列将用数十篇文章详细梳理分库分表的基础理论,并提供一步一步的实用功能和5.X框架的解读。 源码,以及开发中容易遇到的坑,每篇文章都附有代码案例demo,旨在让新手也能看懂。 后续系列完成后,所有内容将会整理成PDF分享给大家,敬请期待!
废话不多说,进入正题吧~
不要急于开始使用实用的框架。 我们先回顾一下分库、分表的基本概念。 大多数技术术语晦涩难懂。 不要记住和理解最重要的事情。 当你戳破窗户纸时,你会发现其实就是这样。 。
基于Boot+Plus+Vue实现的后台管理系统+用户小程序,支持RBAC动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
分库分表是针对海量数据下单个库或表数据量过多导致数据库性能持续下降的问题演化而来的技术解决方案。
分库和分表是由两个独立的概念组成:分库和分表。 但通常分库和分表的操作是同时进行的,所以我们习惯性地将它们结合在一起,称为分库和分表。
通过一定的规则,将数据量较大的原始数据库拆分为多个独立的数据库,将数据量较大的原始表拆分为多个数据表,使单个数据库和表的性能达到最优结果(响应更快)以提高整体数据库性能。
基于+++++Vue实现的后台管理系统+用户小程序&支持RBAC动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
单机数据库的存储容量和连接数都是有限的,很容易成为系统的瓶颈。 当单表数据量超过百万时,我们还可以通过添加从库、优化索引来提升性能。
一旦数据量增长到1000万以上,无论数据库如何优化,很多操作的性能仍然会严重下降。 为了减轻数据库的负担,提高数据库响应速度,缩短查询时间,需要对数据库进行分表。
我们分配给数据库实例的磁盘容量是固定的,数据量持续大幅增长。 用不了多久,单台机器的容量就无法再承载如此多的数据了。 解决办法简单粗暴,加大容量!
单机容量可以随意扩展,但数据库连接数量有限。 高并发场景下,多个业务同时操作一个数据库。 很容易耗尽连接数,导致错误过多,导致后续数据库无法正常访问。
您可以检查最大连接数。
show variables like '%max_connections%'
将原有的单一数据库根据不同业务拆分为订单数据库、物流数据库、积分数据库等,不仅可以有效分担数据库读写压力,还可以提高系统容错能力。
做过报表业务的同学一定经历过SQL语句执行时间超过几十秒的场景。
数据库查询缓慢的原因有很多。 SQL会漏掉索引,就像扫描全表一样,使用函数计算。 这些都可以通过优化来解决,但是大量的数据是无法通过自我优化来解决的。 缓慢的根本原因是存储引擎。 聚集索引结构的B+树层级变高,磁盘IO增加,查询性能变慢。 具体原理大家可以自行查找。 这里不需要用太多篇幅来解释。
阿里巴巴的开发手册中有建议,如果单表行数超过500万或者单表容量超过2GB,建议分库分表。 然而,理想与实现之间始终存在着差距。 像阿里巴巴这样规模的公司已经不错了。 当然钱也可以这样用。 事实上,很多企业在单表数据达到千万级、数十亿级的时候,仍然不会选择分库分表。
技术群里的朋友经常会问,什么情况下会用到分库分表?
分库分表要解决现有海量数据访问的性能瓶颈,为不断增长的数据量提供架构的可预测性。
是否分库分表的关键指标是数据量。 我们以本网站的资源表为例。 系统初期运行时,每天只上传几十个资源。 这时候使用单库单表就足够了。 支持系统存储,数据量小,几乎不存在数据库性能瓶颈。
但有一天,一股神秘的流量开始涌入,系统每天产生的资源数据量激增至数十万甚至数百万。 此时资源表数据量达到千万级,查询响应变慢,数据库性能恶化。 瓶颈逐渐显现。
以数据库为例,当单表的数据量达到亿级别,而通过索引、SQL调优等传统优化策略对性能的提升仍然很小时,可以考虑分库建表。
既然存储海量数据会出现性能瓶颈,我们是否可以考虑用其他解决方案来替代呢? 比如高性能的非关系型数据库?
是的,但这取决于存储的数据类型!
如今,互联网上大多数公司的核心数据几乎都存储在关系数据库(等)中,因为它们具有相当的稳定性和可靠性、成熟的产品生态系统以及核心的交易功能。 其他存储工具没有,但评论、点赞等非核心数据还是可以考虑的。
分库分表的核心是将数据分片并相对均匀地路由到不同的库和表中,以及快速定位分片后的数据并整合检索结果。
分库分表可以从两个维度进行拆分:垂直()和水平(ntal)。 我们以经典的订单业务为例,看看如何拆分。
一般来说,垂直分库按照业务和功能维度进行拆分,不同的业务数据放在不同的数据库中,核心概念数据库是专用的。
根据业务类型分离数据,拆分到多个数据库。 订单、支付、会员、积分等表分别放在对应的订单库、支付库、会员库、积分库中。 禁止不同业务直接跨数据库连接。 获取彼此的业务数据必须通过API接口进行交互。 这也是微服务拆分的重要基础。
垂直分库
垂直分库很大程度上取决于业务的划分,但有时业务之间的划分并不是那么明确,例如:电商中订单数据的拆分,很多其他业务都依赖于订单数据,有时界限并不明确非常清楚。 分得好。
垂直分片将一个数据库的压力分散到多个数据库,提高了部分数据库性能,但并不能解决单表数据量过大带来的性能问题,需要通过后续分片来解决。
垂直分表是针对业务字段较多的大表进行的。 一般将业务全表中相对独立的字段或不常用的字段拆分为单独的数据表。 它是一种将大表拆分成小表的方法。 模型。
例如:订单表中有几十个字段,其中经常计算与订单金额相关的字段。 为了不影响订单表的性能,可以将与订单金额相关的字段分开,单独维护一个离子扩展表,这样每个表只需要存储原表的一些字段,通过订单号关联起来,然后将分割表路由到不同的库。

数据库以行为单位将数据加载到内存中。 拆分后,大部分核心表包含访问频率较高的字段,字段长度也较短,因此可以将更多数据加载到内存中,并减少磁盘IO。 提高索引查询的命中率,进一步提升数据库性能。
经过上述垂直分库、垂直分表后,仍然会存在单库、单表数据量过大的问题。 当我们的应用程序无法再执行细粒度的垂直分段时,仍然会存在单个数据库的读、写和存储性能瓶颈。 这时候就需要水平分库和水平分表的配合了。
数据库水平拆分就是将同一张表按照一定的规则拆分到不同的数据库中。 每个数据库可以位于不同的服务器上,实现水平扩展。 这是提高数据库性能的常用方法。
例如:两个数据库中有完全相同的表。 当访问订单时,我们可以通过订单号 mod 2(数据库实例的数量)来指定订单应该位于哪个数据库中。 操作。
这种方案往往可以解决单一数据库存储和性能瓶颈的问题,但由于同一张表分配在不同的数据库中,数据访问需要额外的路由工作,因此系统的复杂度也随之增加。
水平分表就是将一张数据量较大的表按照一定的规则分成同一个数据库中结构相同的多个表,每个表只存储原表的一部分数据。
例如:订单表有900万条数据,水平拆分后创建三张表,,,,每张表有300万条数据,等等。
水平分表虽然对表进行了拆分,但是子表仍然在同一个数据库实例中。 只解决单表数据量过大的问题,并没有将分表分散到不同的机器上。 竞争同一台物理机的CPU、内存、网络IO等。 为了进一步提高性能,需要将拆分表分散到不同的数据库中,以达到分布式的效果。
数据库分表之后就会出现一个问题。 一张表会出现在多个数据库中。 应该存储在哪个数据库的哪个表中?
我们在上面多次提到了某些规则。 其实这个规则就是一种路由算法,决定一条数据应该存储在哪个数据库的哪个表中。
常见的有模算法、范围限制算法、范围+模算法、预定义算法等。
键字段取模(取散列结果hash(XXX) mod N的余数,N为数据库实例或子表的数量)是最常见的路由方式。
以订单表为例,首先对数据库进行从0到N-1的编号,然后对订单表中的订单号字段进行取模hash() mod N,得到余数i。 i=0 存储第一个存储体,i=1 存储第二个存储体,i=2 存储第三个存储体,依此类推。
相同的订单数据会落在同一个数据库和表中。 查询时,使用相同的规则,以订单号作为查询条件,可以快速定位到数据。
实现简单,数据分布比较均匀,请求不易全部命中同一个数据库。
取模算法对于集群的扩展支持不是很友好。 集群中有N个数据库。 Hash() mod N。当某台机器宕机后,本应落入数据库的请求无法处理。 这时,它就下降了。 删除的实例将被踢出集群。
这时机器数减少算法改变hash() mod N-1,相同的用户数据落在不同的数据库中。 当机器恢复后,作为查询用户数据的条件的用户数据将会减少。
范围限制算法按某些范围字段(例如时间或 ID 区域)进行划分。
用户表分为三个表:1~、1000~、2000~,依此类推。 按日期范围划分也是如此。
为了避免热数据的问题,我们可以优化 算法
这次我们首先使用范围算法来定义每个库的用户表只存储数据。 第一个库存储从1~开始的数据,第二个库存储1000~,第三个库存储2000~,以此类推。
然后,每个库将用户表拆分为 、 、 等,并对这些对执行模路由到相应的表。
有效避免了数据分布不均匀的问题,数据库的水平扩展也简单。 您可以直接添加实例,无需迁移历史数据。
地理位置分片实际上是一个更大的范围,按照城市或者地区来划分。 例如,华东和华北的数据放在不同的分片库和分表中。
预定义的算法提前清楚地知道分库和分表的数量,可以直接将某些类型的数据路由到指定的库或表,查询时也是如此。
了解了上面的分库分表的拆分方式后,我们不难发现,与拆分之前的单库单表相比,系统的数据存储架构已经演化得变得非常复杂。 我们来看几个有代表性的问题,比如:
分页、排序、联合查询这些看似平常但开发中经常用到的操作,在数据库分表后却变得非常麻烦。 查询分散在不同数据库的表中的数据,然后汇总并整合所有结果提供给用户。
例如:我们要查询11月和12月的订单数据。 如果两个月的数据分散到不同的数据库实例中,我们需要查询两个数据库相关的数据。 对数据进行合并、排序、分页的过程繁琐、复杂。
数据库分表后,由于表分布在不同数据库中,必然会出现跨库事务问题。 以后会分别使用阿里巴巴和XA协议来实现分布式事务,比较一下各自的优缺点。
数据库分表后,数据库表的主键ID已经没有什么业务意义了,因为无法标识一条唯一的记录。 例如,多个表的主键ID都会从1开始,并且会重复。 这时候我们就需要主动分配一个记录An ID。 这个全局唯一的ID称为分布式ID。 颁发此 ID 的系统通常称为号码颁发者。
对多个数据库和数据库中大量分片表的高效管理是非常有必要的,因为当像淘宝这样的大厂商推出大促销时,订单表可能会被拆分成数千张表。 如果没有高效的管理方案,手动建表和排查问题是很可怕的。
分库分表架构实现后,首要的问题是如何平滑迁移历史数据、增量数据和全量数据迁移。 这又是一个麻烦的事情,后面会详细讨论。
分库分表架构主要有两种模式:客户端模式和代理模式。
该模式意味着分库分表的逻辑由您的系统应用程序控制。 应用程序会将拆分后的SQL直接连接到多个数据库进行操作,然后在本地进行数据的合并、汇总等操作。
代理模式将应用程序与数据库隔离。 业务方的应用程序不再需要直接连接数据库,而是连接代理服务。 代理服务实现该协议。 对于业务方来说,代理服务就是数据库。 它将SQL分发到特定的数据库执行并返回结果。 该服务有分库分表的配置,分库表会根据配置自动创建。
模式和方式如何选择? 我们可以从以下几个方面做一个简单的比较。
在性能方面,该模式表现稍好一些。 直接连接执行命令; 代理服务扩展了整个执行环节,应用程序->代理服务->,这可能会造成一些性能损失,但是两者的区别并不是很大。 。
模型的开发和使用通常需要引入jar; 代理模式需要构建单独的服务,有一定的维护成本。 既然是服务,就必须考虑高可用性,毕竟应用程序的所有SQL都要通过它来转发。
分库和分表一般依赖基础设施团队的Jar包。 一旦有版本升级或者bug修改,所有申请的项目都必须进行相应的升级。 小规模的团队,服务少,升级少,问题不大。 如果大公司的服务规模较大,涉及多个部门,那么一次升级的成本会比较高;
该模式升级优势明显。 如需发布新功能或修复Bug,只需重新部署代理服务集群即可。 业务方无意识,但发布过程中必须保证服务的可用性。
由于该模式嵌入在应用程序中,应用程序集群部署不方便统一处理; 该模式在SQL限流、读写权限控制、监控、报警等服务管理方面更加优雅。
本文主要回顾一下分库分表的一些基本概念,以便大家在后续的实践中能够更好的理解。 内容中很多概念都是简单提及,没有详细阐述。
欢迎加入我的知识星球,全面提升你的技术能力。
如需加入,请“长按”或“扫描”下面的二维码:
的内容包括:实际项目实践、面试招聘、源码分析、学习路线。
文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)