原生Redis跨数据中心双向同步优化实践( 二 )


为了减少全量同步的次数,我们对redis同步流程进行改造,当部分同步中无法使用环形复制缓冲区完成同步时,增加先尝试使用日志rlog进行同步,如果同步成功,则同步完日志中数据后即可进行增量同步,否则需要先进行全量同步 。
四、rLog日志设计分为索引文件与日志文件,均采用顺序写的方式 , 提高性能 , 经测试与原生redis开启aof持久化性能一致;但是rlog会定期删除 , 原生redis为了防止aof文件无限膨胀 , 会定期通过子进程执行aof文件重写 , 这个对主节点性能比较大 , 所以实质上rlog对redis的性能相对于aof会更小 。
索引文件和日志文件文件名均为文件中保存的第一条命令的id 。
索引文件与日志文件均先写内存缓冲区,然后批量写入操作系统缓冲区 , 并每秒定期刷新操作系统缓冲区真正落入磁盘文件中 。相比较于aof文件缓冲区 , 我们对rlog缓冲区进行了预分配优化,达到提升性能目的 。
1、索引文件格式索引文件格式如下所示,每条命令对应的索引数据包含三部分:

原生Redis跨数据中心双向同步优化实践

文章插图
  • pos:该条命令第一个字节在对应的日志文件中相对于该日志文件起始位置的偏移
  • len:该条命令的长度
  • offset:该条命令第一个字节在主节点复制缓冲区中累积的偏移
2、日志文件拆分为了防止单个文件无限膨胀,redis在写文件时会定期对文件进行拆分,拆分依据两个维度,分别是文件大小和时间 。
默认拆分阈值分别为,当日志文件大小达到128M或者每隔一小时同时并且日志条目数大于10w时,写新的日志文件和索引文件 。
在每次循环处理中,当内存缓冲区的数据全部写入文件时,判断是否满足日志文件拆分条件,如果满足,加上一个日志文件拆分标志,下一次循环处理中,将内存缓冲区数据写入文件之前,先关闭当前的索引文件和日志,同时新建索引文件和日志文件 。
3、日志文件删除为了防止日志文件数量无限增长并且消耗磁盘存储空间,以及由于未做日志重写、通过过多的文件进行断点续传效率低下、意义不大,所以redis定期对日志文件和相应的索引文件进行删除 。
默认日志文件最多保留一天,redis定期删除一天以前的日志文件和索引文件,也就是最多容忍一天时间的机房级故障,否则需要进行机房间数据全量同步 。
在断点续传时,如果需要从日志文件中同步数据,在同步开始前会临时禁止日志文件删除逻辑,待同步完成后恢复正常 , 避免出现在同步的数据被删除的情况 。
五、redis数据同步1、断点续传【原生Redis跨数据中心双向同步优化实践】如前所述,为了容忍更长时间的机房级故障,提高跨数据中心容灾能力,提升机房间故障恢复效率 , 我们对redis同步流程进行改造,当部分同步中无法使用环形复制缓冲区完成同步时,增加先尝试使用日志rlog进行同步,流程图如下所示:
原生Redis跨数据中心双向同步优化实践

文章插图
首先,同步工具连接上主节点后 , 除了发送认证外,需要先通过replconf capa命令告知主节点具备通过rlog断点续传的能力 。
  1. 从节点先发送psync runId offset,如果是第一次启动,则先发送psync ? -1,主节点会返回一个runId和offset
  2. 如果能够通过复制缓冲区同步,主节点给从节点返回 +CONTINUE runId
  3. 如果不能够通过复制缓冲区同步,主节点给从节点返回 +LPSYNC
  4. 如果从节点收到+CONTINUE , 则继续接收增量数据即可,并继续更新offset和命令id
  5. 如果从节点收到+LPSYNC,则从节点继续给主节点发送 LPSYNC runId id
  6. 主节点收到LPSYNC命令后,如果能够通过rlog继续同步数据,则给从节点发送 +LCONTINUE runId;
  7. 从节点收到+LCONTINUE后,可以把offset设置为LONG_LONG_MIN,或者后续数据不更新offset;继续接收通过rlog同步的增量数据即可;
  8. 通过rlog同步的增量数据传输完毕后,主节点会给从节点发送 lcommit offset命令;
  9. 从节点在解析数据的过程中 , 收到lcommit命令时,更新本地offset,后续的增量数据继续增加offset , 同时lcommit命令无需同步到对端(通过id<0识别即可,所有id<0的命令均无需同步到对端)

    推荐阅读