一、背景公司基于业务发展以及战略部署 , 需要实现在多个数据中心单元化部署 , 一方面可以实现多数据中心容灾 , 另外可以提升用户请求访问速度 。需要保证多数据中心容灾或者实现用户就近访问的话 , 需要各个数据中心拥有一致的全量数据 , 如果真正实现用户就近读写 , 也就是实现真正的业务异地多活 , 数据同步是异地多活的基础 , 这就需要多数据中心间数据能够双向同步 。
二、原生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 , 跨数据中心同步场景下 , 网络环境复杂 , 断线的频率和时长可能比同机房更频繁和更长;同时 , 跨数据中心同步数据也是为了机房级故障容灾 , 所以要求能够支持更长时间的断点续传 , 无限增大内存复制缓冲区大小显然不是一个好主意 。
下面来看看我们支持redis跨数据中心同步的优化工作 。
三、redis节点改造为了支持异地多活场景 , 我们对原生redis代码进行了优化改造 , 主要包括以下几个方面:
1、对RESP协议进行扩展为了支持更高效的断点续传 , 以及为了解决数据回环问题 , 我们在redis主节点中对每条需要同步给从节点的命令(大部分为写命令)增加了id , 并且扩展了RESP协议 , 在每条相关命令的头部增加了形如#{id}rn形式的协议 。
本地业务客户端写入的数据依然遵循原生RESP协议 , 主节点执行完命令后 , 同步到从节点的写命令在同步前会进行协议扩展 , 增加头部id协议;非本地业务客户端(即来自其他数据中心同步)写入的数据均使用扩展的RESP协议 。
2、写命令实时写日志为了支持更长时间的断点续传 , 容忍长时间的机房级故障 , 本地业务客户端写入的写命令在进行协议扩展后 , 会顺序写入日志文件 , 同时生成对应的索引文件;为了减少日志文件大小 , 以及提高通过日志文件断点续传的效率 , 来自其他数据中心同步过来的数据不写入日志文件中 。
推荐阅读
- 致敬科技工作者|合意的翡翠如何挑选!
- 京东账号注销! 京东帐号怎么注销?
- 白条怎么开通白条?如何开通京东白条
- |宇宙职业选手:蓝星新科技,未来人族的命运!
- 美术馆|科技何以承载艺术?
- 光芒|不帅不能打职业?京东369谈因长相被VG开除,回家呆1年才走出阴霾
- 唐嫣|唐嫣直播仅200观众!脸部浮肿整容过度,网友:都是科技与狠活
- 朝阳区 病例 轨迹?北京东城区疑似病例
- 秋高气爽去露营?这些黑科技装备别错过!
- 头发丝为啥比脚趾甲老得快 鞋带为啥老开?趣科技解谜题