分库分表

发布于 2022年 05月 19日 13:11

分库分表中间件

比较常见的包括:cobar、TDDL、sharding-jdbc、atlas、mycat

cobar:阿里b2b团队开发和开源的,属于proxy层方案。不支持读写分离、存储过程、跨库join和分页等操作。

TDDL:淘宝团队开发的,属于client层方案。不支持join、多表查询等语法,就是基本的crud语法是ok,但是支持读写分离。使用不多,需要依赖淘宝的diamond配置管理系统。

atals:360开源的,属于proxy层方案,以前是有一些公司在用的,但是确实有一个很大的问题就是社区不维护。

sharding-jdbc:当当开源,属于client层方案。支持分库分表、读写分离、分布式id生成、柔性事务(最大努力送达型事务、TCC事务)。社区比较活跃

mycat:基于cobar改造,属于proxy层方案,支持的功能非常完善,社区活跃。

 

优劣分析:sharding-jdbc和mycat

sharding-jdbc这种client层方案的优点在于不用部署,运维成本低,但是如果遇到升级啥的需要各个系统都需要升级再发布

mycat这种proxy层方案的方案对于各个项目是透明的,属于一个中间件,但是运维成本高。

 

分库分表hash算法

我可以对id取模3 分3个库,然后取模4 分四个表。

11%3 = 2

11%4 = 3

第二个数据库第三个表。

按时间

2022年一个数据库 2023年一个数据库

优缺点:

hash方法:可以平均分担请求压力。扩容比较难

按时间扩容比较方便,缺点是大部分的请求都访问最新的数据库。

落地实现:

可以从一开始就考虑到扩容,搞4个数据库,每个库4个表,实际上数据库服务器就一个,里面放4个数据库。

对于DBA来说,扩容的时候直接开新的数据库服务器,然后把数据库导入过去就好了。我们修改一下数据库连接配置就好,原来的数据库hash规则不需要修改。

 

迁移方案:

方案1:双写方案

系统修改数据对原来的表和分库分表中间件一起操作,同时增加一个服务负责把原来的表数据迁移到分库分表上去。一般表规范是有updatetime的,迁移的时候比较一下这个updatetime,免得旧数据覆盖新数据。迁移完成后去比较原来库和新的分库分表数据是否一样,程序跑个几天。

方案2:我们可以借鉴redis主从复制方案

我们知道redis主从复制的时候,后台生成一个rdb快照。然后这个时刻之后的操作都是对数据的副本进行的。rdb完成之后副本数据覆盖原始数据。

我们也可以这样,不过代码实现起来有点复杂。

创建一张零时表,查询的时候操作原来的表的临时表去查询。零时表会多一个isdelete 字段,如果本来就是逻辑删除的,那不管。

插入数据的时候插入进临时表。

修改数据的时候,查出原来数据,然后修改要修改的字段,然后插入临时表。

删除数据的时候,如果是逻辑删除,和修改其实一样,如果是真删除,那把数据查出来,并且在isdelete上打个标签表示这个数据删除了。

查询的时候从原来表查了之后,要判断是否在临时表被删除。而且要把零时表的数据也一起处理,相同id的数据使用临时表的数据,如果分页查询可能出现一点问题。

原来表数据全部拷贝到分库分表数据后,停机把零时表数据更新到分库分表上。

方案3:对旧库和新库操作

如果插入数据,直接在新库上插入

如果修改数据,把数据从旧数据删除,插入新数据库。

如果删除数据,对新库和旧库一起删

查询数据,从旧库查询,查询不到从新库查询。旧库有的话,插入新库,然后返回。

分页查询:我要查第5页数据,旧数据库前5页,新数据库每个表前5页,数据到内存后合在一起再找第5页

方案2,方案3不可取,原来的增删改查代码是大量的,修改逻辑工作量极大。

 

分库分表id生成策略:

1.数据库主键自增

弄一张表,主键自增,负责生成主键。麻烦,性能低。

2.时间戳

用时间做主键,可能会重复。A数据库和B数据库时间一样的时候生成的ID一样。

3.uuid

id虽然唯一,可是没有顺序。

4.snowflake雪花算法

64位二进制,第一位0 ,41位表示时间,5位机房id,5位机器id,12位表示当前这一毫秒生成了第几个id。

把64位二进制转10进制就是雪花算法id了。只能32个机房 32个机器。不然会报错。或者可以对机器码取模,这样的话就会有重复的id。

推荐文章