Redis集群slot迁移改造实践

news2024/11/23 18:52:10

作者:来自 vivo 互联网存储团队- Xu Xingbao

Redis 集群经常需要进行在线水平扩缩容,实际操作过程中发现迁移期间服务时延剧烈抖动,业务侧感知明显,为了应对以上问题对原生 Redis 集群 slot 迁移功能进行优化改造。

一、背景介绍

Redis 集群服务在互联网公司被广泛使用,众所周知服务集群化可以突破单节点的能力瓶颈,带来规模、可用性、扩展性等多方面的收益。在实际使用 Redis 集群的过程中,发现在进行涉及集群数据迁移的水平扩缩容操作时,业务侧多次反馈 Redis 请求的时延升高问题,甚至发生过扩容操作导致集群节点下线的可用性故障,并进一步引发迁移流程中断、节点间数据脑裂等一系列严重影响,给运维同事带来极大困扰,严重影响线上服务的稳定。

二、问题分析

2.1 原生迁移介绍

Redis 集群功能采用无中心架构设计,集群中各个节点都维护各自视角的集群拓扑并保存自有的分片数据,集群节点间通过 gossip 协议进行信息协调和变更通知。具体来说 Redis 集群数据管理上采用虚拟哈希槽分区机制,将数据的键通过哈希函数映射到 0~16383 整数槽内,此处的槽位在 Redis 集群设计中被称为 slot。这样实际上每一个节点只需要负责维护一部分 slot 所映射的键值数据,slot 就成为 Redis 集群管理数据的基本单位,集群扩缩容本质上就是 slot 信息和 slot 对应数据数据在节点之间的转移。Redis 集群水平扩展的能力就是基于 slot 维度进行实现,具体流程如下图所示。

上图所示的迁移步骤中,步骤 1-2 是对待迁移 slot 进行状态标记,方便满足迁移过程中数据访问,步骤 3-4 是迁移的核心步骤,这两个步骤操作会在步骤 5 调度下持续不断进行,直到待迁移 slot 的键值数据完全迁移到了目标节点,步骤 6 会在数据转移完成后进行,主要是发起集群广播消息更新集群内节点 slot 拓扑。

由于正常的迁移时一个持续的处理过程,不可避免地会出现正在迁移 slot 数据分布于迁移两端地“分裂”状态,这种状态会随着 slot 迁移的流程进行而持续存在。为了保证迁移期间正在迁移的 slot 数据能够正常读写,Redis 集群实现了下图所示的一种 ask-move 机制,如果请求访问正在迁移的 slot 数据,请求首先会按照集群拓扑正常访问到迁移的源节点,如果在源节点查询到数据则正常处理响应请求;如果在源节点没有找到请求所需数据,则会给客户端回复 ASK {ip}:{port} 消息回包。

Redis 集群智能客户端收到该回包后会按照包内节点信息找到新节点重试命令,但是由于此时目标节点还没有迁移中 slot 的所属权,所以在重试具体命令之前智能客户端会首先向目的节点发送一个 asking 命令,以此保证接下来访问迁移中 slot 数据的请求能被接受处理。由于原生迁移时按照 key 粒度进行的,一个 key 的数据要不存在源节点,要不存在目的节点,所以 Redis 集群可以通过实现上述 ask-move 机制,保证迁移期间数据访问的一致性和完整性。

2.2 迁移问题分析

(1)时延分析
根据上述原生 Redis 集群迁移操作步骤的了解,可以总结出原生迁移功能按照 key 粒度进行的,即不断扫描源节点上正在迁移的 slot 数据并发送数据给目的节点,这是集群数据迁移的核心逻辑。微观来说迁移单个 key 数据对于服务端来说包含以下操作:

  • 序列化待迁移键值对数据;
  • 通过网络连接发送序列化的数据包;
  • 等待回复(目标端接收完包并加载成功才会返回);
  • 删除本地残留的副本,释放内存。

上述操作中涉及多个耗费线程处理时长的操作,首先序列化数据是非常耗费 CPU 时间的操作,如果遇到待迁移 key 比较大线程占用时长也会随之恶化,这对于单工作线程的 Redis 服务来说是不可接受的,进一步地网络发送数据到目标节点时会同步等待结果返回,而迁移目的端又会在进行数据反序列化和入库操作后才会向源节点进行结果返回。需要注意的是在迁移期间会不断循环进行以上步骤的操作,而且这些步骤是在工作线程上连续处理的,期间无法对正常请求进行处理,所以此处就会导致服务响应时延持续突刺,这一点可以通过 slowlog 的监控数据得到验证,迁移期间会在 slowlog 抓取到大量的 migrate 和 restore 命令。

(2)ask-move 开销
正常情况下每个正在迁移的 slot 数据都会一段时间内存在数据分布在迁移的两端的情况,迁移期间该 slot 数据访问请求可以通过 ask-move 机制来保证数据一致性,但是不难看出这样的机制会导致单个请求网络访问次数出现成倍的增加,对客户端也存在一定的开销压力。另外,对于可能存在的用户采用 Lua 或者 Pipline 这种需要对单个 slot 内多 key 连续访问的场景,目前大部分集群智能客户端支持有限,可能会遇到迁移期间相关请求不能正常执行的报错。另外需要说明的是,由于 ask-move 机制的只在迁移两端的主节点上能触发,所以迁移期间从节点是不能保证数据请求结果一致性的,这对于采用读写分离方式访问集群数据的用户也非常不友好。

(3)拓扑变更开销
为了降低迁移期间数据 ask-move 的机制对请求的影响,正常情况下原生迁移每次只会操作一个 slot 迁移,这就导致对每一个迁移完成的 slot 都会触发集群内节点进行一次拓扑更新,而每次集群拓扑的更新都会触发正在执行指令的业务客户端几乎同时发送请求寻求更新集群拓扑,拓扑刷新请求结果计算开销高、结果集大,大大增加了节点的处理开销,也会造成正常服务请求时延的突刺,尤其对于连接数较大、集群节点多的集群,集中的拓扑刷新请求很容易造成节点计算资源紧张和网络拥塞,容易触发出各种服务异常告警。

(4)迁移无高可用
原生的迁移的 slot 标记状态只存在于迁移双端的主节点,其对应的从节点并不知道迁移状态,这也就导致一旦在迁移期间发生节点的 failover,迁移流程将会中断和出现 slot 状态残留,也将进一步导致迁移 slot 数据的访问请求无法正常触发 ask-move 机制而发生异常。例如迁移源节点异常,那么其 slave 节点 failover 上线,由于新主节点并不能同步到迁移状态信息,那么对于迁移中 slot 的请求就不能触发 ask 回复,如果是一个对已经迁移至目标节点的数据的写请求,新主节点会直接在本节点新增 key,导致数据出现脑裂,类似地如果处理的是已经迁移数据的读取请求也无法保证返回正确结果。

三、优化方案

3.1 优化方向思考

通过原生数据迁移机制分析,可以发现由于迁移操作涉及大量的同步阻塞操作会长时间占用工作线程,以及频繁的拓扑刷新操作,会导致请求时延不断出现上升。那么是否可以考虑将阻塞工作线程的同步操作改造成为异步线程处理呢?这样改造有非常大的风险,因为原生迁移之所以能够保证迁移期间数据访问的正确性,正是这些同步接口进行了一致性保证,如果改为异步操作将需要引入并发控制,还要考虑迁移数据请求与 slave 节点的同步协调问题,此方案也无法解决拓扑变动开销问题。所以 vivo 自研 Redis 放弃了原生按照 key 粒度进行迁移的逻辑,结合线上真实扩容需求,采用了类似主从同步的数据迁移逻辑,将迁移目标节点伪装成迁移源节点的从节点,通过主从协议来转移数据。

3.2 功能实现原理

Redis 主从同步机制是指在 Redis 主节点(Master)和从节点(Slave)之间进行数据同步和复制的过程,主从同步机制可以提高 Redis 集群的可用性,避免单点故障和数据丢失等问题。Redis 目前主从同步有全量同步和部分同步两种方式,从节点发送同步位点给主节点,如果是首次同步则需要走全量同步逻辑,主节点通过发送 RDB 基础数据文件和传播增量命令方式将数据同步给从节点;如果不是首次同步,主节点则会通过从节点同步请求中的位点等信息判断是否满足增量同步条件,优先进行增量同步以控制同步开销。由于主节点在同步期间也在持续处理新的命令请求,所以从节点对主节点的数据同步是一个动态追齐的过程,正常情况下,主节点会持续发送写命令给从节点。

基于同步机制,我们设计实现了一套如下图所示的 Redis 集群数据迁移的功能。迁移数据逻辑主要走的全量同步逻辑,迁移数据和同步数据最大的区别在于,正常情况下需要迁移的是源节点部分 slot 数据,目标节点并不需要复制源节点的全量数据,完全复用同步机制会产生不必要的开销,需要对主从同步逻辑进行修改适配。为了解决该问题,我们对相关逻辑做了一些针对性的改造。首先在同步命令交互上,针对迁移场景增加了迁移节点间 slot 信息交互,从而让迁移源节点获知需要迁移哪些 slot 到哪个节点。另外,我们还对 RDB 文件文件结构按照 slot 顺序进行了调整改造,并且将各个 slot 数据的文件起始偏移量数据作为元数据记录到 RDB 文件尾部固定位置,这样在进行迁移操作的 RDB 传输步骤时就可以方便地索引到 RDB 文件中目标 slot 数据片段。

3.3 改造效果分析

(1)时延影响小
对于 slot 迁移操作而言,主要涉及迁移源和目的两端的开销,对于基于主从同步机制实现的新 slot 迁移,其源节点主要开销在于生成 RDB 和传送网络包,正常对于请求时延影响不大。但是因为目的节点需要对较大的 RDB 文件片段数据进行接收、加载,由于目的节点迁移时也需要对正常服务请求响应,此时不再能采用类似 slave 节点将所有数据收取完以后保存本地文件,然后进行阻塞式数据加载的方案,所以新 slot 迁移功能对迁移目的节点的数据加载流程进行了针对性改造,目的节点会按照接收到的网络包粒度将数据按照下图所示进行递进式加载,即 slot 迁移目标节点每接收完一个 RDB 数据网络包就会尝试加载,每次只加载本次网络包内包含的完整元素,这样复合类型数据就可以按照 field 粒度加载,从而降低多元素大 key 数据迁移对访问时延的剧烈影响。通过这样的设计保持原来单线程简洁架构的同时,有效地控制了时延影响,所有数据变更操作都保持在工作线程进行,不需要进行并发控制。通过以上改造,基本消除了迁移大 key 对迁移目的节点时延影响。

(2)数据访问稳定
新 slot 迁移操作期间,正在迁移的数据还是存储在源节点上没有变,请求继续在源节点上正常处理,用户侧的请求不会触发 ask-move 转发机制。这样用户就不需要担心读写分离会出现数据不一致现象,在进行事务、pipeline 等方式封装执行命令时也不会出现大量请求报错的问题。迁移动作一旦完成,残留在源端的已迁移 slot 数据将成为节点的残留数据,这部分数据不会再被访问,对上述残留数据的清理被设计在 serverCron 中逐步进行,这样每一次清理多少数据可以参数化控制,可以根据需要进行个性化设置,保证数据清理对正常服务请求影响完全可控。

(3)拓扑变更少
原生的迁移功能为了降低 ask-move 机制对正常服务请求的影响,每次仅会对一个 slot 进行数据迁移,迁移完了会立即发起拓扑变更通知来集群节点转换 slot 的属主,这就导致拓扑变化的次数随着迁移 slot 的数量增加而变多,客户端也会在每一次感知到拓扑变化后发送命令请求进行拓扑更新。更新拓扑信息的命令计算开销较大,如果多条查询拓扑的命令集中处理,就会导致节点资源的紧张。新的 slot 迁移按照节点进行数据同步,可以支持同时迁移源节点的多个 slot 甚至全部数据,最后可以通过一次拓扑变更转换多个 slot 的属主,大大降低了拓扑刷新的影响。

(4)支持高可用
集群的数据迁移是一个持续的过程,这个过程可能长达几个小时,期间服务可能发生各种异常情况。正常情况下的 Redis 集群具有 failover 机制,从节点可感知节点异常以代替旧主节点进行服务。新 slot 迁移功能为了应对这样的可用性问题,将 slot 迁移状态同步给从节点,这样迁移期间如果集群迁移节点发生 failover,其从节点就可以代替旧主节点继续推进数据迁移流程,保证了迁移流程的高可用能力,避免人工干预,大大简化运维操作复杂度。

四、功能测试对比

为了验证改造后迁移功能的效果,对比自研迁移和原生迁移对请求响应的影响,在三台同样配置物理机上部署了原生和自研两套相同拓扑的集群,选择后对 hash 数据类型的 100k 和 1MB 两种大小数据分别进行了迁移测试,每轮在节点间迁移内存用量 5G 左右的数据。测试主要目的是对比改造前后数转移对节点服务时延影响,所以在实际测试时没有对集群节点进行背景流量操作,节点的时延数据采用每秒钟 ping 10 次节点的方式进行采集,迁移期间源节点和目的节点的时延监控数据入下表所示(纵轴数值单位:ms)。

通过对比以上原生和自研集群 slot 迁移期间的时延监控数据,可以看出自研 slot 迁移功能迁移数据期间迁移两端节点的请求响应时延表现非常平稳,也可以表现出经过主从复制原理改造的 Redis 集群 slot 迁移功能具备的优势和价值。

五、总结和展望

原生 Redis 集群的扩缩容功能按照 key 粒度进行数据转移,较大的 key 会造成工作线程的长时间占用,进而引起正常服务请求时延飙高问题,甚至导致节点长时间无法回复心跳包而被判定下线的情况,存在稳定性风险。通过同步机制改造实现的新 slot 迁移功能,能显著降低数据迁移对用户访问时延的影响,提升线上 Redis 集群稳定性和运维效率,同时新的 slot 迁移功能还存在一些问题,例如新的迁移造成节点频繁的 bgsave 压力,迁移期间节点内存占用增加等问题,未来我们将围绕这些具体问题,继续不断优化总结。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2127960.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

乔迁新址,盛启新章!聚铭网络河北办事处盛大开业

2024年9月10日,金秋九月,阳光灿烂。在这样一个美好的日子里,聚铭网络河北办事处正式迎来了乔迁之喜并盛大开业。随着公司业务规模的快速扩张,原有的办公空间已经不足以支撑未来的增长,新址的启用不仅代表了我们迈出的一…

5V*0.5A低压降二极管芯片 CH213

概述 CH213是带限流功能的低压降理想二极管芯片。芯片内部集成了过流保护、短路保护、过温保护、电源极性保护等模块,额定5V*0.5A,支持5V电压下不超过1A电流的直流应用,在 VO输出端发生过流时可以限制电流从而保护供电系统,在输入…

Vue路由一(简介、分类、基本使用、注意事项)

目录 1. 简介2. 路由的分类3. 基本使用4. 注意事项 1. 简介 路由就是一组key:value的对应关系。vue可能是function或component多个路由,需要经过路由器管理 是为了实现SPA(single page web application)单页面应用。以前需要实现多个html,现在只需实现一…

零基础也能掌握!大模型训练指南

在这个信息爆炸的时代,人工智能技术正以前所未有的速度渗透到我们生活的方方面面。从智能手机上的语音助手到自动驾驶汽车,AI的应用无处不在。而在这些令人惊叹的技术背后,大语言模型(LLM)扮演着至关重要的角色。它们不…

Navicat On-Prem Server 2.0 | MySQL与MariaDB基础管理功能正式上云

近日,Navicat 发布了 Navicat On-Prem Server 2.0 的重大版本更新。这标志着这款自2021年首发的私有云团队协作解决方案迈入了一个崭新的阶段。此次2.0版本的飞跃性升级,核心聚焦于MySQL与MariaDB基础管理功能的全面革新与强化,赋予了用户的操…

当 PLC 遇见 “IT”

IT&OT 深度融合工控人加入PLC工业自动化精英社群 IT & OT integration 当今不断发展的工业自动化世界,在智能、高效和快速的系统和软件应用中,数据扮演着越来越重要的角色。传统的 IT 网络中,提供了丰富多彩的规范和协议&#xff0…

PHP即刻送达同城派送小程序系统

即刻送达,同城派送小程序系统让生活更便捷 🚀 瞬间连接,即刻送达的奇迹 你是否曾经因为等待快递而焦急万分?是否渴望有一种方式能让物品像魔法一样瞬间出现在你面前?现在,有了“即刻送达同城派送小程序系…

交易所站队“NEIRO”?MEME内战进行时

加密市场总有“狗”传奇。 日前,此前一度被称为新一代“狗狗币”的NEIRO合约被OKX 和 Binance先后上线,在交易所推动下,NEIRO迅速暴涨超6倍。而这一上线,也正式宣告分庭抗礼的竞品“Neiro”走向缓慢的消亡。 大小写MEME的最终结局…

快人一步迅为LPDDR5版本瑞芯微RK3588核心板升级了

性能强--iTOP-3588开发板采用瑞芯微RK3588处理器,是全新一代ALoT高端应用芯片,采用8nm LP制程,搭载八核64位CPU,四核Cortex-A76和四核Cortex-A55架构,主频高达2.4GHZ,8GB内存,32GB EMMC。四核心…

小白学大模型:四种文本解码策略

在大型语言模型(LLM)的迷人世界中,模型架构、数据处理和优化常常成为关注的焦点。但解码策略在文本生成中扮演着至关重要的角色,却经常被忽视。 在这篇文章中,我们将通过深入探讨贪婪搜索和束搜索的机制,以…

电机驱动开发之主控板

目录 1.主要器件选型2.原理图设计电源调理最小系统通讯接口显示器 3.PCB绘制4.打板验证5.总结 1.主要器件选型 器件参数理由MCUSTM32CBT6资源丰富价格低廉LDOASM1117(5V-3.3V)常见CANSIT1057T常见UARTType-C CH340使用常见Type-c线通讯即可屏幕ips TFT资…

sheng的学习笔记-AI-话题模型(topic model),LDA模型,Unigram Model,pLSA Model

AI目录:sheng的学习笔记-AI目录-CSDN博客 基础知识 什么是话题模型(topic model) 话题模型(topic model)是一族生成式有向图模型,主要用于处理离散型的数据(如文本集合)​,在信息检索、自然语言处理等领域有广泛应用…

【赵渝强老师】大数据主从架构的单点故障

大数据体系架构中的核心组件都是主从架构,即:存在一个主节点和多个从节点,从而组成一个分布式环境。下图为展示了大数据体系中主从架构的相关组件。   视频讲解如下: 大数据主从架构的单点故障 【赵渝强老师】大数据主从架构的…

【大模型专栏—入门篇】科研论文疑惑汇总

大模型专栏介绍 😊你好,我是小航,一个正在变秃、变强的文艺倾年。 🔔本文为大模型专栏子篇,大模型专栏将持续更新,主要讲解大模型从入门到实战打怪升级。如有兴趣,欢迎您的阅读。 &#x1f4…

【多线程】手把手带你学习定时器那些事

💐个人主页:初晴~ 📚相关专栏:多线程 / javaEE初阶 在软件开发中,有一些代码逻辑并不需要立马就被执行,可能需要等一段时间在执行。就好像我们会用闹钟来提醒我们过一段时间后要做某事一样,代码…

裸土检测算法、裸土检测算法样本标注,裸土覆盖检测算法

裸土检测算法主要用于环境保护、土地管理和农业等领域,通过图像识别技术来检测地表上的裸露土壤区域。这种技术对于土地退化监测、水土流失预防、农田管理等方面有着重要意义。以下是关于裸土检测算法的技术实现、应用场景及优势的详细介绍。 应用场景 裸土检测算法…

kafka原理剖析及实战演练

一、消息系统概述 一)消息系统按消息发送模型分类 1、peer-to-peer(单播) 特点: 一般基于pull或polling接收消息发送对队列中的消息被一个而且仅仅一个接收者所接收,即使有多个接收者在同一队列中侦听同一消息即支持异…

JVM - GC垃圾回收

文章目录 目录 文章目录 1. 自动垃圾回收 1.1 垃圾回收区域 2. 方法区回收 3. 堆回收 3.1 对象已死? 3.1.1 引用计数算法 3.1.2 可达性分析算法 3.1.3 再谈引用 强引用 软引用 弱引用 虚引用 3.2 垃圾收集算法 3.2.1 分代收集理论 3.2.2 垃圾回收算…

Android U 多任务启动分屏——Launcher流程(下分屏 更新中)

前文 Android U 多任务启动分屏——Launcher流程(上分屏) 最近任务onClick事件的监听 在最近任务中每个任务都是一个TaskView,对TaskView操作,就是每个任务的操作。 代码路径:packages/apps/Launcher3/quickstep/…

安装Anaconda(过程)

Anaconda是一个开源的Python发行版本,用来管理Python相关的包,安装Anaconda可以很方便的切换不同的环境,使用不同的深度学习框架开发项目,本文将详细介绍Anaconda的安装。 一、安装 1、安装方式 官网:“https://www.…