一、Redis新特性ACL安全策略
在Redis6之前的版本,我们只能使用requirepass参数给default用户配置登录密码,同一个Redis集群的所有开发都共享default用户,难免会出现误操作把别人的key删掉或者数据泄露的情况。
因此Redis6版本退出了ACL(Access Controller List)访问控制权限的功能,基于次功能,我们可以设置多个用户,并且给每一个用户单独设置命令权限和数据权限。为了保证向下兼容性,Redis6保留了default用户和使用requirepass 的方式给default用户设置密码,默认情况下default用户拥有Redis最大权限,我们使用的redis-cli链接时如果没有指定用户,默认也是default。
1.配置ACL
#1.查看当前所有用户
127.0.0.1:6379> ACL LIST
1) "user default on #a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3 ~* +@all"
#2.配置ACL
127.0.0.1:6379> config rewrite
OK #执行config rewrite重写配置后会自动在conf文件最下面新增一行记录配置default的密码和权限
[root@docker ~]# cd /usr/local/redis/conf
[root@docker conf]# cat redis.conf
user default on #a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3 ~* +@all
2.Redis设置密码
在Redis6之前,Redis只有一个default用户也是Redis中的超级管理员用户,如果要将其设置密码,需要修改Redis的配置文件
#设置密码
[root@docker ~]# vim /usr/local/redis/conf/redis.conf
requirepass 123 #可将此内容注释即没有密码,或修改其他密码
#验证
[root@docker ~]# systemctl restart redis
[root@docker ~]# redis-cli
127.0.0.1:6379> set a b
OK
3.使用ACL
我们可以直接在conf配置文件中使用上面default用户ACL这行DSL命令设置用户权限,或者我们也可以配置外部aclfile配置权限。配置aclfile需要先将conf中配置的DSL注释或者删除。因为Redis不允许两种ACL管理方式同时使用,否则在启动Redis的时候会报错
#1.创建用户
127.0.0.1:6379> acl setuser test #创建用户(不设置密码权限默认没有密码没有任何权限)
OK
127.0.0.1:6379> acl list #查看用户
1) "user default on nopass ~* +@all"
2) "user test off -@all"
#2.启用用户
(用户默认情况下,是未激活状态)
127.0.0.1:6379> acl setuser test on #激活用户
OK
127.0.0.1:6379> acl list
1) "user default on nopass ~* +@all"
2) "user test on -@all"
#3.给用户增加密码
127.0.0.1:6379> acl setuser test on >123
OK
127.0.0.1:6379> acl list
1) "user default on nopass ~* +@all" #+@all代表拥有所有权限
2) "user test on #a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3 -@all" #-@all代表所有权限都没有
#4.查看当前用户
127.0.0.1:6379> acl whoami
"default" #可以看做Redis的超级用户,拥有所有权限
#5.登录普通用户,是没有acl权限的
[root@docker ~]# redis-cli
127.0.0.1:6379> auth test 123
OK
127.0.0.1:6379> acl list
(error) NOPERM this user has no permissions to run the 'acl' command or its subcommand
#6.认证
127.0.0.1:6379> auth default 123
OK
127.0.0.1:6379> acl whoami
"default"
#7.给用户设置权限
127.0.0.1:6379> acl setuser test on >123 ~name* +@all #给test用户以name开头的key加上所有权限
OK
127.0.0.1:6379> acl list
1) "user default on nopass ~* +@all"
2) "user test on #a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3 ~name* +@all"
127.0.0.1:6379> acl setuser dashuju #创建大数据用户
OK
127.0.0.1:6379> acl setuser dashuju on >123 ~dashuju* +set +get #给大数据用户的dashuju开头的key授set get权限
OK
127.0.0.1:6379> acl list
1) "user dashuju on #a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3 ~dashuju* -@all +set +get"
2) "user default on nopass ~* +@all"
3) "user test on #a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3 ~name* +@all"
#8.展示所有的用户
127.0.0.1:6379> acl list
1) "user dashuju on #a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3 ~dashuju* -@all +set +get"
2) "user default on nopass ~* +@all"
3) "user test on #a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3 ~name* +@all"
#9.展示所有用户名
127.0.0.1:6379> acl users
1) "dashuju"
2) "default"
3) "test"
#10.展示当前用户
127.0.0.1:6379> acl whoami
"default"
#11.展示当前可授权限
127.0.0.1:6379> acl cat
1) "keyspace"
2) "read"
3) "write"
4) "set"
5) "sortedset"
6) "list"
7) "hash"
8) "string"
9) "bitmap"
10) "hyperloglog"
11) "geo"
#12.查看一个用户所有的key
127.0.0.1:6379> acl getuser test
1) "flags"
2) 1) "on"
2) "allcommands"
3) "passwords"
4) 1) "a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3"
5) "commands"
6) "+@all"
7) "keys"
8) 1) "name*"
#13.删除一个用户
127.0.0.1:6379> acl list
1) "user dashuju on #a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3 ~dashuju* -@all +set +get"
2) "user default on nopass ~* +@all"
3) "user test on #a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3 ~name* +@all"
127.0.0.1:6379> acl deluser dashuju #删除大数据用户
(integer) 1
127.0.0.1:6379> acl list
1) "user default on nopass ~* +@all"
2) "user test on #a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3 ~name* +@all"
4.保存ACL
我们可以使用 acl save 命令将当前服务器中的 ACL 权限持久化到 aclfile 中,如果没持久化就关闭 redis 服务, 那些 ACL 权限就会丢失,因此我们每次授权之后一定要记得 ACL SAVE 将 ACL 权限持久化到 aclfile中。
#1.首先在redis.conf配置文件中启用aclfile文件
[root@docker conf]# vim /usr/local/redis/conf/redis.conf
aclfile /usr/local/redis/conf/users.acl
#2.重启redis,如果没有user.acl文件可以手动创建一个
[root@docker ~]# systemctl restart redis
[root@docker conf]# ll
总用量 84
-rw-r--r-- 1 root root 85015 5月 1 20:29 redis.conf
[root@docker conf]# touch user.acl
[root@docker conf]# ll
总用量 84
-rw-r--r-- 1 root root 85015 5月 1 20:29 redis.conf
-rw-r--r-- 1 root root 0 5月 1 20:31 users.acl
#3.redis-cli连接到server
[root@docker ~]# redis-cli
127.0.0.1:6379> acl list
1) "user default on nopass ~* +@all"
127.0.0.1:6379> acl setuser test on >123 ~name* +@all
OK
127.0.0.1:6379> acl list
1) "user default on nopass ~* +@all"
2) "user test on #a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3 ~name* +@all"
127.0.0.1:6379> acl save
OK
#4.查看文件是否存入内容
[root@docker conf]# ll #没acl save之前
总用量 84
-rw-r--r-- 1 root root 84893 5月 1 20:33 redis.conf
-rw-r--r-- 1 root root 0 5月 1 20:31 user.acl
[root@docker conf]# ll #acl save之前后
总用量 88
-rw-r--r-- 1 root root 84893 5月 1 20:33 redis.conf
-rw-r--r-- 1 root root 124 5月 7 05:41 users.acl #可以看见文件已有大小,内容已存在
5.加载用户信息
我们也可以直接在 aclfile 中修改或新增 ACL 权限,修改之后不会立刻生效,我们可以在 redis 命令行中执行 acl load 将该 aclfile 中的权限加载至 redis 服务中
#1.修改users.acl文件内容
[root@docker conf]# vim users.acl #添加一行tests用户信息
user default on nopass ~* +@all
user test on #a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3 ~name* +@all
user tests on #a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3 ~name* +@all
#2.使用命令重新加载用户信息会生成一个文件中指定的新用户tests
127.0.0.1:6379> acl load
OK
127.0.0.1:6379> acl list
1) "user default on nopass ~* +@all"
2) "user test on #a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3 ~name* +@all"
3) "user tests on #a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3 ~name* +@all"
二、Redis发布与订阅
Redis 通过 PUBLISH 、 SUBSCRIBE 等命令实现了订阅与发布模式, 这个功能提供两种信息机制, 分别是 订阅/发布到频道和订阅/发布到模式, 下文先讨论订阅/发布到频道的实现, 再讨论订阅/发布到模式的实现
1.角色(发布者、消费者、频道)
1)发布者
发布者最主要的工作就是将信息发布到频道中
2)消费者
消费者最主要的功能就是接收消费频道中的信息
3)频道
频道最主要的功能是存储发布者的信息,然后分别发给每一个消费者
2.模型
3.发布订阅队列
1)publish 发布 subscribe 订阅
#1.发布一个test管道内容是123
127.0.0.1:6379> publish test 123
(integer) 1
#2.订阅(实时监控test管道的内容)
127.0.0.1:6379> subscribe test
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "test"
3) (integer) 1
1) "message"
2) "test"
3) "123"
三、Redis集群
由于单机 Redis 存储能力受单机限制,以及无法实现读写操作的负载均衡和读写分离,无法保证高可用。本 篇就来介绍 Redis 集群搭建方案及实现原理,实现 Redis 对数据的冗余备份,从而保证数据和服务的高可用。主 从复制是哨兵和集群的基石,因此我们循序渐进,由浅入深一层层的将 Redis 高可用方案抽丝剥茧展示在大家面 前。
1.主从复制
主从复制,是指将一台 Redis 服务器的数据,复制到其他的 Redis 服务器,主从是哨兵和集群模式能够实施 的基础。前者称为主节点(master),后者称为从节点(slave),数据的复制是单向的,只能由主节点到从节点。默认 情况下,每台 Redis 服务器都是主节点;且一个主节点可以有零个或多个从节点(0+个从节点),但一个从节点只 能有一个主节点。一般主节点负责接收写请求,从节点负责接收读请求,从而实现读写分离。主从一般部署在不 同机器上,复制时存在网络延时问题,使用参数 repl-disable-tcp-nodelay 选择是否关闭 TCP_NODELAY,默认为关闭:
- 关闭:无论数据大小都会及时同步到从节点,占带宽,适用于主从网络好的场景。
- 开启:主节点每隔指定时间合并数据为 TCP 包节省带宽,默认为 40 毫秒同步一次,适用于网络环境复 杂或带宽紧张,如跨机房
2.作用
- 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
- 故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
- 负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务,分担服 务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高 Redis 服务器的并发量。
- 读写分离:主库写、从库读,读写分离不仅可以提高服务器的负载能力,同时可根据需求的变化,改变从库 的数量。
- 高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础。
3.开启主从配置
配置主从可以在命令行或配置文件中配置,上面提到主节点负责写,从节点负责读,因此推荐开启从服务器 的只读配置,否则的话在从节点的写操作不会同步到主节点会导致数据不一致。
#1.查看主从信息
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:0
master_replid:30506cff89f7a58082bcbe39b46e3687f2706dba
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
#1.准备主从环境(一主两从)
[root@docker conf]# cp redis.conf redis-6380.conf
[root@docker conf]# cp redis.conf redis-6381.conf
[root@docker conf]# ll
总用量 256
-rw-r--r-- 1 root root 84893 5月 7 06:24 redis-6380.conf
-rw-r--r-- 1 root root 84893 5月 7 06:24 redis-6381.conf
-rw-r--r-- 1 root root 84893 5月 1 20:33 redis.conf
-rw-r--r-- 1 root root 217 5月 7 05:52 users.acl
#改配置文件对应端口号
[root@docker conf]# vim redis-6380.conf
port 6380
[root@docker conf]# vim redis-6381.conf
port 6381
#将三个配置文件中aclfile一行内容注释掉
#2.启动三个Redis服务
[root@docker ~]# /usr/local/redis/bin/redis-server /usr/local/redis/conf/redis.conf
[root@docker ~]# /usr/local/redis/bin/redis-server /usr/local/redis/conf/redis-6380.conf
[root@docker ~]# /usr/local/redis/bin/redis-server /usr/local/redis/conf/redis-6381.conf
[root@docker ~]# netstat -lntp|grep redis
tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 1297/redis-server 1
tcp 0 0 127.0.0.1:6380 0.0.0.0:* LISTEN 1426/redis-server 1
tcp 0 0 127.0.0.1:6381 0.0.0.0:* LISTEN 1432/redis-server 1
#3.redis-cli连接三个服务端
[root@docker ~]# redis-cli -p 6379
127.0.0.1:6379>
[root@docker conf]# redis-cli -p 6380
127.0.0.1:6380>
[root@docker ~]# redis-cli -p 6381
127.0.0.1:6381>
#4.从节点加入主节点
127.0.0.1:6381> slaveof 127.0.0.1 6379
OK
127.0.0.1:6380> slaveof 127.0.0.1 6379
OK
127.0.0.1:6379> info replication #查看集群信息
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=14,lag=0
slave1:ip=127.0.0.1,port=6381,state=online,offset=14,lag=1
master_replid:6f0e47bb4fedf816f83210956ed1d277d82851b9
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:14
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:14
#5.撤销集群主节点
SLAVEOF NO ONE
config set masteruser #从节点设置主节点用户命令
config get masteruser #从节点查看主节点用户命令
4.主从复制的原理
1、主从复制过程大体分为3个阶段:
- 连接建立阶段(即准备阶段)
- 数据同步阶段
- 命令传播阶段
2、在从节点执行slaveof命令后,复制过程便开始按下面的流程运作:
- 保存主节点信息:配置slaveof之后会在从节点保存主节点信息
- 主从建立socket连接:定时发现主节点以及尝试建立连接
- 发送ping命令:从节点定时发送 ping 给主节点,主节点返回 PONG。若主节点没有返回 PONG 或因阻 塞无法响应导致超时,则主从断开,在下次定时任务时会从新 ping 主节点
- 权限验证:若主节点开启了 ACL 或配置了 requirepass 参数,则从节点需要配置 masteruser 和 masterauth 参数才能保证主从正常连接(密码主从)
- 同步数据集:首次连接,全量同步
- 命令持续复制:全量同步完成后,保持增量同步
3、当节点被当做从节点的时候,需要注意将从节点设置为只读,这样做的目的是为了保证集群的数据一致性。
5.全量复制与部分复制
1)全量复制
redis 全量复制的原理是,首先将 master 本身的 RDB 文件同步给 slave,而在同步期间,master 写入的命令 也会记录下来(master 内部有一个复制缓冲区,会记录同步时 master 新增的写入),当 slave 将 RDB 加载完后, 会通过偏移量的对比将这期间 master 写入的值同步给 slave
2)部分复制
当 master 和 slave 断开连接时,master 会将期间所做的操作记录到复制缓存区当中(可以看成是一个队列, 其大小默认 1M)。待 slave 重连后,slave 会向 master 发送 psync 命令并传入 offset 和 runId,这时候,如果 master 发现 slave 传输的偏移量的值,在缓存区队列范围中,就会将从 offset 开始到队列结束的数据传给 slave,从而达 到同步,降低了使用全量复制的开销
6.全量复制的开销
- bgsave 的开销,每次 bgsave 需要 fork 子进程,对内存和 CP的开销很大
- RDB 文件网络传输的时间(网络带宽)
- 从节点清空数据的时间
- 从节点加载 RDB 的时
- 可能的 AOF 重写时间(如果我们的从节点开启了 AOF,则加载完 RDB 后会对 AOF 进行一个重写,保证 AOF 是最新的)
7.主从复制存在的问题
- 手动故障转移
- 写能力和存储能力受限
四、哨兵
哨兵(sentinel),用于对主从结构中的每一台服务器进行监控,当主节点出现故障后通过投票机制来挑选 新的主节点,并且将所有的从节点连接到新的主节点上。前面的主从是最基础的提升 Redis 服务器稳定性的一种 实现方式,但我们可以看到 master 节点仍然是一台,若主节点宕机,所有从服务器都不会有新的数据进来,如 何让主节点也实现高可用,当主节点宕机的时候自动从从节点中选举一台节点提升为主节点就是哨兵实现的功 能。
1.作用
- 监控:监控主从节点运行情况
- 通知:当监控节点出现故障,哨兵之间进行通讯
- 自动故障转移:当监控到主节点宕机后,断开与宕机主节点连接的所有从节点,然后在从节点中选取一个作为主节点,将其他的从节点连接到这个最新的主节点。最后通知客户端最闲的服务地址
2.哨兵的工作方式
- 每个 Sentinel 以每秒钟一次的频率向它所知的 Master,Slave 以及其他 Sentinel 实例发送一个 PING 命令。
- 如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 own-after-milliseconds 选项所指定 的值,则这个实例会被 Sentinel 标记为主观下线。(主观下线不影响其他功能)
- 如果一个 Master 被标记为主观下线,则正在监视这个 Master 的所有 Sentinel 要以每秒一次的频率确认 Master 的确进入了主观下线状态。
- 当有足够数量的 Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认 Master 的确进入了主观下 线状态,则 Master 会被标记为客观下线。 (客观下线直接杀死)
- 在一般情况下,每个 Sentinel 会以每 10 秒一次的频率向它已知的所有 Master,Slave 发送 INFO 命令。
- 当 Master 被 Sentinel 标记为客观下线时,Sentinel 向下线的 Master 的所有 Slave 发送 INFO 命令的频率会 从 10 秒一次改为每秒一次。
- 若没有足够数量的 Sentinel 同意 Master 已经下线,Master 的客观下线状态就会被移除。 若 Master 重新向Sentinel 的 PING 命令返回有效回复,Master 的主观下线状态就会被移除。
3.哨兵架构图
4.配置哨兵
#1.配置文件详解:
# 端口
port 26379
# 是否后台启动
daemonize yes
# pid 文件路径
pidfile /var/run/redis-sentinel.pid
# 日志文件路径
logfile "/var/log/sentinel.log"
# 定义工作目录
dir /tmp
# 定义 Redis 主的别名, IP, 端口,这里的 2 指的是需要至少 2 个 Sentinel 认为主 Redis 挂了才最终会
采取下一步行为
# sentinel monitor [集群名称] [集群主节点 IP] [断开] []
sentinel monitor mymaster 127.0.0.1 6379 2
# 如果 mymaster 30 秒内没有响应,则认为其主观失效
sentinel down-after-milliseconds mymaster 30000
# 如果 master 重新选出来后,其它 slave 节点能同时并行从新 master 同步数据的台数有多少个,显然该值
越大,所有 slave 节点完成同步切换的整体速度越快,但如果此时正好有人在访问这些 slave,可能造成读取
失败,影响面会更广。最保守的设置为 1,同一时间,只能有一台干这件事,这样其它 slave 还能继续服务,
但是所有 slave 全部完成缓存更新同步的进程将变慢。
sentinel parallel-syncs mymaster 1
# 该参数指定一个时间段,在该时间段内没有实现故障转移成功,则会再一次发起故障转移的操作,单位毫秒
sentinel failover-timeout mymaster 180000
# 不允许使用 SENTINEL SET 设置 notification-script 和 client-reconfig-script。
sentinel deny-scripts-reconfig yes
#1.添加配置文件
[root@docker ~]# cd /usr/local/redis/conf/
[root@docker conf]# vim sentinel-26379.conf
port 26379
daemonize yes
pidfile "/var/run/redis-sentinel-26379.pid"
logfile "/var/log/sentinel-26379.log"
dir "/tmp"
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 2000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes
[root@docker conf]# vim sentinel-26380.conf
port 26380
daemonize yes
pidfile "/var/run/redis-sentinel-26380.pid"
logfile "/var/log/sentinel-26380.log"
dir "/tmp"
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 2000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes
[root@docker conf]# vim sentinel-26381.conf
port 26381
daemonize yes
pidfile "/var/run/redis-sentinel-26381.pid"
logfile "/var/log/sentinel-26381.log"
dir "/tmp"
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 2000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes
#2.启动
[root@docker redis]# ./bin/redis-sentinel ./conf/sentinel-26379.conf
[root@docker redis]# ./bin/redis-sentinel ./conf/sentinel-26380.conf
[root@docker redis]# ./bin/redis-sentinel ./conf/sentinel-26381.conf
#3.验证
[root@docker redis]# ps -ef |grep redis
root 2107 1 0 11:57 ? 00:00:00 ./bin/redis-sentinel *:26379 [sentinel]
root 2113 1 0 11:57 ? 00:00:00 ./bin/redis-sentinel *:26380 [sentinel]
root 2119 1 0 11:57 ? 00:00:00 ./bin/redis-sentinel *:26381 [sentinel]
#4.查看集群主节点监控
[root@docker redis]# redis-cli -p 26379
127.0.0.1:26379> sentinel master mymaster
1) "name"
2) "mymaster"
3) "ip"
4) "127.0.0.1"
5) "port"
6) "6379"
7) "runid"
8) "50d713000de317940645802862c2d53a6c116189" #有runid ID号就证明监控成功
5.三个定时任务
- 每 10 秒每个 sentinel 会对 master 和 slave 执行 info 命令,这个任务达到两个目的: a) 发现 slave 节点 b) 确认主从关系
- 每 2 秒每个 sentinel 通过 master 节点的 channel 交换信息(pub/sub)。master 节点上有一个发布订阅的频 道(sentinel:hello)。sentinel 节点通过__sentinel__:hello 频道进行信息交换(对节点的"看法"和自身的信息), 达成共识。
- 每 1 秒每个 sentinel 对其他 sentinel 和 redis 节点执行 ping 操作(相互监控),这个其实是一个心跳检测, 是失败判定的依据
6.主观下线与客观下线
1)主观下线
所谓主观下线(Subjectively Down, 简称 SDOWN)指的是单个 Sentinel 实例对服务器做出的下线判断,即 单个 sentinel 认为某个服务下线(有可能是接收不到订阅,之间的网络不通等等原因)。如果服务器在 down-after-milliseconds 给定的毫秒数之内, 没有返回 Sentinel 发送的 PING 命令的回复, 或者返回一个错误, 那么 Sentinel 将这个服务器标记为主观下线(SDOWN )。sentinel 会以每秒一次的频率向所有与其建立了命令 连接的实例(master,从服务,其他 sentinel)发 ping 命令,通过判断 ping 回复是有效回复,还是无效回复来判 断实例时候在线(对该 sentinel 来说是“主观在线”)。sentinel 配置文件中的 down-after-milliseconds 设置了判 断主观下线的时间长度,如果实例在 down-after-milliseconds 毫秒内,返回的都是无效回复,那么 sentinel 回认为 该实例已(主观)下线,修改其 flags 状态为 SRI_S_DOWN。如果多个 sentinel 监视一个服务,有可能存在多个 sentinel 的 down-after-milliseconds 配置不同,这个在实际生产中要注意。
2)客观下线
客观下线(Objectively Down, 简称 ODOWN)指的是多个 Sentinel 实例在对同一个服务器做出 SDOWN 判断,并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后,得出的服务器下线判断,然后开启 failover。
客观下线就是说只有在足够数量的 Sentinel 都将一个服务器标记为主观下线之后, 服务器才会被标记为客 观下线(ODOWN)。
只有当 master 被认定为客观下线时,才会发生故障迁移。
当 sentinel 监视的某个服务主观下线后,sentinel 会询问其它监视该服务的 sentinel,看它们是否也认为该服 务主观下线,接收到足够数量(这个值可以配置)的 sentinel 判断为主观下线,既任务该服务客观下线,并对其 做故障转移操作。
客观下线条件只适用于主服务器: 对于任何其他类型的 Redis 实例, Sentinel 在将它们判断为下线前不需 要进行协商, 所以从服务器或者其他 Sentinel 永远不会达到客观下线条件。只要一个 Sentinel 发现某个主服务 器进入了客观下线状态, 这个 Sentinel 就可能会被其他 Sentinel 推选出, 并对失效的主服务器执行自动故障 迁移操