当前位置: 首页 > news >正文

分库分表内容

  • 为什么需要分库
  • 为什么需要分表
  • 如何选择分表键
  • 分表之后非表键如何查询
  • 分表的策略都有哪些?如何选择
  • 热点数据倾斜问题
  • 分库之后,事务如何解决?(一般讲一两个即可)
  • 跨节点表Join关联问题
  • 分表之后order by,group by等聚合函数问题
  • 垂直分库、水平分库、垂直分表、水平分表区别
  • 分表要停服嘛?不停服怎么做

为什么需要分库

当我们系统业务增加,数据库就有可能出现性能的瓶颈,主要是针对于两个方面:
1、mysql单机磁盘容量会不够
2、数据库连接数是有限的,高并发场景下,大量请求数据库的话单机mysql是扛不住的。

为什么需要分表

分表是:当我们数据量非常大的时候,我们的查询和存储的性能就会遇到瓶颈,因为那个时候b+树的层高可能就高于3层,这个时候就需要考虑分表。
补充
单表行数超过500万行或者单表容量超过2GB,才推荐进行分库分表。

如何选择分表键

分表键,即用来分库/分表的字段,换种说法就是,你以哪个维度来分库分表的。比如你按用户ID分表、按时间分表、按地区分表,这些用户ID、时间、地区就是分表键。
一般数据库表拆分的原则,需要先找到业务的主题
比如我们的数据库表是一张企业客户信息表,就可以考虑用了客户号做为分表键。为什么考虑用客户号做分表键呢?
这是因为表是基于客户信息的,所以,需要将同一个客户信息的数据,落到一个表中,避免触发全表路由

分表之后非表键如何查询

假设一张用户表,根据userId做分表键,来分库分表。但是用户登录时,需要根据用户手机号来登陆。这时候,就需要通过手机号查询用户信息。而手机号是非分表键。
非分表键查询,一般有这几种方案:
1、遍历:最粗暴的方法,就是遍历所有的表,找出符合条件的手机号记录(不建议)
2、将用户信息冗余同步到ES,同步发送到ES,然后通过ES来查询(推荐)
3、还可以将非分表键可以解析出分表键出来,比如常见的,订单号生成时,可以包含客户号进去,通过订单号查询,就可以解析出客户号。但是这个场景除外,手机号似乎不适合冗余userId。

分表的策略都有哪些?如何选择

1、range范围策略划分表:即范围策略划分表。比如我们可以将表的主键order_id,按照从0300万的划分为一个表,300万600万划分到另外一个表。
有时候我们也可以按时间范围来划分,如不同年月的订单放到不同的表,它也是一种range的划分策略。
优点:Range范围分表,有利于扩容。
缺点:可能会有热点问题。因为订单id是一直在增大的,也就是说最近一段时间都是汇聚在一张表里面的。比如最近一个月的订单都在300万~600万之间,平时用户一般都查最近一个月的订单比较多,请求都打到order_1表啦。

2、hash取模策略,一般,我们会取哈希值,再做取余
优点:hash取模的方式,不会存在明显的热点问题。
缺点:如果未来某个时候,表数据量又到瓶颈了,需要扩容,就比较麻烦。所以一般建议提前规划好,一次性分够。(可以考虑一致性哈希)

3、一致性hash策略,如果用hash方式分表,前期规划不好,需要扩容二次分表,表的数量需要增加,所以hash值需要重新计算,这时候需要迁移数据了。应对这个扩容迁移的问题,可以使用一致性hash来解决。
缺点:节点比较少的时候容易造成因为数据分布不均匀而造成缓存热点的问题。解决:使用虚拟节点。

热点数据倾斜问题

如果我们根据时间范围分片,某电商公司11月搞营销活动,那么大部分的数据都落在11月份的表里面了,其他分片表可能很少被查询,即数据倾斜了,有热点数据问题了。
我们可以使用range范围 + hash哈希取模结合的分表策略,简单的做法就是:
在拆分库的时候,我们可以先用range范围方案,比如订单id在04000万的区间,划分为订单库1;id在4000万8000万的数据,划分到订单库2,将来要扩容时,id在8000万~1.2亿的数据,划分到订单库3。然后订单库内,再用hash取模的策略,把不同订单划分到不同的表。

采用数据分片均衡策略来解决分库分表的数据倾斜问题,通常可以通过以下几个方法来优化:

  1. 合理选择分片键(Sharding Key)
    • 选择一个能够均匀分布数据的字段作为分片键。通常选取具有高基数且更新频率适中的字段,比如用户ID、订单ID等,这样可以避免数据集中到某些分片中。
    • 要避免选择某些容易出现热点的数据,比如日期、地理位置等,避免部分分片的负载过重。
  2. 复合分片键
    • 在有些场景下,单一分片键可能导致数据倾斜,此时可以采用复合分片键,将两个或多个字段作为分片的依据。这样可以进一步分散数据,避免某些分片过于集中。
    • 比如,结合用户ID和时间戳作为分片键,既可以避免用户ID集中,也能在某些时间段内保持负载均衡。
  3. 分片策略设计
    • 范围分片:按范围进行分片,如按时间段、按地理区域分割数据。虽然这种方法简单,但容易发生数据倾斜,特别是某些时间段或地区的数据量大,可以通过合理的时间段划分来避免。
    • 哈希分片:对分片键进行哈希运算,均匀分配数据到各个分片。这种方式相对均衡,但对于查询时需要涉及多个分片的场景可能会带来性能问题。
    • 一致性哈希:通过一致性哈希来处理动态扩容问题,避免数据倾斜时影响整个系统的性能。通过一致性哈希算法,数据在分片之间的分配会更加均衡。
  4. 动态扩容和负载均衡
    • 随着数据量的增加,需要定期对分库分表进行扩容,保证数据均衡地分布在多个分片上。扩容时要确保数据重新分布时不会造成过多的迁移成本。
    • 可以通过数据迁移或者重新计算分片键的方式,将负载较高的分片的数据均匀地分布到新加入的分片中。
  5. 数据访问模式优化
    • 根据业务场景的需求,合理设计分片策略。例如,如果某些查询大多数基于某个字段(如用户ID)进行,那么就可以根据这个字段进行分片,从而减少跨分片查询的次数,降低数据倾斜的影响。
  6. 避免跨分片查询(避免全表扫描)
    • 在设计数据库结构时,应尽量避免跨分片的查询,尤其是涉及到大量数据的全表扫描。可以通过在应用层加上一些缓存策略,减少数据库的查询压力。
  7. 数据倾斜的监控与调优
    • 对系统进行实时监控,及时发现数据倾斜的风险,定期对分片负载进行分析,调整分片策略。比如,可以通过查询频率、响应时间等指标来判断是否存在数据倾斜问题,并在出现问题时进行调整。

总之,通过合理选择分片键、设计合适的分片策略、动态扩容与负载均衡等手段,可以有效地解决分库分表过程中的数据倾斜问题,提升系统的整体性能和可扩展性。

分库之后,事务如何解决?(一般讲一两个即可)

1.两阶段提交方案:这个是分布式事务中最简单的一种解决方案,主要将事务的提交分为两个阶段:准备阶段和提交执行阶段。
准备阶段,事务管理器向每个资源管理器发送准备消息,如果资源管理器的本地事务操作执行成功,则返回成功,如果执行失败,则返回失败。
提交执行阶段,如果事务管理器收到了所有资源管理器回复的成功消息,则向每个资源管理器发送提交消息,RM 根据 TM 的指令执行提交。如果事务管理器收到了任何一个资源管理器失败的消息,则向每个资源管理器发送回滚消息。资源管理器根据事务管理器的指令回滚本地事务操作,释放所有事务处理过程中使用的锁资源。

方案实现起来简单,成本较低,但是主要有以下缺点
单点问题:如果事务管理器出现故障,资源管理器将一直处于锁定状态。
性能问题:所有资源管理器在事务提交阶段处于同步阻塞状态,占用系统资源,一直到提交完成,才释放资源,容易导致性能瓶颈。
数据一致性问题:如果有的资源管理器收到提交的消息,有的没收到,那么会导致数据不一致问题。

2、本地消息表:它的核心思想就是将分布式事务拆分成本地事务进行处理。
基本实现思路,主要分为发送消息方,和消费消息方。
发送消息方:
1.需要有一个消息表,记录着消息状态相关信息。
2.业务数据和消息表在同一个数据库,即要保证它俩在同一个本地事务。
3.在本地事务中处理完业务数据和写消息表操作后,通过写消息到MQ消息队列。
4.消息会发到消息消费方,如果发送失败,即进行重试。

消息消费方:
1.处理消息队列中的消息,完成自己的业务逻辑。
2.此时如果本地事务处理成功,则表明已经处理成功了。
3.如果本地事务处理失败,那么就会重试执行。
4.如果是业务上面的失败,给消息生产方发送一个业务补偿消息,通知进行回滚等操作。

生产方和消费方定时扫描本地消息表,把还没处理完成的消息或者失败的消息再发送一遍。如果有靠谱的自动对账补账逻辑,这种方案还是非常实用的。
优点&缺点
该方案的优点是很好地解决了分布式事务问题,实现了最终一致性。缺点是消息表会耦合到业务系统中。
还有什么Saga事务、TCC补偿机制。
链接:
https://mp.weixin.qq.com/s?__biz=MzkyMzU5Mzk1NQ==&mid=2247505875&idx=1&sn=7401b329f2ed73118616ed3b4fd8f7d6&source=41#wechat_redirect

跨节点表Join关联问题

跨库Join的几种解决思路:
1、字段冗余:把需要关联的字段放入主表中,避免关联操作;比如订单表保存了卖家ID(sellerId),你把卖家名字sellerName也保存到订单表,这就不用去关联卖家表了。这是一种空间换时间的思想。
2、全局表:比如系统中所有模块都可能会依赖到的一些基础表(即全局表),在每个数据库中均保存一份。
3、数据抽象同步:比如A库中的a表和B库中的b表有关联,可以定时将指定的表做同步,将数据汇合聚集,生成新的表。一般可以借助ETL工具。
4、应用层代码组装:分开多次查询,调用不同模块服务,获取到数据后,代码层进行字段计算拼装。

分表之后order by,group by等聚合函数问题

跨节点的count,order by,group by以及聚合函数等问题,都是一类的问题,它们一般都需要基于全部数据集合进行计算。
1.可以分别在各个节点上得到结果后,再在应用程序端进行合并。
2.定期将数据备份到一个总的库中,然后在总的库里面使用范围查询。

垂直分库、水平分库、垂直分表、水平分表区别

水平分库:以字段为依据,按照一定策略(hash、range等),将一个库中的数据拆分到多个库中。
水平分表:以字段为依据,按照一定策略(hash、range等),将一个表中的数据拆分到多个表中。
垂直分库:以表为依据,按照业务归属不同,将不同的表拆分到不同的库中。
垂直分表:以字段为依据,按照字段的活跃性,将表中字段拆到不同的表(主表和扩展表)中。

分表要停服嘛?不停服怎么做

不用停服。不停服的时候,主要是采用双写的方式进行迁移:
1.增量的消息各自往新表和旧表写一份
2.将旧表的数据迁移到新的库中,迟早新表的数据都会追的上旧表(在某个节点上他们数据是同步的)
3.校验新表和老表的数据是否能够对的上。
4.对上之后开启双读,一部分流量走新表,一部分流量走老表,相当于灰度上线的过程。
5,逐步过渡到读流量全部切新表,停止老表的写入。
并且在迁移的过程还需要准备回滚机制,临时切换失败能恢复正常业务以及有修改的数据的相关程序。

相关文章:

  • 智能制造全场景数字化解决方案
  • 跨境电商每周信息差—5.26-5.30
  • 换行符在markdown格式时异常2
  • Ollama(1)知识点配置篇
  • 保险行业数字化应用解决方案
  • DiTAR: Diffusion Transformer Autoregressive Modeling for Speech Generation
  • 网易 - 灵犀办公文档
  • 【术语扫盲】BSP与MSP
  • React 事件处理与合成事件机制揭秘
  • 前端基础之《Vue(17)—路由集成》
  • 正点原子Z20 ZYNQ ​​​开发板​​发布!板载FMC LPC、LVDS LCD和WIFI蓝牙等接口,资料丰富!
  • LangChain表达式(LCEL)实操案例1
  • MathWorks无法注册,显示no healthy upstream(已解决)
  • PyQt6基础_QCharts绘制饼状图
  • 【nn.GroupNorm】
  • MQTT协议,EMQX部署,MQTTX安装学习
  • 苹果签名工具
  • 每天掌握一个Linux命令 - curl
  • 代码随想录算法训练营第60期第五十二天打卡
  • SpringBoot+Vue+微信小程序校园自助打印系统
  • 电子商务网站建设的主页/网络推广的具体方式
  • b2b商业网站建设/优质的seo快速排名优化
  • python做网站的好处/推广app赚钱项目
  • 做招聘网站都需要什么手续/免费制作网站
  • 誓做中国最大钓鱼网站/贵州二级站seo整站优化排名
  • 徐州市城乡建设局门户网站/网页关键词排名优化