原生 Redis 跨数据中心双向同步优化实践
一、背景
公司基于业务发展以及战略部署,需要实现在多个数据中心单元化部署,一方面可以实现多数据中心容灾,另外可以提升用户请求访问速度。需要保证多数据中心容灾或者实现用户就近访问的话,需要各个数据中心拥有一致的全量数据,如果真正实现用户就近读写,也就是实现真正的业务异地多活,数据同步是异地多活的基础,这就需要多数据中心间数据能够双向同步。
二、原生 redis 遇到的问题
1、不支持双主同步
原生 redis 并没有提供跨机房的主主同步机制,仅支持主从同步;如果仅利用 redis 的主从数据同步机制,只能将主节点与从节点部署在不同的机房。当主节点所在机房出现故障时,从节点可以升级为主节点,应用可以持续对外提供服务。但这种模式下,若要写数据,则只能通过主节点写,异地机房无法实现就近写入,所以不能做到真正的异地多活,只能做到备份容灾。而且机房故障切换时,需要运维手动介入。
因此,想要实现主主同步机制,需要同步工具模拟从节点方式,将本地机房中数据同步到其他机房,其他机房亦如此。同时,使用同步工具实现跨数据中心数据同步,会遇到以下一些问题。
(1)数据回环
数据回环的意思是,A 机房就近写入的数据,通过同步工具同步到 B 机房后,然后又通过 B 机房同步工具同步回 A 机房了。所以在同步的过程中需要识别本地就近写入的数据还是其他数据中心同步过来的数据,只有本地就近写入的数据需要同步到其他数据中心。
(2)幂等性
同步过程中的命令可能因断点续传等原因导致重复同步了,此时需要保证同一命令多次执行保证幂等。
(3)多写冲突
以双写冲突为例,如下图所示:
DC1 写入 set a 1,同时 DC2 写入 set a 2,当这两条命令通过同步工具同步到对方机房时,导致最终 DC1 中保存的 a 为 2,DC2 中保存的 a 为 1,也就是说两个机房最终数据不一致。
2、断点续传
针对瞬时的断开重连、从节点重启等场景,redis 为了提高该场景下的主从同步效率,在主节点中增加了环形复制缓冲区,主节点往从节点写数据的同时也往复制缓冲区中也写入一份数据,当从节点断开重连时,则只需要通过复制缓冲区把断开期间新增的增量数据发送给从节点即可,避免了全量同步,提升了这些场景下的同步效率。
但是,该内存复制缓冲区一般来说不会太大,生产目前默认设置为 64M,跨数据中心同步场景下,网络环境复杂,断线的频率和时长可能比同机房更频繁和更长;同时,跨数据中心同步数据也是