当前位置: 首页 > 科技观察

如何实现水平分库的平滑扩容

时间:2023-03-20 00:06:27 科技观察

在上一篇关于DynamoDB的介绍中,有一个特别的亮点,就是可以不停地动态扩容。这对于我们常用的分库分表方案来说有很大的优势。分库分表的扩容很头疼。如果在db层使用consistenthashing或者支持中间价,成本太高,否则只能通过停机维护来处理,对高可用有影响。有没有一种解决方案可以在不降低可用性的情况下快速扩展?本篇就来谈谈分库分表的扩容方案,供大家一起探讨。1.数据库水平分片的扩展为了提高db的并发能力,常见的解决方案是对数据进行分片,也就是常说的分库分表。这就需要前期对数据规划有一个预期,以便预分配足够的库来处理。比如目前规划了三个数据库,剩下的分片是根据uid进行的,那么在每个数据库上的划分规则如下:上面我们可以看到,可以将数据平均分配到三个数据库中。但是,如果后续业务发展迅速,用户量大增,目前的容量不足以支撑,怎么办?需要横向扩展数据库,然后添加新的库进行分解。添加新库后,原来分库到三个库的数据可以分库到四个库。但是,由于分片规则的变化(uid%3变为uid%4),大部分数据无法分片。***在原数据库上,需要重新分配,需要迁移大量数据。比如之前uid1是通过uid1%3分配到A库上的,加入新库D后,算法改为uid1%4,此时可能分配到B库上。如果你之前看过《一致性哈希的原理与实践》,你会发现如果增加一个节点,大约90%的数据都需要迁移。这对DB同学来说还是比较有压力的,那么如何应对呢?一般来说,有几种方法。2.服务关闭和迁移是最常见的解决方案。大致流程如下:预估服务关闭时间,发布服务关闭公告,使用提前准备好的数据迁移工具遵循新的分片规则。迁移并修改分片规则以启动服务。我们看到这种方法是比较安全的。停止服务后,不写入任何数据,可以保证迁移工作的正常进行,不会出现一致性问题。唯一的问题是暂停服务和时间压力。停止服务会损害用户体验并降低服务器的可用性。迁移必须在指定时间内完成。如果失败,则需要选择另一天重新进行。同时增加了开发商的压力,容易发生重大事故。当数据量巨大时,迁移需要花费大量时间。还有其他方法可以改善吗?让我们看看以下两种解决方案。3.从数据库升级在线数据库。为了保持它的高可用,我们通常会为每个主库配备一个从库,在主库中读写,然后将主从同步到从库。如下,A、B为主库,A0、B0为从库。这时候需要扩容的时候,我们将A0和B0升级到新的主库节点,从而从2个分库变成4个分库。同时在上层的分片配置中,做映射。规则如下:uid%4=0和uid%4=2分别指向A和A0,即之前指向uid%2=0的数据,拆分为uid%4=0和uid%4=2uid%4=1anduid%4=3指向B和B0,也就是之前指向uid%2=1的数据,拆分为uid%4=1和uid%4=3,因为A和A0数据库有相同的数据,B和B0有相同的数据,所以此时不??需要做数据迁移。只需要更改分片配置,通过配置中心更新即可,无需重启。由于之前uid%2的数据分配在2个库中,此时分散在4个库中。由于旧数据仍然存在(uid%4=0,还有uid%4=2的一半数据),所以需要对冗余数据进行一次清理。而且这种清洗不会影响线上数据的一致性,而且可以随时随地进行。处理完成后,为了保证高可用,还有下一步的扩容需求。可以将一个从站重新分配给一个现有的主站。总结一下本方案的步骤如下:修改分片配置,做好新旧库的映射。同步配置,从库升级为主库,去除主从关系,清理冗余数据,为新的数据节点搭建新的从库。4、双写迁移和双写方案多用于在线数据库迁移。当然对于分库的扩容,也需要进行数据的迁移,所以也可以用来辅助分库的扩容。原理同上,拆分扩展,只是数据同步方式不同。1.增加新库写链接双写的核心原理是在需要扩容的数据库上增加一个新库,同时在现有分片上增加一个写链接,同时写入两份数据。因为新数据库中的数据是空的,数据的CRUD对其没有影响。在上层逻辑层,旧数据库中的数据仍然是主要的。2.新旧数据库数据迁移使用工具将旧数据库的数据迁移到新数据库。这时候可以选择同步拆分数据(1/2)来同步,也可以完全同步。一般推荐全同步,最后做查数据的时候就好办了。3、数据校验按照理想的环境,数据迁移之后,因为是双写操作,所以两边的数据是一致的,尤其是insert和update,一致性非常高。但是在真实环境中,会出现网络延迟等情况,不适合删除。比如A库删除数据a时,数据a正在迁移,还没有写入C库。这时,C库的删除操作已经执行完毕,C库就会多出一份数据。此时,就要做好数据校验工作。可以多次进行数据校验,直到数据几乎相同。尽量以旧数据库中的数据为准。4.分片配置修改数据同步后,可以重新处理新库的分片映射,或者和旧库拆分一样。uid%2=0beforeu变成uid%4=0anduid%4=2的uid%2=1变成uid%4=1anduid%4=3。参考:《数据库秒级平滑扩容架构方案》