首页 > 首页 > 数据库 > 非关系型数据库 > Redis > 【原创】缩减大数据量Redis集群主从数据同步时间的解决方案
2024
09-05

【原创】缩减大数据量Redis集群主从数据同步时间的解决方案

问题描述

随着公司业务量得大幅增长,还有某些业务系统将redis当成数据库使用,不设置key过期时间,导致现在生产环境的一些redis集群容量越来越大,最大的集群目前已经使用1T+的内存空间,集群中单节点数据大小更是达到40G+,如此大的数据量对日常的运维工作产生以下影响:

  • 单节点数据量过大,在主从节点异常切换后,整个数据同步和加载数据时间过长,节点在加载数据时是阻塞状态,可能会导致从节点还没完成数据同步完成,就会引发超时,导致再次触发主从全量同步,进而形成死循环,主从数据永远无法完成同步
  • 正常的redis集群架构中,单台服务器上可能部署了集群中多个master节点,如果这台服务器异常宕机,或者我们需要关闭这台服务器进行维护时候(例如:更换硬盘、内存等),就会触发几个master节点同时的主从切换,数据同步等操作,如果按照正常参数配置和同步流程,非常耗费时间。
  • 根据实际生产环境经验,一个服务器上面有8个节点,3主4从,每个节点40G+内存,SSD硬盘,如果按照正常主从数据同步流程,完全恢复这台服务器上的redis服务正常需要大概约2.5~3小时,如果在此期间,集群剩余的服务器节点再出现问题,则整个集群将无法使用,直接影响业务正常运行。

同步原理

下面是我画的当redis集群维护或者宕机时,单台服务器上一个master节点从启动到服务恢复正常的流程图(备注:redis master节点关闭后再启动角色会变为slave)

【原创】缩减大数据量Redis集群主从数据同步时间的解决方案 - 第1张  | 架构迷

说明:

在上面流程图中,耗时最多的步骤是如下几个,下面耗时是根据生产真实维护日志记录,一个服务器上面有8个节点,3主4从,每个节点40G+内存,RDB持久化文件大小18G,采用SSD硬盘

“2、加载本地RDB持久化数据到内存”------>耗时约37分钟

“4、fork内存数据持久化到本地磁盘” ------>耗时约11分钟

“5、发送全量RDB持久化数据”+“7、接收持久化数据写入本地磁盘”------>耗时约6分钟

“8、清空内存数据”------>耗时约8分钟

“9、加载新的RDB数据到内存”------>耗时约30分钟

“11、发送增量缓存数据”+“12、加载增量缓存数据到内存”------>耗时需要根据操作期间,业务数据写入缓存空间实际情况计算

以上只是原主节点启动后的操作耗时,数据同步完成后,还需要手动主从切换,切换后还会触发流程图上3~12步骤,总体服务恢复正常时间为2.5~3小时左右

解决方案

   根据对redis主从同步原理以及相关配置参数研究,针对上面耗时的操作步骤,找到了以下解决办法:

“2、加载本地RDB持久化数据到内存------>耗时省约37分钟

从节点启动时候,会加载本地的RDB文件到内存中,我们可以在启动服务前,将节点的RDB文件迁移到其他目录,节点启动的时候就不会再加载RDB文件,因为按照主从复制同步原理,即使加载数据到内存,后面也会清空内存数据,重新加载主节点同步过来的全量数据,所以此步骤可以人为干预,节省时间

“4、fork内存数据持久化到本地磁盘”------>b+c 耗时省约11分钟

“5、发送全量RDB持久化数据”+“7、接收持久化数据写入本地磁盘”

以上几个个步骤可以通过在线修改redis相关配置参数“repl-diskless-sync no”,此参数默认为关闭状态,将其修改为yes开启,其作用是master节点在内存中直接创建 RDB,然后通过socket网络直接发送给 slave节点,不会再自己本地落地磁盘了,但是 slave节点会将持久化数据写入本地磁盘,配置生效后,操作时我们会再redis主节点日志中看到下面得提示:

【原创】缩减大数据量Redis集群主从数据同步时间的解决方案 - 第2张  | 架构迷

“8、清空内存数据””------>耗时省约8分钟

因为本地启动时候就没有加载RDB数据,所以没有此步操作

“9、加载新的RDB数据到内存”

以上属于正常加载流程,无法加快

“11、发送增量缓存数据”+“12、加载增量缓存数据到内存”

需要在线修改加大以下三个参数的值,否则从节点加载数据离线时间过长会导致全量数据同步死循环,就永远不会触发增量同步

“repl-backlog-size 60”-------> "repl-backlog-size 600”

“repl-backlog-size100m”-------> “repl-backlog-size 500m”

“client-output-buffer-limit slave 256mb 64mb 60”-------> “client-output-buffer-limit slave 2048mb 1024mb 600”

”14、新从节点会按照3~12步骤再次执行“------>耗时省约11分钟

此步骤中还会涉及4、fork内存数据持久化到本地磁盘”,因为在之前设置了无盘复制参数,所以此处也会跳过

总上所述,按照上面说的集群架构和节点数据量,理论上整个集群操作到恢复正常过程可以节省约1小时左右时间

方案效果

公司某个服务使用了redis作为数据存储,目前是公司最大的redis集群之一,总共有1T+数据,12主12从,单节点内存使用40G+

 近期由于服务器内存不足,需要逐台关闭服务器添加内存,再恢复集群服务,下面是应用本方案前后,操作redis集群的时间对比,需要说明的是

两次操作的服务器上的节点数量、节点内存大小都是一致的。

次数操作时间总耗时是否采用新方案
第一次操作21:46 ~ 00:242小时44分钟
第二次操作21:25 ~ 11:101小时40分钟

总结:由上面记录可以看出,总体操作时间节省了约1小时,跟方案中计算的时间基本吻合

附录说明

1、方案中描述的Redis集群恢复的时间强依赖于硬盘类型,SSD硬盘和普通硬盘的恢复时间差距很大,所以一般我们都建议redis服务器采用SSD硬盘

2、”repl-diskless-sync“此参数目前在3.2 ~ 6.0版本默认是关闭的,7.0版本是默认开启,原因是功能尚处于测试阶段,可以使用,但是官方不建议生产环境长期开启,另外无盘复制需要依赖良好的网络环境,网络经常抖动的环境可能会造成数据丢失,另外传输过程中会造成过多内存和网络带宽的消耗。此方案中之所以可以使用,依赖于以下两点:

  • 业务流量低峰阶段,数据同步在同网段,且服务器内存充足,资源使用在可接受范围,总体评估对业务影响较小
  • 操作者熟悉主从复制原理,懂得如何校验主从数据,且可以保证即使同步中不在本地创建RDB文件,也可以手动触发保留最新的,不会丢失数据

3、“repl-backlog-size 60”、“repl-backlog-size100m”、“client-output-buffer-limit slave 256mb 64mb 60”关于此三个参数值为什么不在生产中就直接配置过大,原因是日常的主从同步,切换等相关操作也会涉及到以上几个参数,参数值过大会影响系统内存的使用,进而影响日常业务的稳定,正常情况下不会按照方案中设置过大,方案中的操作完成后,还需要在线还原参数值。

4、针对大容量redis集群,尤其是单节点存储数据量过大的集群,原则上,我们是需要不断的优化扩容架构,确保每个节点的内存使用上限不超过20G,这样再结合本方案在故障或者维护时候,可以加速业务的恢复速度,缺点在于不断扩容架构的总体成本较高。

5、另外本身redis是作为缓使用的,有些业务当成数据库使用,此为不合理的使用情况,但是由于历史原因,业务改造成本过高,本人目前也在寻找研究一种非内存型,无需内存和硬盘来回加载切换,可以替代redis的开源软件。

最后编辑:
作者:摘星怪
这个作者貌似有点懒,什么都没有留下。

留下一个回复

你的email不会被公开。