Redis(四)——redis主从复制、哨兵模式sentinel

时代在进步,生产环境中单机部署的情况已经越来越少了,redis同样如此。redis集群技术也越来越成熟,在生产中redis集群部署已经是一个常见的技术。

本文主要总结自《redis深度历险》


主从同步

所有集群模式都离不开一个基础:同步机制。节点之间的数据同步是集群基础,主从同步则是这一切的基础。

redis主从同步的意义:有一些企业虽然没有使用redis集群,但是至少做了主从同步。当一个redis master节点挂了的时候,如果要要重启这个redis节点,需要耗费很多时间来进行数据恢复和重启。为了不影响线上功能,使用slave节点代替master,将影响降到最低。


主从同步:redis的数据是异步同步的,所以分布式模式下的redis无法满足一致性要求。如果主从节点之间出现问题,比如网络中断,主节点可以继续对外服务,但是从节点无法同步主节点上的数据。这个时候就会出现数据不一致的情况,当网络恢复时从节点会努力去追赶上主节点上的数据。

数据同步时,支持主从、从从同步(后面统一说成是主从复制)
Redis(四)——redis主从复制、哨兵模式sentinel_第1张图片

同步机制

增量同步

增量同步同步的是指令流,主节点会将那些对自己数据状态产生修改性影响的指令(比如增删改)记录在本地的内存buffer中,然后将buffer中的指令同步到从节点中。从节点一边执行同步以达到和主节点一样的状态,一边像主节点报告自己同步到哪里了(偏移量)。

内存buffer是有限的,它是一个环形数组,当数组内容满了会从头开始覆盖前面的内容:

Redis(四)——redis主从复制、哨兵模式sentinel_第2张图片


当redis主节点中的指令还没来得及同步就被新指令覆盖时,从节点就无法通过指令流来进行同步了,这个时候需要新的同步机制————快照同步。

快照同步

进行快照同步时,需要将主节点内存中的数据全部刷入磁盘文件中,然后将快照文件的内容全部传到从节点。从节点接收文件完毕后,会将其内存中的数据清空,然后进行一次全量加载。加载完毕后再通知主节点进行增量同步。
如果快照同步的过程中又有新的指令被覆盖,此时还是无法进行增量同步,而是需要再发起一次快照同步,此时极有可能陷入一个循环:每次快照同步完,内存buffer中已经堆满指令,只能再发起一次快照同步。

  • 当有新的节点加入集群时,会进行一次快照同步,同步完成后再进行增变量同步。

必须配置合理的buffer大小避免出现这种复制循环的现象。

无盘复制

主节点进行快照同步时会进行很多IO操作,对系统负载产生很大影响。特别是当系统正在进行AOF的同步操作时,如果发生快照同步,AOF同步会被推迟执行,这将严重影响主节点服务效率。

所以从redis-2.8.18版本开始支持无盘复制功能:主节点通过套接字将快照内容发送到从节点,生成快照是一个遍历的过程:一边遍历内存一边将序列化的内容发送到从节点。从节点则还是和以前一样,先将内容存到磁盘再一次性进行加载。

Wait 指令

wait指令可以将异步复制的方式变成同步复制,确保系统的强一致性。实现强一致性的代价就是主节点的性能大大降低。


哨兵模式 Sentinel

主从模式虽然可以在一定程度上保证数据的高可用性,但是却需要人工进行节点的切换:某个主节点挂掉了,需要使用从节点,此时就需要人工进行主从的切换。都2020年了,这种模式肯定是不可取的。所以我们需要让系统自动完成这些事:如果主节点挂了,从节点会自动选举出新的节点作为主节点,系统可以继续平稳运行。
Redis Sentinel哨兵模式可以满足这种需求。

Redis(四)——redis主从复制、哨兵模式sentinel_第3张图片

redis sentinel 是一套独立的集群,可以同时监控多个redis的 master-slave集群,可以将它看成是一套zookeeper集群。它是集群高可用的核心,一般由3~5个节点组成,即使某个节点宕机了系统还能高效运行。

客户端连接到集群时会先连接到sentinel,通过sentinel拿到master节点的地址,然后再和主节点进行数据交互。当主节点发生故障、宕机时,客户端会重新向sentinel发起一个请求以来获取新的master节点地址。sentinel随后将新选举出来的master节点地址发给客户端,客户端通过新的地址继续和redis进行数据交互。

Redis(四)——redis主从复制、哨兵模式sentinel_第4张图片

当master节点挂掉的时候,客户端与master之间交互失败。

Redis(四)——redis主从复制、哨兵模式sentinel_第5张图片

此时redis集群已经选举出新的master节点,可能与原master交互失败时会再发一次请求以获得新的master地址,当获取到新的master地址后与新的master节点进行数据交互。

Redis(四)——redis主从复制、哨兵模式sentinel_第6张图片

消息丢失

redis采用异步复制的方式进行数据同步,这就意外着肯定会存在数据丢失的情况。从节点可能还没接收到主节点的所有数据,主节点就挂了。主从节点的延迟特越大,丢失的数据就越多。redis sentinel是无法保证数据完全不丢失的,但是可以通过配置使得数据进来不丢失:

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

# min-slaves-to-write 1
#表示主节点至少有一个从节点在进行正常复制,否则就停止对外写服务,丧失可用性

# min-slaves-max-lag 10
#表示10s内主节点还没收到从节点的反馈就意味着从节点同步不正常

当sentinel主从切换时,主节点可能没有宕机(比如人为的进行主从切换),又或者master宕机后,已经恢复并且已经选举出新的master节点,原master节点变成了slaver,这个时候客户端如何获取正确的master节点呢?

通过源码可知,当进行连接的时候,会进行主库地址变更判断。连接池在建立连接时会去查询主库地址,然后和内存中的地址进行比对,如果发生变化则断开所有连接并使用新的地址建立新的链接。

在原master节点没有挂掉,并且原先master节点的连接已经在使用的情况下,上面所说的机制还是无法满足。这个时候就需要用到ReadOnlyError:当原master降级成为slaver时,所有修改性的指令都会抛出ReadOnlyError。

从而避免主从节点数据冲突的问题。


你可能感兴趣的:(redis)