二次扩容的问题和方案
扩容的问题
在ShardingSphere中间件的分库分表
方案中,Hash
取模和Range
占了绝大多数。
如果业务发展非常快,可能在初次分库分表
后过不了多久就要考虑开始扩容了。例如,原来只分了4个库,但是现在要在原来的基础上再分4个,变成8个库。
当采用
Datetime Range(日期时间范围)
进行分库分表
时,一般不会有扩容问题,因为时间天然就是有序且易分割的。例如按月划分的话,就很容易划分为12个库,保存每年相同月份的数据。当采用
Region Range(地区范围)
进行分库分表
时,需要对原有数据进行迁移。例如,如果之前按照华中
地区来划分的话,现在需要进一步细分为省份,那么就需要将所有的华中
数据再次拆分到各个对应的省份数据库中。

- 当采用
Hash
取模进行分库分表时,一般情况下,扩容后都会有一半的数据迁移到新数据库中。

解决方案
扩容的解决方案无非就是两种:停机维护
和在线升级
。
停机维护
指的是对外发布停机公告,然后在停机时间内完成系统的升级扩容。这种方式方便且安全,几乎没有什么后遗症,但最大的问题是要停止业务服务,这可能会给组织带来很大的损失。虽然停机维护
会稍显从容一点,但风险和压力一点也不小,它需要精确规划好每一步需要采取的行动。下面是典型的理想化的停机维护
过程。理想化的停机维护过程 通过自研的业务中间件配合RocketMQ,将准备扩容的数据库中的数据全部都读取出来,然后再通过ShardingSphere对全部数据进行再次进行
Hash
取模运算。这幅图中忽略了很多内容,例如,准备扩容的数据如何读取到RocketMQ?业务中间件是否需要采取集群模式运行?有没有分布式事务问题?重新分库分表后对原业务有无影响?如何保证每一条数据都被同步?万一扩容中出现意外导致失败,如何保障数据完整性?是全部重来还是有容错手段?......等等诸如此类的问题。
在线升级
指的是业务依旧照常进行,扩容升级同步进行。这种方式非常考验研发团队的整体能力和配合协调,可能一步搞错都会导致升级失败,最终也会给组织带来很大的损失,而且还可能会留有一些潜在的后遗症。例如,某条数据未做同步彻底,导致客户无法查询到对应订单等问题。至于
在线升级
则更复杂,其总体过程是这样的。新增6个库作为从库,这6个库中有3个是同步时备份用的。用它来保证业务的不中断。同时为每个数据表都添加一个
synctime
字段,这个字段需要由数据库自动更新。例如,它可以这样定义:synctime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
。设置三个从库 因为之前是按3取模来划分的数据库,所以尾数为
0
和尾数为3
的订单都在扩容前的ds0
库中。也就是说,如果按照6进行取模,那么ds0
会被分为ds0
和ds3
两个库,ds0
的数据要分一半到ds3
里面去,其他ds1
和ds2
的情况依此类推。但在新的分片算法(也就是按6取模)生效前,
ds0
和ds3
中的数据经过同步后,是完全一致的。修改业务代码,让它按照新的算法执行
分库分表
。除了读取(R)
操作,其他的创建(C)
、更新(U)
和删除(D)
操作都通过RocketMQ来完成,但是此时不要消费任何RocketMQ中的消息。另外,也就是虽然有操作,但只是把这些业务消息给存储
起来。为了保障业务不中断,还需要业务系统同时操作之前同步的
备份库
。此时业务系统重新发布并上线运行(设定一个时间点,例如2023-01-01 00:00:00
,后面需要它作为参照)。修改业务系统并存储 Create
、Update
和Delete
这三类操作关闭主从同步,切换到真正的业务数据库,同时让业务系统在指定的时间点开始消费之前在RocketMQ中存储的消息(注意消息积压问题,否则一上线就可能导致崩溃)。此时所有的数据都会按照设定的新规则执行
分库分表
。切换到真正的业务数据库并开始消费消息 因为执行新的
分库分表
规则后,表中的synctime
字段必然会自动更新,所以可以以此为依据,删除所有早于它的冗余数据。例如,尾号为
3
的订单现在仍然存在于ds0
中,可以通过SQL
语句(DELETD FROM t_order WHERE id % 6 = 3 AND synctime < '2023-01-01 00:00:00'
)删除它。同样的道理,可以用这种方法删除ds3
中的冗余数据。
经过以上步骤,基本上大头就搞定了。
停机维护
和在线升级
这两种方式并非绝对的,因为停机维护
中可能会有部分服务仍然对外提供服务,然后在线升级。而在线升级
中也可能会有某些集群中的服务执行轮换停机。
而且上面的方案也基本是一个纯粹理想的简化版,实际上执行起来,一定会涉及到若干业务集群、若干内外系统交互、若干团队协作,是停机维护
还是在线升级
,是全部一起还是轮换进行,是灰度发布还是蓝绿发布,都是需要仔细斟酌和考量的。
总之,这种分库分表
的扩容工作绝不是哪一个或哪几个人可以独立搞定的,面对这种程度的复杂度和挑战性,除了发挥团队的力量外,个人无能为力。
感谢支持
更多内容,请移步《超级个体》。