【Redis 技术进阶之路】「原理分析系列开篇」高可用之 Master-Slave 主从架书的点制问题分析(分析旧版复制功能)

【专栏简介】
随着数据需求的迅猛增长,持久化和数据查询技术的重要性日益凸显。关系型数据库已不再是唯一选择,数据的处理方式正变得日益多样化。在众多新兴的解决方案与工具中,Redis 凭借其独特的优势脱颖而出。
【技术大纲】
为何 Redis 备受瞩目?原因在于其学习曲线平缓,短时间内便能对 Redis 有初步了解。同时,Redis 在处理特定问题时展现出卓越的通用性,专注于其擅长的领域。深入了解 Redis 后,您将能够明确哪些任务适合由 Redis 承担,哪些则不适宜。这一经验对开发人员来说是一笔宝贵的财富。

在这个专栏中,我们将专注于 Redis 的 6.2 版本进行深入分析和介绍。Redis 6.2 不仅是我个人特别偏爱的一个版本,而且在实际应用中也被广泛认为是稳定性和性能表现都相当出色的版本。
【专栏目标】
本专栏深入浅出地传授 Redis 的基础知识,旨在助力读者掌握其核心概念与技能。深入剖析了 Redis 的大多数功能以及全部多机功能的实现原理,详细展示了这些功能的核心数据结构和关键算法思想。读者将能够快速且有效地理解 Redis 的内部构造和运作机制,这些知识将助力读者更好地运用 Redis,提升其使用效率。
将聚焦于 Redis 的五大数据结构,深入剖析各种数据建模方法,并分享关键的管理细节与调试技巧。
【目标人群】
Redis 技术进阶之路专栏:目标人群与受众对象,对于希望深入了解 Redis 实现原理底层细节的人群。
1. Redis 爱好者与社区成员
Redis 技术有浓厚兴趣,经常参与社区讨论,希望深入研究 Redis 内部机制、性能优化和扩展性的读者。
2. 后端开发和系统架构师
在日常工作中经常使用 Redis 作为数据存储和缓存工具,他们在项目中需要利用 Redis 进行数据存储、缓存、消息队列等操作时,此专栏将为他们提供有力的技术支撑。
3. 计算机专业的本科生及研究生
对于学习计算机科学、软件工程、数据分析等相关专业的在校学生,以及对 Redis 技术感兴趣的教育工作者,此专栏可以作为他们的学习资料和教学参考。
无论是初学者还是资深专家,无论是从业者还是学生,只要对 Redis 技术感兴趣并希望深入了解其原理和实践,都是此专栏的目标人群和受众对象。
让我们携手踏上学习 Redis 的旅程,探索其无尽的可能性!
Redis 主从复制
在 Redis 架构中,用户拥有灵活的机制来配置数据复制,这一过程通过执行 SLAVEOF 命令或配置 slaveof 选项实现,旨在让一个 Redis 实例(我们称之为从服务器,slave)去同步并复制另一个 Redis 实例(即主服务器,master)的数据。

具体而言,SLAVEOF 命令的引入,为 Redis 集群管理提供了高度的动态性和灵活性。通过简单地执行这一命令并指定主服务器的地址和端口,从服务器便能立即开始复制过程,自动同步主服务器上的数据变更。
通过配置文件设置 slaveof 选项,用户可以在 Redis 实例启动时自动建立复制关系,无需手动干预,进一步简化了运维流程。
案例介绍
在设想的场景中,我们配置了两个 Redis 服务器实例,它们虽共处同一物理或逻辑隔离的环境中,却各自独立地监听不同的端口以提供服务:一个是遵循惯例的 Redis 默认端口 6379(对应地址 127.0.0.1:6379),另一个则是自定义的非标准端口 12345(对应地址 127.0.0.1:12345),以命令行工具 redis-cli 为例,发送命令至 127.0.0.1:12345 的示例命令如下:
在此配置中,我们设定了一个主从关系,其中原本监听于非标准端口 12345 的 Redis 服务器(地址 127.0.0.1:12345)被配置为从服务器,而监听于标准端口 6379 的 Redis 服务器(地址 127.0.0.1:6379)则相应地扮演了主服务器的角色。
主从数据一致性问题
在主从复制架构中,主服务器与从服务器之间的数据库通过持续的数据同步过程,确保了双方存储着完全一致的数据集合。这一现象在概念层面上被精确地定义为“数据库状态一致性”,简称则为“一致性”。
当我们向位于 127.0.0.1:6379 的主 Redis 服务器发送一个 SET 命令来设置键 msg 的值为"hello world",并成功接收到 OK 响应时,这标志着数据写入操作在主服务器上顺利完成。
紧接着,我们可以通过在主服务器上执行 GET msg 命令来验证该键的值,预期会返回"hello world"。
同样地,由于配置了 Redis 的主从复制机制,当主服务器上的数据发生变化时,这些变化会自动同步到从服务器上。
当我们转向 127.0.0.1:12345 的从服务器,并尝试通过 GET msg 命令获取 msg 键的值时,也应当能够接收到相同的"hello world"结果,这证明了数据在主从服务器之间保持了一致性。
随后在主服务器上执行 DEL msg 命令来删除 msg 键,并确认操作成功(通过(integer)1 的返回值),那么该键及其关联的数据将从主服务器的数据库中移除。
为了验证这一点,我们可以使用 EXISTS msg 命令来检查 msg 键是否还存在,预期会收到(integer)0 的响应,表示该键已被删除。
由于主从复制的特性,从服务器也会实时或近乎实时地反映主服务器上的数据变化。因此,当我们对从服务器执行相同的 EXISTS msg 命令时,同样会收到(integer)0 的响应,确认了 msg 键在从服务器上也已被删除。
分析旧版复制功能
Redis 的复制机制精妙地融合了同步(synchronization)与命令传播(command propagation)两大核心步骤,旨在确保主从服务器间数据库状态的高度一致性与实时性。
同步操作:此阶段是建立主从关系的基石,它旨在将从服务器的数据库快照迅速更新至与主服务器当前数据库状态完全匹配的水平。同步过程负责将从服务器的数据环境“对齐”到主服务器的最新状态,为后续的数据一致性维护奠定坚实的基础。
命令传播操作:紧随同步阶段之后,命令传播机制扮演了关键角色。每当主服务器的数据库状态因任何操作(如数据新增、修改或删除)而发生变化,这些变更将以命令的形式自动传播至所有已连接的从服务器。
同步
当客户端向从服务器发起SLAVEOF
指令,旨在配置或更新从服务器以复制指定主服务器的状态时,从服务器会首先触发同步操作这一关键步骤。这一过程的核心在于,将从服务器的数据库当前状态全面且准确地更新至与主服务器当前数据库状态相一致的水平。
在从服务器对主服务器进行同步操作时,一个关键步骤是向主服务器发送一个正确的命令来启动这一过程,但值得注意的是,标准 Redis 中使用的命令是SYNC
。
注意,在较新版本中可能已被
REPLCONF slaveof
或类似的自动重连机制所取代,且SYNC
命令的具体行为也可能有所调整,特别是引入了PSYNC
以支持部分同步。

发起同步请求:从服务器首先向主服务器发送
SYNC
命令,正式请求启动数据同步过程。主服务器准备快照与缓冲区:接收到
SYNC
命令后,主服务器会立即执行BGSAVE
命令,在后台异步生成一个 RDB(Redis Database)快照文件。同时,主服务器会启动一个缓冲区,用于记录从SYNC
命令接收到 BGSAVE 命令执行完毕期间内,所有对数据库进行修改的写命令。发送 RDB 快照并更新从服务器状态:一旦
BGSAVE
完成,主服务器会将新生成的 RDB 文件发送给从服务器。从服务器接收并加载这个 RDB 文件,从而将其数据库状态快速更新至与主服务器执行BGSAVE
时相同的数据库状态。命令传播与状态同步:在 RDB 文件传输并加载完成后,主服务器将开始将之前记录在缓冲区中的所有写命令发送给从服务器。从服务器逐一执行这些写命令,逐步将其数据库状态更新至与主服务器当前数据库状态完全一致,从而完成整个同步过程。

在同步操作圆满结束后,主服务器与从服务器的数据库会实现一个瞬间的完全一致状态,这一同步的达成标志着数据复制过程的阶段性胜利。

然而,值得注意的是,这种一致性状态是动态且相对的,它并非一种永恒的、静态的保持。每当主服务器接收到来自客户端的写操作指令并执行时,其数据库内容便可能经历变动,这一变动随即打破了先前主从服务器间的一致状态,引发了两端数据库内容的不一致现象。
命令传播
设想主服务器与从服务器刚刚成功完成了数据同步流程,它们的数据库内容宛如镜像般完全一致,存储着相同的数据快照。但随后,随着业务活动的进行,主服务器接收到了一条来自客户端的写请求,比如更新某个数据项的值或添加新的记录。主服务器响应这一请求并相应地修改了其数据库中的信息。

由于这一修改是实时且直接作用于主服务器的,而从服务器在默认情况下可能并未立即得知这一变更(除非有特定的同步机制被触发),因此,在这一时刻起,主服务器与从服务器之间的数据一致性便遭到了破坏,它们的数据库内容不再保持完全一致的状态。
主服务器向从服务器发送命令
为了恢复主从服务器之间的一致状态,主服务器会采取命令传播机制:即将导致数据不一致的写命令(即那些仅在主服务器上执行过的写操作)转发给从服务器执行。这一过程确保了从服务器能够“追赶”上主服务器的状态变化,通过执行相同的写命令来更新其数据库内容。

以先前所述示例为鉴,当主服务器执行了DEL k3
命令并因此导致主从服务器间出现数据不一致时,主服务器会主动将这一相同的DEL k3
命令发送给从服务器。从服务器接收到命令后,会立即执行,从而删除其数据库中相应的键k3
。随着这一操作的完成,主从服务器间的数据状态得以重新对齐,两者再次达到一致,此时双方的数据库都不再包含键k3
的记录。
SYNC 命令是一个非常耗费资源的操作
在每次触发 SYNC 命令时,主从服务器间的数据同步过程涉及一系列关键步骤,这些步骤显著影响系统资源的使用与性能表现:
主服务器资源密集型操作:首先,主服务器需执行 BGSAVE 命令,该命令异步地在后台生成 RDB 快照文件。此过程对主服务器构成了显著负担,因为它会大量占用 CPU 计算资源、内存空间以及磁盘 I/O 能力,进而影响服务器的整体响应速度和并发处理能力。
网络资源消耗:随后,主服务器需将庞大的 RDB 文件通过网络发送给从服务器。这一过程不仅消耗了主从服务器间的大量网络带宽资源,还可能因为数据传输的延迟和流量高峰,对主服务器的命令响应速度产生不利影响,延长了客户端请求的等待时间。
从服务器阻塞处理:在从服务器端,接收并加载 RDB 文件同样是一个资源密集且耗时的过程。在加载期间,从服务器将处于阻塞状态,无法处理任何来自客户端的命令请求,这可能导致从服务器的服务暂时中断,影响数据的可用性和系统的整体可靠性。
鉴于 SYNC 命令对系统资源的巨大消耗及其潜在的性能影响,Redis 设计了一套高效的同步机制,旨在确保仅在确实需要时才执行 SYNC 命令。这通常发生在从服务器首次与主服务器建立连接、或从服务器与主服务器间的数据一致性遭到严重破坏需要重新同步时。
评论