扩容问题的来源
在项目初期,我们部署了三个数据库 A、B、C,此时数据库的规模可以满足我们的业务需求。为了将数据做到平均分配,我们在 Service 服务层使用 uid%3 进行取模分片,从而将数据平均分配到三个数据库中,哈希流程如图所示:
后期随着用户量的增加,用户产生的数据信息被源源不断的添加到数据库中,最终达到数据库的最佳存储容量。
如果此时继续向数据库中新增数据,会导致数据库的 增删改查等操作变慢,进而影响整个服务的响应速度。
这时,我们需要增加新的节点,对数据库进行水平扩容,那么加入新的数据库 D 后,数据库的规模由原来的 3 个变为 4 个,哈希流程如图所示:
此时由于分片规则发生了变化(uid%3 变为 uid%4),导致大部分的数据,无法命中原有的数据,需要重新进行分配,要做大量的数据迁移处理。
举例:
如果之前 uid=3,取模 3%3=0, 是分配在 A 库上;新加入 D 库后, 现在uid=3 取模 3%4=3,变成分配在 D 库上,但是读取的话D库上肯定不存在uid为3的数据,必须把旧数据都迁移正确才行。
以上就是数据库扩容问题的来源!
哈希流程和数据迁移如下图
哈希法扩容的总结:
新增节点时会有大量的旧数据需要迁移,迁移过程中可能需停服,等全部数据迁移完成后才能哈希到正确的数据库。但这样会面临大量的数据压力,并且对服务造成极大的不稳定性
方案一(停服迁移再开服方案 )
1. 发布停服公告
为了进行数据的重新拆分,在停止服务之前,我们需要提前通知用户,比如:我们的服务会在 yyyy-MM-dd 进行升级,给您带来的不便敬请谅解
2. 停服
关闭 Service,不再对数据库进行增删改查等操作
3. 增加新的数据库节点
购买或建立新的数据库,建好数据库和表
4. 旧数据迁移
将旧库中的全部数据按照新的哈希算法,将数据重新分配,更新到正确的数据库
5. 数据校验
开发一个程序对旧库和新库中的数据进行校验,比对,确保重分配是正确的
6. 更改数据库配置和哈希算法
Service配置中添加新库连接地址,账号密码等;修改 Service 层的算法,也就是将原来的 uid%3 变为 uid%4
7. 开服
重启 Service 服务
方案一总结
停止服务之后, 能够保证迁移工作的正常进行。 但是服务停止,伤害用户体验, 而且造成了时间压力, 必须在指定的时间内完成迁移,且不能出错,每一步都要有回滚预案