Redis

原理

Redis的主从复制

1、同一个Master可以同步多个Slaves。

2、Slave同样可以接受其它Slaves的连接和同步请求,这样可以有效的分载Master的同步压力。

3、Master Server是以非阻塞的方式为Slaves提供服务。所以在Master-Slave同步期间,客户端仍然可以提交查询或修改请求。

4、Slave Server同样是以非阻塞的方式完成数据同步。在同步期间,如果有客户端提交查询请求,Redis则返回同步之前的数据。

5、在Slave启动并连接到Master之后,它将主动发送一个SYNC命令。此后Master将启动后台存盘进程,同时收集所有接收到的用于修改数据集的命令,在后台进程执行完毕后,Master将传送整个数据库文件到Slave,以完成一次完全同步。而Slave服务器在接收到数据库文件数据之后将其存盘并加载到内存中。即连上之后,先进行一次全量同步。

6、此后,Master继续将所有已经收集到的修改命令,和新的修改命令依次传送给Slaves,Slave将在本次执行这些数据修改命令,从而达到最终的数据同步。后面进行增量同步。

7、 如果Master和Slave之间的链接出现断连现象,Slave可以自动重连Master,但是在连接成功之后,一次完全同步将被自动执行。

发现故障

主观下线(subjectively down,SDOWN):当前 Sentinel 实例认为某个 redis 服务为”不可用”状态。Sentinel 向 redis master 数据节点发送消息后 30s(down-after-milliseconds) 内没有收到有效回复(+PONG、-LOADING 或者 -MASTERDOWN),Sentinel 会将 master 标记为下线

**客观下线(objectively down,ODOWN):**多个 Sentinel 实例都认为 master 处于 SDOWN 状态,那么此时 master 将处于 ODOWN, ODOWN可以简单理解为master已经被集群确定为”不可用”,将会开启故障转移机制。向其他 sentinel 节点发送 sentinel is-master-down-by-addr 消息询问数据节点情况,得知达到 quorum 数量的 sentinel 节点认为数据节点已经下线

故障处理–选举

就是选举出新的Leader-Sentinel,选举过程如下:

1、发现主库客观下线的哨兵节点(这里称为A)向每个哨兵节点发送命令要求对方选举自己为领头哨兵(leader);
2、如果目标哨兵没有选举过其他人,则同意将A选举为领头哨兵;
3、如果A发现有超过半数且超过quorum参数值的哨兵节点同意选自己成为领头哨兵,则A哨兵成功选举为领头哨兵。
4、当有多个哨兵节点同时参与领头哨兵选举时,出现没有任何节点当选可能,此时每个参选节点等待一个随机时间进行下一轮选举,直到选出领头哨兵。

故障处理–转移(切换 Redis master 数据节点)

  1. sentinel master 选择合适的 redis slave 成为 master
    slave 选择标准:健康的节点:在线的、最近成功通信过的(5s 内回复过 PING 命令)、数据比较新的(与 master 失联时间不超过 10*down-after-milliseconds)、slave-priority(slave节点优先级)最高的slave节点(越小越高,master节点的优先级为0,因此如果设置为0的话永远不会被选为主)、复制偏移量最大的 slave 节点(复制的最完整)、选择 runId 最小的 slave 节点(启动最早的节点)
  2. 执行 SLAVEOF no one(不会删除已有数据,只是不再接受主节点新的数据变化) 命令让其成为新的 master 节点。每秒 Sentinel 向其发送一次 INFO 命令,直到成功变为 master
  3. 向剩余的 slave 节点发送 SLAVEOF 新master 命令,让他们成为新 master 节点的 slave 节点
  4. 让剩余的 slave 复制新 master 的数据,通过配置 sentinel parallel-syncs(sentinel.conf) 规定了每次向新的主节点发起复制操作的从节点个数,parallel-syncs 取值越大,slave 完成复制的时间越快,但是对主节点的网络负载、硬盘负载造成的压力也越大
  5. 更新原来master 节点配置为 slave 节点,并保持对其进行关注,一旦这个节点重新恢复正常后,会命令它去复制新的master节点信息
  6. 全部故障转移工作完成后,Leader Sentinel 就会推送 +switch-master 消息,同时重置 master,重置操作会释放掉原来 master 全部的 slave 对象和监听该 master 的其他 Sentinel 对象,然后创建出新的 slave 对象。故障迁移过程中 slave 能否返回数据给客户端取决于 slave-serve-stale-data(redis.conf)
  7. 持续关注旧的 master,并在他重新上线后将它设置为新 master 的 slave

在 sentinel 中执行 sentinel failover master 可以强制该 sentinel 节点执行故障转移,不与其他节点进行选举(跳过leader的选举过程),因为最先使用优先级进行选择新master,那么可以使用以下命令来配置redis的slave优先级

## 默认是100,这里配置成50
config set slave-priority 50

## 其他可配置项目可以通过以下命令查看
config get *

## 配置的信息如果想要保存到配置文件中,可以使用以下命令,进行redis主备转移的时候会默认执行一次这个
config rewrite

配置

redis.conf配置内容如下:

# 开启后台启动,默认为no
daemonize yes

# 新增密码
requirepass "password"

# 允许从节点进行写功能
slave-read-only no

# 设置了密码,主节点需要进行密码认证
masterauth "password"

# 如果是Slave则需要配置Master的地址
# slaveof 10.10.10.238 6379

sentinel.conf配置内容如下:

# 检查主redis节点的地址和端口信息,1代表至少1个sentinel节点认为主节点宕机才算宕机,根据实际情况进行配置
sentinel monitor mymaster 10.10.10.44 6379 1

# 主节点失联X秒后,认为主节点不可达,默认30s
sentinel down-after-milliseconds mymaster 5000

# 主节点的密码,如有的话
sentinel auth-pass mymaster password

# sentinel后台运行
daemonize yes

# 解决哨兵之间不能通信,不能进行主结节客观下线的判断,以及failover
protected-mode no

测试

redis.conf配置文件(关键内容)如下:

# 237
daemonize yes
requirepass zhkjredis@002396
slave-read-only no
masterauth zhkjredis@002396

# 238
daemonize yes
requirepass zhkjredis@002396
slave-read-only no
masterauth zhkjredis@002396
slaveof peerServer 6379

# 104
daemonize yes
requirepass zhkjredis@002396
slave-read-only no
masterauth zhkjredis@002396
slaveof server237 6379

sentinel.conf配置文件(关键内容)如下:

# 237
sentinel monitor mymaster localServer 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel auth-pass mymaster password
daemonize yes
protected-mode no

# 238
sentinel monitor mymaster peerServer 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel auth-pass mymaster password
daemonize yes
protected-mode no

# 104
sentinel monitor mymaster server237 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel auth-pass mymaster password
daemonize yes
protected-mode no

先启动237的redis和sentinel,然后启动238和104的组件。

通过INFO命令可以看到237为master,下面有两个slave,一个是238一个是104

# 237-Replication
role:master
connected_slaves:2
slave0:ip=10.10.10.238,port=6379,state=online,offset=17686,lag=1
slave1:ip=10.10.10.104,port=6379,state=online,offset=17408,lag=1

# 238-Replication
role:slave
master_host:peerServer
master_port:6379
master_link_status:up

# 104-Replication
role:slave
master_host:peerServer
master_port:6379
master_link_status:up

在237插入<test, test>,分别在238和104进行查询,能够查询成功,说明238和104对237同步成功。

在238插入<test238, test>,分别在237和104查询,查询失败,说明237和104并没有同步238数据,且slave能够进行数据的插入。

关闭237,此时经过选举之后,238和104中其中一个将会成为新的master,讲238重新上线,238将会成为新master的slave。

将237重新变为master,此时想指定让104成为master,需要进行以下操作:

## 先保证238和104的优先级为100,然后设置237的优先级为50
redis-cli -h 10.10.10.104 -a zhkjredis@002396 config set slave-priority 100
redis-cli -h 10.10.10.104 -a zhkjredis@002396 config rewrite

redis-cli -h 10.10.10.238 -a zhkjredis@002396 config set slave-priority 100
redis-cli -h 10.10.10.238 -a zhkjredis@002396 config rewrite

redis-cli -h 10.10.10.237 -a zhkjredis@002396 config set slave-priority 50

## 进行sentinel故障转移
redis-cli -h 10.10.10.237 -a zhkjredis@002396 -p 26379 sentinel failover mymaster

## 等待104成为master之后,讲104的优先级改回100
redis-cli -h 10.10.10.237 -a zhkjredis@002396 config set slave-priority 100
redis-cli -h 10.10.10.237 -a zhkjredis@002396 config rewrite

主动主备切换

保证除了指定成为新master的redis的优先级变成100,然后讲该redis的优先级设置为50,然后通过sentinel的命令进行故障转移,待转移完成之后,讲该redis的优先级改回100。

例如目前237为master,要使得104成为主,只需要保证237和238的slave优先级为100,并讲104的优先级设置为50,然后进行故障转移,等待转移完成之后将104的优先级改回100.

被动主备切换

当发生故障转移时,sentinel会选举出leader-sentinel,然后由该sentinel选择适合的redis成为新的master,原master重新上线时候,会被sentinel转换成当前master的slave。