分库分表 *

目录 #

分库分表 #

垂直切分 & 水平切分 [4] #

  • 垂直切分

    • 垂直分库 不同的业务使用不同的数据库. eg.订单库和促销活动库
    • 垂直分表 根据一张表中的字段,将一张表划分为两张表
  • 水平切分

    • 水平分表 将表中的某一列作为切分的条件,按照某种规则(Range 或 Hash 取模)来 切分为更小的表
    • 水平分库分表 水平切换的表分布到不同机器的库中
切分方式 数据量 访问特点 适用场景
单库单表 较小 xxx 小规模业务
表分区 较大 热点数据比较集中 数据量大、历史访问少
单库多表 较大 访问热点数据分散,所有数据都会访问 数据量较大
多库多表 极大 并发量高、海量数据 高并发、大数据量

分片原则的总结 [3] #

  1. 尽可能不要使用分片,优先考虑单表优化。[规避]
  2. 如果必须使用分片,分片数量应该尽量少,均匀分布在多个数据节点上。
  3. 分片规则应提前规划选择,考虑数据增长模式、访问模式、关联性和扩容问题。
  4. 避免在一个事务中跨越多个分片。 [规避]
  5. 查询条件要优化,避免使用 “SELECT *” 的方式,尽量避免返回大量结果集,并为频繁使用的查询语句建立索引。
  6. 通过数据冗余和表分区等方式降低跨库 joins 的可能性。 [规避]
  7. 对于有时间特征的数据表,采用时间范围分片,当前活跃数据采用短跨度分片,历史数据采用长跨度分片。
  8. 分片的选择应该取决于最频繁的查询 SQL 的条件,避免不带 where 语句的查询 SQL。

问题&解决方案 #

分库分表带来的问题 [1] #

  • 事务性问题
    • 方案一:尽可能保证一个事务所操作的表分布在一个库中 [规避]
    • 方案二:业务层引入分布式事务组件,如事务性消息、TCC、Seata等
  • 主键唯一性问题
    • 方案一:设置自增步长,采用等差数列递增
    • 方案二:采用全局统一ID生成机制,如UUID、雪花算法、数据库号段等方式
  • 跨库多表join问题
    • 建议尽可能避免表join操作,可以采用多次查询业务层进行数据组装 [规避]
    • 冗余表或冗余字段来优化跨库 JOIN 查询 [规避] [4]
  • 跨库聚合查询问题 [5]
    • 方案一:赛道赛马机制,每次从N个库表中查询出TOP N数据,然后在业务层代码中进行聚合合并操作 [全局视野法]
    • 方案二:将经常使用到groupby、orderby字段存储到一个单一库表中,先到单一表中查询出相应数据,然后根据查询到的主键ID,到分库分表中查询详情进行返回 [二次查询法]
  • 跨节点分页查询问题 [5] 跨节点分页查询问题是指在分库分表的环境下,通过某些非分库分表字段进行查询时,可能需要跨多个库或表进行查询,这会带来性能问题。解决这个问题的一种方法是使用两套数据,一套是基于分库分表的用户查询数据,另一套是基于Elasticsearch或Solr的订单数据,主要用于运营人员进行分页查询。 为了不影响订单业务性能,可以使用异步消息来实现Elasticsearch或Solr订单数据的新增和修改。 [gpt 总结] [4]
  • 扩容问题 [4] 一旦动态增加表了,就会涉及到数据迁移问题 在最开始设计表数据量时,尽量使用 2 的倍数来设置表数量。当需要扩容时,也 同样按照 2 的倍数来扩容,这样可以减少数据的迁移量。

ShardingSphere-分布式事务 [2] #

LOCAL XA BASE
业务改造 需要 seata server
一致性 不支持 支持 最终一致
隔离性 不支持 支持 业务方保证
并发性能 无影响 严重衰退 略微衰退
适合场景 业务方处理不一致 短事务 & 低并发 长事务 & 高并发

参考 #

  1. 一文读懂数据库分库分表
  2. ShardingSphere-分布式事务
  3. MySQL 大表优化方案(长文)
  4. 《36 | 什么时候需要分表分库?》
  5. {% post_link ‘dbShardingPaging’ %} self