10分钟搞懂redis主从,哨兵,集群

151 阅读8分钟

主从复制原理

复制初始化

当一个从数据库启动后,会向主数据库发送一个SYNC命令。主数据库在接收到从数据据库的SYNC命令后会在后台fork出一个子线程进行快照备份,并将保存快照期间接收到的命令缓存起来,当快照缓存完之后,redis会把RDB快照和缓存的命令发送给从数据库,从数据库收到后会保存快照并执行收的的命令

复制初始化完成之后主数据库会把每次收到的写命令发送给从数据库,从而保证主从数据库的一致性

111111.png 在redis2.6以前的版本,每次从数据断开后和主数据库重连后都需要重新完整的复制一份主数据库的文件,哪怕从数据库只有几条没有接收到,这大大降低了redis主从复制的可用性,在redis2.8以后开始支持断开重连后的增量复制,节省了从数据库断开后重连的复制时间

总结一句话,redis主丛复制是基于redis RDB 持久化的方式进行的,既主数据库在后台保存快照,从数据库接收并载入快照文件

这么做的缺点有

  • 当主数据库没有启用RDB快照持久化时,如果执行了复制初始化操作,主数据库依旧会生成RDB快照,下次启动数据库时,redis就会使用开RDB文件,由于复制初始化执行的时间不确定,所以这时候丢失的数据是不确定的

  • 由于RDB复制初始化的时候会使用到硬盘,当硬盘性能比较差的时候,复制的时候性能就比较差

redis如何实现增量复制

  • 首先从数据库会存储主数据库的运行id,redis每个数据库都会拥有一个唯一的运行id,每次重启之后就会生成一个新的运行id

  • 在复制阶段主数据库每发送一个命令给从数据库都会将该命令存储在一个积压队列中,并记录下当前队列中存放的命令的偏移量

  • 同时从数据库接收到该命令后会记录下该命令的偏移量

从数据库不再发送SYNC命令,取而代之的时PSNYC命令

redis如何判断是执行增量复制还是全量复制

  • 首先主数据库会判断从数据库传来的运行id是否和自己的运行id相同,这一步骤是用来判断从数据库确实是之前和自己同步的,并且在断线期间主从数据库没有重启过

  • 判断从数据库最后同步的命令是否在积压队列中,如果是则可以执行增量复制

积压队列本质上是一个循环队列,挤压队列的大小是可以设置的,积压队列设置的越大,那么允许从数据库和主数据断开的时间就越长

repl-backlog-size:设置积压队列的大小默认1M 
repl-backlog-ttl:设置主从断开多久后释放积压队列

哨兵

哨兵的功能

  • 监控主从数据库的状态

  • 当主数据库宕机后,自动将从数据库切换为主数据库

哨兵机制架构图

单个哨兵

222.png

多个哨兵

为了避免哨兵的单点故障,可以部署多个哨兵,哨兵之间也可以互相监控

3333.png

在配置哨兵监控的的数据库时只需要配置主数据库即可,哨兵会自动发现复制主数据库的从数据库

哨兵的实现原理

哨兵的配置文件

sentinel monitor master-name ip port quorum

  • master-name:监控主数据库的名字

  • ip:监控数据库的地址

  • port:数据库端口

  • quorum:顾兆回复时需要几台哨兵同意

为什么哨兵需要建立两条链接

要解决这个问题首先要知道这两条链接是用来干什么的,首先一条链接是用来订阅主数据库的_sentinel_:hello频道,用来获取其他监控该主数据库的哨兵的,另一条用来向主数据库发送INFO信息,进而获取主数据的信息,因为当数据库订阅了频道之后就无法在接受其他信息了,所以需要另一条链接来获取数据库的信息

这两个链接建立成功后哨兵没做三件事情

  • 每10s向主数据库和从数据库发送INFO命令

获取当前数据库的信息,通过info命令可以获取到复制当前数据库从数据库,然后和每个从数据建立一样的两条链接

  • 每2s向主数据库和从数据库的_sentinel_:hello发送自己的信息向同样监控该数据库的哨兵分享自己的信息

  • 每1s向主数据库和从数据库和其他哨兵发送PING命令判断各个数据库是否联接正常

由谁进行故障恢复

领头哨兵,可以防止同一时刻有多个哨兵进行故障恢复

领头哨兵的选举

当一个哨兵发现主数据库连接异常时会认为主数据库主观下线,这个时候发现主数据库下线的哨兵为询问其他哨兵主数据库是否下线,当发现有quorum个哨兵认为主数据库下线时,则认为主数据库客观下线,这个时候哨兵会进行一次领头哨兵的选举,有领头哨兵来进行故障恢复,领头哨兵的选举会采用raft算法

  • 发现主数据库下线的哨兵A会要求其他哨兵选举自己为领头哨兵,当没有其他哨兵参与选举的时候,这个时候A就会成为领头哨兵,当有其他哨兵参与选举的时候。

  • 如果A发现有半数以上同意自己成为领头哨兵的时候A就会成为领头哨兵。

  • 当发现有多个哨兵可以成为领头哨兵的时候,这个时候就不会选举出领头哨兵,会在接下来的任意一个时间点进行下一轮选举,直到产生领头哨兵为止

领头哨兵开始进行故障恢复

  • 选举出优先级最高的从节点作为master(可以通过slave-priority进行配置)

  • 如果有多个优先级高的从节点,则选举复制偏移量最大(偏移量越大数据越新)的从节点作为master

  • 如果还是发现有多个的话,就是用运行id最小的slave作为master

redis master故障后的故障恢复流程

4444.png

目前这个基于哨兵redis主从架构的优缺点

优点

1.可以实现主从复制,当主数据库宕机不会造成数据的丢失

2.引入了哨兵机制,当主数据库出现故障的时候,可以自动的进行故障恢复

3.可以通过配置实现读写分离进而减轻主数据库的读压力

缺点

  • redis是基于内存存储的,内存资源是很宝贵的,尽管当前使用了主从架构,但是所有的机器上存储的数据都是全量的,这样就造成了内存的浪费

  • 水平扩容之后只能解决读并发的问题,基本无法解决写并发的问题,因为只有master可以支持写命令

集群

redis集群模式

redis从3.0版本后开始支持集群,集群的特点就是既有单机的性能,在网络出现分区之后还能保证集群的基本可用以及对主数据库的故障恢复能力,另外集群基本支持所有的单机命令,集群模式下redis默认使用0库,并且不支持切换

如何实现redis集群

www.cnblogs.com/PatrickLiu/… 这边博客写的很详细,直接参照就可以了

集群的故障恢复

主数据库下线

  • 在一个集群中每个节点都会定期的向其他节点发送PING命令,当没有收到PONG的回复时,就认为该节点疑似下线

  • 这个时候就会向集群中的其他节点A发送该节点下线的消息,A记录下该消息,当超过半数节点认为改节点下线之后,该节点就会真正下线,

故障恢复

故障恢复采用raft算法

  • 那么此时就需要进行master的故障转移,该master下面的slave节点就会向其他节点发送选举自己成为master的消息,当超过半数的节点同意的时候,

  • 当有多个的时候,就会在接下来任意时间继续进行选举,

  • 当一个节点发现自己成为master节点的时候就会使用SLAVEOF NO ONE 将自己切换成主数据库,并接管旧的数据库分配的槽

注意当一个分配了至少一个槽的主数据库没有从节点时,如果下线,此时集群就会处于不可用的状态

集群master下线和恢复流程图

66666.png