redis之哨兵模式

写在前面

redis之哨兵模式_第1张图片
哨兵用来执行redis实例的监控工作,实现redis集群的高可用,可以执行实例下线,选举新主节点等工作,本文一起看下。

1:实战

1.1:创建redis集群

启动命令:redis-server.exe "redis.windows.conf" --maxheap 200m。单机环境下我们只需要将配置文件复制多份就可以启动多个redis实例了,分别准备如下3个配置文件(注意只列出了主要配置而非所有配置),用来创建3个节点的redis集群:

  • master
# 运行端口
port 6379
# 当本实例作为slave时连接的master的认证密码
masterauth "123456"
  • slave1
# 运行端口
port 7379
# 当本实例作为slave时连接的master的认证密码
masterauth "123456"

启动后执行slaveof 127.0.0.1 6379

  • slave2
# 运行端口
port 8379
# 当本实例作为slave时连接的master的认证密码
masterauth "123456"

启动后执行slaveof 127.0.0.1 6379

接着查看集群状态:

  • master
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.10.44,port=7379,state=online,offset=85,lag=0
slave1:ip=192.168.10.44,port=8379,state=online,offset=85,lag=1
master_repl_offset:85
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:84
  • slave1
127.0.0.1:7379> info replication
# Replication
role:slave
master_host:192.168.10.44
master_port:6379
master_link_status:up
master_last_io_seconds_ago:7
master_sync_in_progress:0
slave_repl_offset:183
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
  • slave2
127.0.0.1:8379> info replication
# Replication
role:slave
master_host:192.168.10.44
master_port:6379
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_repl_offset:239
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:817123

到这里redis集群就创建完毕了!

1.2:创建sentinel集群

启动命令:redis-server.exe redis-sentinel-36666.conf --sentinel。单机环境下我们只需要将配置文件复制多份就可以用来启动多个sentinel实例了。准备如下2个配置文件,用来创建2个节点的sentinel集群:

  • 节点1
# sentinel运行的端口号
port 36666
# redis master地址是127.0.0.1 6379 
# 2:至少2个sentinel实例判断Redis master状态为主观下线,才会标记为客观下线,执行failover
sentinel monitor mymaster 192.168.10.44 6379 2
# mymaster redis 实例,在5000毫秒内没有返回PING信息,则标记为主观下线
sentinel down-after-milliseconds mymaster 5000
# 新Redis master选举成功后,多少个从实例暂时不从新master同步数据,而是继续对外提供服务,如有3个从实例,配置为1代表1个对外继续提供查询,剩余2个从新主同步数据
sentinel parallel-syncs mymaster 1
# master被标记为客观下线后,执行failover的超时时间,超过该时间则认为failover切换失败
sentinel failover-timeout mymaster 15000
# 设置redis master 认证密码,否则会因为无法连接而判断为sdown
sentinel auth-pass mymaster 123456
  • 节点2
# sentinel运行的端口号
port 46666
# redis master地址是127.0.0.1 6379 
# 2:至少2个sentinel实例判断Redis master状态为主观下线,才会标记为客观下线,执行failover
sentinel monitor mymaster 192.168.10.44 6379 2
# mymaster redis 实例,在5000毫秒内没有返回PING信息,则标记为主观下线
sentinel down-after-milliseconds mymaster 5000
# 新Redis master选举成功后,多少个从实例暂时不从新master同步数据,而是继续对外提供服务,如有3个从实例,配置为1代表1个对外继续提供查询,剩余2个从新主同步数据
sentinel parallel-syncs mymaster 1
# master被标记为客观下线后,执行failover的超时时间,超过该时间则认为failover切换失败
sentinel failover-timeout mymaster 15000
# 设置redis master 认证密码,否则会因为无法连接而判断为sdown
sentinel auth-pass mymaster 123456

接着查看集群状态:

  • 节点1
D:\program_files\Redis-x64-2.8.2402>redis-cli.exe -p 36666
127.0.0.1:36666> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
master0:name=mymaster,status=ok,address=192.168.10.44:8379,slaves=2,sentinels=2

通过master0:name=mymaster,status=ok,address=192.168.10.44:8379,slaves=2,sentinels=2行中的slaves=2,sentinels=2可以看到已经成功识别了redis集群,并组成了2个节点的sentinel集群。

  • 节点2
D:\program_files\Redis-x64-2.8.2402>redis-cli.exe -p 46666
127.0.0.1:46666> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
master0:name=mymaster,status=ok,address=192.168.10.44:7379,slaves=2,sentinels=2

通过master0:name=mymaster,status=ok,address=192.168.10.44:8379,slaves=2,sentinels=2行中的slaves=2,sentinels=2可以看到已经成功识别了redis集群,并组成了2个节点的sentinel集群。

以上sentinel配置中,我们并没有配置其他的sentinel信息,但还是发现了彼此组成了集群,是怎么做到的呢?其实是在redis集群的master节点有一个名字叫做__sentinel:hello__的频道 ,所有的变更都会向该频道发布消息,我们也可以通过subscribe __sentinel__:hello来订阅此频道消息,基于此就实现了自动发现机制。

1.3:测试故障切换

  • 停止Redis master 6379
Ctrl C
[700112] 13 Oct 13:34:03.451 # Redis is now ready to exit, bye bye...
  • 查看sentinel failover日志
[727760] 13 Oct 13:28:43.272 # +config-update-from sentinel 192.168.10.44:46666 192.168.10.44 46666 @ mymaster 192.168.10.44 8379
[727760] 13 Oct 13:28:43.272 # +switch-master mymaster 192.168.10.44 8379 192.168.10.44 7379
[727760] 13 Oct 13:28:43.274 * +slave slave 192.168.10.44:6379 192.168.10.44 6379 @ mymaster 192.168.10.44 7379
[727760] 13 Oct 13:28:43.274 * +slave slave 192.168.10.44:8379 192.168.10.44 8379 @ mymaster 192.168.10.44 7379
[727760] 13 Oct 13:29:03.398 * +fix-slave-config slave 192.168.10.44:8379 192.168.10.44 8379 @ mymaster 192.168.10.44 7379
[727760] 13 Oct 13:34:08.620 # +sdown slave 192.168.10.44:6379 192.168.10.44 6379 @ mymaster 192.168.10.44 7379

可以看到选择了7379作为新的master,并将6379,8379设置为其slave,设置的的方式是修改对应的配置文件redis.windows.conf,如下是在6379配置文件中自动添加的配置:

################################## INCLUDES ###################################

# Include one or more other config files here.  This is useful if you
# have a standard template that goes to all Redis server but also need
# to customize a few per-server settings.  Include files can include
# other files, so use this wisely.
#
# include /path/to/local.conf
# include /path/to/other.conf
# Generated by CONFIG REWRITE
# slaveof 192.168.10.44 8379
# slaveof 192.168.10.44 8379
slaveof 192.168.10.44 7379

这样当6379启动后,会自动作为新master7379的slave运行,启动后如下:

127.0.0.1:6379> info replication
# Replication
role:slave
master_host:192.168.10.44
master_port:7379
...

2:理论

2.1:主观下线和客观下线

主观下线:哨兵自己认为某redis实例不可用。
客观下线:多个哨兵认为redis实例不可用,即不可用是客观上的事实,所以叫做客观下线。

主观下线和客观下线都是对某redis实例可用性的描述,sentinel集群通过PING命令来检测redis实例是否正常,当某个redis实例返回PING命令超时,哨兵就会将其标记为主观下线,如果是当前被标记为主观下线的redis实例是slave,则直接将其下线即可,因为不会中断redis集群服务,但如果是master,则就不能将其进行简单的下线处理了,而是要和其他哨兵节点商议,只有达到一定数量(如配置"sentinel monitor mymaster 192.168.10.44 7379 2"必须达到2)的哨兵节点认为其主观下线,才能将其标记为客观下线,然后进入failover。

如下是当配置必须2个哨兵认为主观下线,才会标记为客观下线时只有一个哨兵认为主观下线,不执行failover的情况以及2个哨兵认为主观下线被标记为客观下线的情况:

redis之哨兵模式_第2张图片

2.2:如何判定客观下线

当某哨兵判断redis主实例的PING命令返回时间超过了down-after-milliseconds配置的时长,则就会将redis主节点先标记为主观下线,此时想要标记为客观下线,会向其他哨兵发送is-master-down-by-addr命令进行询问,当超过quorum个哨兵认为主观下线时,会被标记为客观下线,这个过程可能如下图:

redis之哨兵模式_第3张图片

2.3:判断客观下线后哪个哨兵执行failover

当redis主节点被标记为客观下线后,对应的哨兵并不能立即开始failover的过程,而是必须向其他哨兵节点发送申请成为leader的请求,当然会自己先给自己投一票赞成票,只有超过quorum个的哨兵实例同意自己成为leader,之后才能开始执行failover的过程,当然这个过程中可能也有其他哨兵也判定了redis主节点客观下线,也会执行这个过程,只有最终成为leader的哨兵实例才有资格执行failover,假设quorum=2,这个过程可能如下图:

redis之哨兵模式_第4张图片

上图中S3最终获得了2个Y,即获得了2张赞成票,成为leader,执行failover过程,新主选择完成后,由其通知其他Redis slave实例以及客户端程序选择的结果。

2.4:failover如何选新master

当redis集群master节点被判定为主观下线后,就要开始failover过程,从从节点中选择一个作为新的主节点,然后其他的节点设置为其从节点,那么这个新的主节点如何选择出来呢,看下如下的步骤:

  • 1:过滤不适合从节点
    如果是从节点已经主观下线,或者是其总是和主节点断连(具体的断连次数等信息在哨兵有),即其服务本身或网络状况不稳定,则需要过滤掉,不能作为新master的候选实例。如下图:

redis之哨兵模式_第5张图片

  • 2:打分
    通过打分,分数最高者作为新的master,具体的打分过程如下:
1:通过slave-priority配置打分,该值配置越小分数则越高,分数最高的作为新master,如果是存在多个分数相同的则进入2
2:通过slave_repl_offset判断同步偏移量,该值越大则分数越高,分数最高的作为新master,如果是存在多个分数相同则进入3
3:实例ID号(ID号是实例分配的唯一编号,递增,越小则说明启动越早)最小的作为新master

这样,新的master就可以选举出来了。

2.5:新master如何通知客户端

sentinel利用了pub/sub 机制来发布各种消息到对应的频道,其中新的master切换的消息会发送到频道+switch-master中,如下是我本地订阅sentinel频道:

D:\program_files\Redis-x64-2.8.2402>redis-cli.exe -p 46666
127.0.0.1:46666> subscribe +switch-master
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "+switch-master"
3) (integer) 1
1) "message"
2) "+switch-master"
3) "mymaster 192.168.10.44 6379 192.168.10.44 7379"

其中mymaster 192.168.10.44 6379 192.168.10.44 7379就是新主的切换消息,格式是<主库名称> ,因此这里的新master地址就是192.168.10.44 7379,客户端就可以动态的变换到这个地址来向新master更新数据了。

另外sentinel主要的频道如下图所示,客户端可以根据具体的业务需要来进行订阅:

redis之哨兵模式_第6张图片

写在后面

参考文章列表:

redis配置哨兵(sentinel)模式 。

redis-Sentinel配置 。

redis sentinel部署(Windows下实现) 。

Redis和Sentinel搭建一主多从高可用集群 。

你可能感兴趣的:(redis,redis,数据库,缓存)