Redis高可用总结:Redis主从复制、哨兵集群、脑裂...

本文涉及的产品
云数据库 Redis 版,标准版 2GB
推荐场景:
搭建游戏排行榜
云原生内存数据库 Tair,内存型 2GB
简介: 在实际的项目中,服务高可用非常重要,如,当Redis作为缓存服务使用时, 缓解数据库的压力,提高数据的访问速度,提高网站的性能 ,但如果使用Redis 是单机模式运行 ,只要一个服务器宕机就不可以提供服务,这样会可能造成服务效率低下,甚至出现其相对应的服务应用不可用。

在实际的项目中,服务高可用非常重要,如,当Redis作为缓存服务使用时, 缓解数据库的压力,提高数据的访问速度,提高网站的性能 ,但如果使用Redis 是单机模式运行 ,只要一个服务器宕机就不可以提供服务,这样会可能造成服务效率低下,甚至出现其相对应的服务应用不可用。


因此为了实现高可用,Redis 提供了哪些高可用方案?


  • Redis主从复制
  • Redis持久化
  • 哨兵集群
  • ...


20.png


Redis基于一个Master主节点多Slave从节点的模式和Redis持久化机制,将一份数据保持在多个实例中实现增加副本冗余量,又使用哨兵机制实现主备切换, 在master故障时,自动检测,将某个slave切换为master,最终实现Redis高可用 。


Redis主从复制


Redis主从复制,主从库模式一个Master主节点多Slave从节点的模式,将一份数据保存在多Slave个实例中,增加副本冗余量,当某些出现宕机后,Redis服务还可以使用。


21.png


但是这会存在数据不一致问题,那redis的副本集是如何数据一致性?


Redis为了保证数据副本的一致,主从库之间采用读写分离的方式:


  • 读操作:主库、从库都可以执行处理;
  • 写操作:先在主库执行,再由主库将写操作同步给从库。


22.png


使用读写分离方式的好处,可以避免当主从库都可以处理写操作时,主从库处理写操作加锁等一系列巨额的开销。


采用读写分离方式,写操作只会在主库中进行后同步到从库中,那主从库是如何同步数据的呢?


主从库是同步数据方式有两种:


  • 全量同步:通常是主从服务器刚刚连接的时候,会先进行全量同步
  • 增量同步 :一般在全同步结束后,进行增量同步,比如主从库间网络断,再进行数据同步。


全量同步


主从库间第一次全量同步,具体分成三个阶段:


  • 当一个从库启动时,从库给主库发送 psync 命令进行数据同步(psync 命令包含:主库的 runID 和复制进度 offset 两个参数),
  • 当主库接收到psync 命令后将会保存RDB 文件并发送给从库,发送期间会使用缓存区(replication buffer)记录后续的所有写操作 ,从库收到数据后,会先清空当前数据库,然后加载从主库获取的RDB 文件,
  • 当主库完成 RDB 文件发送后,也会把将保存发送RDB文件期间写操作的replication buffer发给从库,从库再重新执行这些操作。这样一来,主从库就实现同步了。


23.png


另外,为了分担主库生成 RDB 文件和传输 RDB 文件压力,提高效率,可以使用 “主 - 从 - 从”模式将主库生成 RDB 和传输 RDB 的压力,以级联的方式分散到从库上。


24.png


增量同步


增量同步,基于环形缓冲区repl_backlog_buffer缓存区实现。


在环形缓冲区,主库会记录自己写到的位置 master_repl_offset ,从库则会记录自己已经读到的位置slave_repl_offset, 主库并通过master_repl_offsetslave_repl_offset的差值的数据同步到从库。


25.png


主从库间网络断了, 主从库会采用增量复制的方式继续同步,主库会把断连期间收到的写操作命令,写入 replication buffer,同时也会把这些操作命令也写入 repl_backlog_buffer 这个缓冲区,然后主库并通过master_repl_offsetslave_repl_offset的差值数据同步到从库。


26.png


因为repl_backlog_buffer 是一个环形缓冲区,当在缓冲区写满后,主库会继续写入,此时,会出现什么情况呢?


覆盖掉之前写入的操作。如果从库的读取速度比较慢,就有可能导致从库还未读取的操作被主库新写的操作覆盖了,这会导致主从库间的数据不一致。因此需要关注 repl_backlog_size参数,调整合适的缓冲空间大小,避免数据覆盖,主从数据不一致。


主从复制,除了会出现数据不一致外,甚至可能出现主库宕机的情况,Redis会有主从自主切换机制,那如何实现的呢?


Redis哨兵机制


当主库挂了,redis写操作和数据同步无法进行,为了避免这样情况,可以在主库挂了后重新在从库中选举出一个新主库,并通知到客户端,redis提供了 哨兵机制,哨兵为运行在特殊模式下的 Redis 进程。


Redis会有主从自主切换机制,那如何实现的呢?


哨兵机制是实现主从库自动切换的关键机制,其主要分为三个阶段:


  • 监控:哨兵进程会周期性地给所有的主从库发送 PING 命令,检测它们是否仍然在线运行。
  • 选主(选择主库):主库挂了以后,哨兵基于一定规则评分选选举出一个从库实例新的主库 。
  • 通知 : 哨兵会将新主库的信息发送给其他从库,让它们和新主库建立连接,并进行数据复制。同时,哨兵会把新主库的信息广播通知给客户端,让它们把请求操作发到新主库上。


27.png


其中,在监控中如何判断主库是否处于下线状态?


哨兵对主库的下线判断分为:


  • 主观下线:哨兵进程会使用 PING 命令检测它自己和主、从库的网络连接情况,用来判断实例的状态, 如果单哨兵发现主库或从库对 PING 命令的响应超时了,那么,哨兵就会先把它标记为“主观下线”
  • 客观下线:在哨兵集群中,基于少数服从多数,多数实例都判定主库已“主观下线”,则认为主库“客观下线”。


为什么会有这两种"主观下线"和“客观下线”的下线状态呢?


由于单机哨兵很容易产生误判,误判后主从切换会产生一系列的额外开销,为了减少误判,避免这些不必要的开销,采用哨兵集群,引入多个哨兵实例一起来判断,就可以避免单个哨兵因为自身网络状况不好,而误判主库下线的情况,


基于少数服从多数原则, 当有 N 个哨兵实例时,最好要有 N/2 + 1 个实例判断主库为“主观下线”,才能最终判定主库为“客观下线” (可以自定义设置阙值)。


28.png


那么哨兵之间是如何互相通信的呢?


哨兵集群中哨兵实例之间可以相互发现,基于 Redis 提供的发布 / 订阅机制(pub/sub 机制),


哨兵可以在主库中发布/订阅消息,在主库上有一个名为“\__sentinel__:hello”的频道,不同哨兵就是通过它来相互发现,实现互相通信的,而且只有订阅了同一个频道的应用,才能通过发布的消息进行信息交换。


29.png


哨兵 1连接相关信息(IP端口)发布到“\__sentinel__:hello”频道上,哨兵 2 和 3 订阅了该频道。


哨兵 2 和 3 就可以从这个频道直接获取哨兵 1连接信息,以这样的方式哨兵集群就形成了,实现各个哨兵互相通信。


哨兵集群中各个实现通信后,就可以判定主库是否已客观下线。


在已判定主库已下线后,又如何选举出新的主库?


新主库选举按照一定条件筛选出的符合条件的从库,并按照一定规则对其进行打分,最高分者为新主库。


通常一定条件包括:


  • 从库的当前在线状态,
  • 判断它之前的网络连接状态,通过down-after-milliseconds * num(断开连接次数),当断开连接次数超过阈值,不适合为新主库。


一定规则包括


  • 从库优先级 , 通过slave-priority 配置项,给不同的从库设置不同优先级,优先级最高的从库得分高
  • 从库复制进度,和旧主库同步程度最接近的从库得分高,通过repl_backlog_buffer缓冲区记录主库 master_repl_offset 和从库slave_repl_offset 相差最小高分
  • 从库 ID 号 , ID 号小的从库得分高。


全都都基于在只有在一定规则中的某一轮评出最高分从库就选举结束,哨兵发起主从切换


leader哨兵


选举完新的主库后,不能每个哨兵都发起主从切换,需要选举成leader哨兵,那如何选举leader哨兵执行主从切换?


选举leader哨兵,也是基于少数服从多数原则"投票仲裁"选举出来,


  • 当任何一个从库判定主库“主观下线”后,发送命令 s-master-down-by-addr命令发送想要成为Leader的信号,
  • 其他哨兵根据与主机连接情况作出相对的响应,赞成票Y,反对票N,而且如果有多个哨兵发起请求,每个哨兵的赞成票只能投给其中一个,其他只能为反对票。


想要成为Leader 的哨兵,要满足两个条件:


  • 第一,获得半数以上的赞成票;
  • 第二,获得的票数同时还需要大于等于哨兵配置文件中的quorum值。


选举完leader哨兵并新主库切换完毕之后,那么leader哨兵怎么通知客户端?


还是基于哨兵自身的 pub/sub 功能,实现了客户端和哨兵之间的事件通知,客户端订阅哨兵自身消息频道 ,而且哨兵提供的消息订阅频道有很多,不同频道包含了:


事件 相关频道
主库下线事件 +sdown(实例进入“主观下线”状态)
-sdown(实例退出“主观下线”状态)
+odown(实例进入“客观下线”状态)
-odown(实例退出“客观下线”状态)
新主库切换 + switch-master(主库地址发生变化)


其中,当客户端从哨兵订阅消息主从库切换,当主库切换后,端户端就会接收到新主库的连接信息:


switch-master <master name> <oldip> <oldport> <newip> <newport>  
复制代码


在这样的方式哨兵就可以通知客户端切换了新库。


基于上述的机制和原理Redis实现了高可用,但也会带了一些潜在的风险,比如数据缺失。


数据问题


Redis实现高可用,但实现期间可能产出一些风险:


  • 主备切换的过程, 异步复制导致的数据丢失
  • 脑裂导致的数据丢失
  • 主备切换的过程,异步复制导致数据不一致


数据丢失-主从异步复制


因为master 将数据复制给slave是异步实现的,在复制过程中,这可能存在master有部分数据还没复制到slave,master就宕机了,此时这些部分数据就丢失了。


总结:主库的数据还没有同步到从库,结果主库发生了故障,未同步的数据就丢失了。


数据丢失-脑裂


何为脑裂?当一个集群中的 master 恰好网络故障,导致与 sentinal 通信不上了,sentinal会认为master下线,且sentinal选举出一个slave 作为新的 master,此时就存在两个 master了。


此时,可能存在client还没来得及切换到新的master,还继续写向旧master的数据,当master再次恢复的时候,会被作为一个slave挂到新的master 上去,自己的数据将会清空,重新从新的master 复制数据,这样就会导致数据缺失。


总结:主库的数据还没有同步到从库,结果主库发生了故障,等从库升级为主库后,未同步的数据就丢失了。


数据丢失解决方案


数据丢失可以通过合理地配置参数 min-slaves-to-write 和 min-slaves-max-lag 解决,比如


  • min-slaves-to-write 1
  • min-slaves-max-lag 10


如上两个配置:要求至少有 1 个 slave,数据复制和同步的延迟不能超过 10 秒,如果超过 1 个 slave,数据复制和同步的延迟都超过了 10 秒钟,那么这个时候,master 就不会再接收任何请求了。


数据不一致


在主从异步复制过程,当从库因为网络延迟或执行复杂度高命令阻塞导致滞后执行同步命令,这样就会导致数据不一致


解决方案: 可以开发一个外部程序来监控主从库间的复制进度(master_repl_offsetslave_repl_offset ),通过监控 master_repl_offsetslave_repl_offset差值得知复制进度,当复制进度不符合预期设置的Client不再从该从库读取数据。


30.png


总结


Redis使用主从复制、持久化、哨兵机制等实现高可用,需要理解其实现过程,也要明白其带了风险以及解决方案,才能在实际项目更好优化,提升系统的可靠性、稳定性。


谢谢各位点赞,没点赞的点个赞支持支持



相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
16天前
|
NoSQL Redis
基于Redis的高可用分布式锁——RedLock
这篇文章介绍了基于Redis的高可用分布式锁RedLock的概念、工作流程、获取和释放锁的方法,以及RedLock相比单机锁在高可用性上的优势,同时指出了其在某些特殊场景下的不足,并提到了ZooKeeper作为另一种实现分布式锁的方案。
44 2
基于Redis的高可用分布式锁——RedLock
|
2月前
|
存储 缓存 NoSQL
Redis常见面试题(二):redis分布式锁、redisson、主从一致性、Redlock红锁;Redis集群、主从复制,哨兵模式,分片集群;Redis为什么这么快,I/O多路复用模型
redis分布式锁、redisson、可重入、主从一致性、WatchDog、Redlock红锁、zookeeper;Redis集群、主从复制,全量同步、增量同步;哨兵,分片集群,Redis为什么这么快,I/O多路复用模型——用户空间和内核空间、阻塞IO、非阻塞IO、IO多路复用,Redis网络模型
Redis常见面试题(二):redis分布式锁、redisson、主从一致性、Redlock红锁;Redis集群、主从复制,哨兵模式,分片集群;Redis为什么这么快,I/O多路复用模型
|
2月前
|
监控 NoSQL Redis
Redis 哨兵模式高可用
Redis 哨兵模式高可用
50 4
|
12天前
|
运维 监控 NoSQL
【Redis】哨兵(Sentinel)原理与实战全解~炒鸡简单啊
Redis 的哨兵模式(Sentinel)是一种用于实现高可用性的机制。它通过监控主节点和从节点,并在主节点故障时自动进行切换,确保集群持续提供服务。哨兵模式包括主节点、从节点和哨兵实例,具备监控、通知、自动故障转移等功能,能显著提高系统的稳定性和可靠性。本文详细介绍了哨兵模式的组成、功能、工作机制以及其优势和局限性,并提供了单实例的安装和配置步骤,包括系统优化、安装、配置、启停管理和性能监控等。此外,还介绍了如何配置主从复制和哨兵,确保在故障时能够自动切换并恢复服务。
|
30天前
|
消息中间件 存储 缓存
深入理解Redis集群主从复制原理
该文章主要探讨了Redis集群中的主从复制原理,包括为何需要主从复制、配置方法、复制流程以及一些高级特性。
深入理解Redis集群主从复制原理
|
2月前
|
NoSQL Redis
Redis 主从复制架构配置及原理
Redis 主从复制架构配置及原理
43 5
|
2月前
|
负载均衡 NoSQL 应用服务中间件
搭建高可用及负载均衡的Redis
【7月更文挑战第10天】
|
18天前
|
缓存 NoSQL Redis
【Azure Redis 缓存】Redission客户端连接Azure:客户端出现 Unable to send PING command over channel
【Azure Redis 缓存】Redission客户端连接Azure:客户端出现 Unable to send PING command over channel
|
14天前
|
缓存 NoSQL Java
Redis深度解析:解锁高性能缓存的终极武器,让你的应用飞起来
【8月更文挑战第29天】本文从基本概念入手,通过实战示例、原理解析和高级使用技巧,全面讲解Redis这一高性能键值对数据库。Redis基于内存存储,支持多种数据结构,如字符串、列表和哈希表等,常用于数据库、缓存及消息队列。文中详细介绍了如何在Spring Boot项目中集成Redis,并展示了其工作原理、缓存实现方法及高级特性,如事务、发布/订阅、Lua脚本和集群等,帮助读者从入门到精通Redis,大幅提升应用性能与可扩展性。
32 0