@[toc]
分库分表解决方案和数据库分片中常见的问题及其解决方案
1、分库分表形式
水平分库
建立结构一样的库,根据分库方案划分数据到不同库
水平分表
建立多个表,根据分表方案划分数据到不同表
垂直分库
根据业务模块,把一组表划分为一个库
垂直分表
根据字段的活跃性,把字段组拆分到不同的表中
2、分库分表解决方案
分库分表工具(轻量级)
1、sharding-sphere :jar 包,前身是 sharding-jdbc (当当)
2、TSharding : 蘑菇街的中间件
分库分表工具(重量级)
1、Mycat : 中间件产品,基于开源的 cobar 开发
2、TDDL Smart Client : jar 包,Taobao Distribute Data Layer
3、Atlas : 奇虎 360
4、alibaba.cobar : 阿里 B2B 部门开发
5、Oceanus : 58 同城的数据库中间件
6、OneProxy : 支付宝首席架构师楼方鑫开发
7、vitess : 谷歌开发的数据库中间件
分表规则
1、Hash
2、Range
3、分库分表中存在的问题
1、事务问题
方案一:使用分布式事务
优点:交由数据库管理,简单有效
缺点:性能代价高,特别是shard越来越多时
方案二:由应用程序和数据库共同控制
原理:将一个跨多个数据库的分布式事务分拆成多个仅处 于单个数据库上面的小事务,并通过应用程序来总控 各个小事务。
优点:性能上有优势
缺点:需要应用程序在事务控制上做灵活设计。如果使用 了spring的事务管理,改动起来会面临一定的困难。
2、跨节点的 Join 问题
只要是进行切分,跨节点 Join 的问题是不可避免的。但是良好的设计和切分却可以减少此类情况的发生。解决这一问题的普遍做法是分两次查询实现。
在第一次查询的结果集中找出关联数据的id,根据这些id发起第二次请求得到关联数据。
3、跨节点聚合问题
比如 count、order by、group by 等聚合函数问题,方案是各节点完成计算后,交由业务层进行合并
多节点的查询可以是并行的,因此大多数情况他比单一大表快很多,但是如果结果集很大,可能会导致内存消耗过高
4、数据迁移,容量规划,扩容等问题
这些问题目前都没有特别好的解决方案,每个方案都或多或少的有一些问题存在,因此这个问题的解决难度其实挺高的
5、ID 问题
数据被切分后,就不能依赖数据库的自增 ID 进行赋值,另外 ID 还需要承担携带路由信息的功能,以降低查询难度
一种方案是使用 UUID ,但是 UUID 比较长会占用较多的存储空间,另外一方面,UUID 对索引不友好
一种方案是通过维护一个 ID 签发表来对 ID 进行签发,但是这会导致插入需要增加一次查询,且该表容易成为性能瓶颈存在单点故障问题
一种方案是使用雪花算法进行 ID 的下发
6、跨分片的排序问题
如果排序字段是分片字段,则可以直接使用分片排序
如果排序字段不是分片字段,则需要先在分片上进行排序,然后到业务系统进行合并,然后再排序
7、分库策略、分库数量
这个需要根据实际的业务场景,进行合理的分配,否则容易给后期造成很大的问题
4、总结
1、分库分表,首先要知道数据库的瓶颈在哪里,才能给出合理的方案
2、对于 Key 的选择很重要,要考虑数据拆分均匀,也要考虑非 partition key 的查询
3、满足要求的情况下,划分规则越简单越好