【0】哨兵 sentinel 的作用

  其概念参考:Redis高可用(理论篇) 中的【2】

  【0.1】监控:监控主从是否正常

  【0.2】通知:出现问题时,可以通知相关人员

  【0.3】故障转移:自动主从切换

  【0.4】统一的配置管理:可以从 sentinel 取得主从的地址,统一管理

  如果2台机器,可以在1台机器上布置2个哨兵。3台机器则每个机器各部署一个。

  前置条件:主从搭建部分可以参考上一篇:Redis(1.9)Redis主从复制

    

java 连接 哨兵模式redis redis连接哨兵命令_redis

 

 

 

 

【1】环境

  CentOS7.5

  redis4.0.11

  master1/sentinel1:192.168.135.173

  slave1/sentinel2:192.168.135.174

  slave2/sentinel3:192.168.135.175

  架构:1主2从3哨兵

  安装包软件目录: /soft

  redis目录:/data/redis/

      (1)conf:存放配置文件pid文件,rdb文件  (2)log:日志文件  (3)data:安装目录

#redis的配置文件核心参数如下

daemonize yes
logfile "/data/redis/log/redis.log"
requirepass 123456
bind 0.0.0.0
pidfile /data/redis/conf/redis.pid
dbfilename redis.rdb
dir /data/redis/conf/
timeout 300
port 6379
#如果主从各个库都设置了密码,那么建议密码一致且都配置下面masterauth参数
masterauth 123456

【2】修改哨兵配置文件

【2.1】找到 sentinel.conf 配置文件
cp /soft/redis-4.0.14/sentinel.conf /data/redis/conf/sentinel.conf
#不复制了,直接新建吧,否则会各种报错。。除非你查询下面的选项一个一个修改

【2.2】修改文件(3台机器都这么操作,主库所在机器为173)
vim /data/redis/conf/sentinel.conf
#sentinel 实例之间的通讯端口

sentinel monitor mymaster 192.168.135.173 6379 2
  #sentinel monitor 主服务器别名 主服务器IP 主服务器redis实例端口 客观下线投票数(一般为节点数/2+1)
sentinel down-after-milliseconds mymaster 10000
  #主库多久没有响应后宕机, mymaster 为主服务器别名,10000 单位为毫秒,换算成秒为10秒,即主库10秒没有响应则认为其宕机
sentinel parallel-syncs mymaster 1
  #当故障转移切换后,新主库与其他从库并行同步的数量,如果是1则一个一个同步,同步完一个从库才回去同步下一个从库,如果是2就同时同步2个从库,同步完后继续同步下2个从库
sentinel failover-timeout mymaster 15000
  #故障转移时间,如果故障转移步骤15秒还没有完成,则跳过,随机选择
sentinel auth-pass mymaster 123456
  #定义主库的登录密码
bind 0.0.0.0
port 26379
  #sentinel的端口
daemonize yes
logfile /data/redis/log/sentinel.log
dir /data/redis/conf

 

【2.3】启动哨兵(先启动redis再启动哨兵)
redis-server /data/redis/conf/redis.conf
redis-sentinel /data/redis/conf/sentinel.conf
ps -ef|grep redis
  #这就意味着起来了,如下图

java 连接 哨兵模式redis redis连接哨兵命令_数据_02

【3】查看哨兵状态

redis-cli -h 192.168.135.173 -p 26379 sentinel masters #登录主库哨兵用 sentinel masters 查看
redis-cli -p 26379 -a 123456 -h 192.168.135.173 info #登录主库哨兵,用Info查看

【4】故障转移

【4.1】模拟故障:主库关机

173:shutdown -h now
#然后去其他任意哨兵节点查看日志如下

java 连接 哨兵模式redis redis连接哨兵命令_java 连接 哨兵模式redis_03

 

 由上图选中可见,主库已经切换成175了。

【4.2】核验故障转移

#登录上175

  

java 连接 哨兵模式redis redis连接哨兵命令_服务器_04

 

#登录上174

  

java 连接 哨兵模式redis redis连接哨兵命令_java 连接 哨兵模式redis_05

 

#重启173机器,查看其现在是否把主库转移到175了,且数据同步。至于是down,查看了一下是因为我没有给主库配置文件设置masterauth,设置完重启后即可。

   

java 连接 哨兵模式redis redis连接哨兵命令_redis_06

 

【5】数据丢失与脑裂

redis哨兵主从切换下数据丢失:

(1)异步数据丢失问题:
当集群节点间网络或其他问题导致异步复制延时很高,如果此时master宕机了,
毫无疑问会丢失延时的这段时间的数据当集群节点间网络或其他问题导致异步复制延时很高,
如果此时master宕机了,毫无疑问会丢失延时的这段时间的数据
(2)脑裂问题:
当网络分区变化导致master和slave节点之间无法正常通信时,sentinel哨兵集群会选举
slave为master,此时与之前master连接的client一直发送数据,当我们进行恢复将原master
当做新master的slave节点的时候,那么后来一直发送到原master内存的数据会丢失

【5.1】【解决办法】

解决上述两种数据丢失的问题,redis配置文件中有以下两行:
  min-slaves-to-write 3
  min-slaves-max-lag 10

  意味着至少要有3个slave节点与master保持10秒钟以内的数据同步,否则master就不会
接受新的请求,我们需要采取其他措施来应对

min-slaves-to-write默认情况下是0,min-slaves-max-lag默认情况下是10。

【5.2】【数据丢失问题】   

  以上面配置为例,这两个参数,前者表示至少有3个salve在与master进行复制,后者表示,在所有从库中一旦任意一个slave复制和同步的延迟达到了10s,那么此时master就不会接受任何请求。
我们可以减小min-slaves-max-lag参数的值,这样就可以避免在发生故障时大量的数据丢失,一旦发现延迟超过了该值就不会往master中写入数据。
那么对于client,我们可以采取降级措施,将数据暂时写入本地缓存和磁盘中,在一段时间后重新写入master来保证数据不丢失;也可以将数据写入kafka消息队列,隔一段时间去消费kafka中的数据。
通过上面两个参数的设置我们尽可能的减少数据的丢失,具体的值还需要在特定的环境下进行测试设置。

【5.3】【脑裂问题】

  若一个master出现了脑裂,跟其他slave失去连接,那么开始的两个配置可以确保
若不能继续给指定数量的slave发送数据,而且slave超过10秒没有给自己ack消息,那么就直接拒绝客户端的写请求
这样脑裂后的旧master就不会接受client的新数据,也就避免了数据丢失
上面的配置就确保了,如果跟任何一个slave丢了连接,在10秒后发现没有slave给自己ack,那么就拒绝新的写请求
因此在脑裂场景下,最多就丢失10秒的数据

 

【6】哨兵的常见代码操作

【6.1】哨兵的客户端操作

Sentinel时客户端命令
检查其他 Sentinel 节点的状态,返回 PONG 为正常。
> PING sentinel
显示被监控的所有 主节点 以及它们的状态。
> SENTINEL masters
 

显示指定 主节点 的信息和状态。
> SENTINEL master <master_name>
 

显示指定 主节点 的所有 从节点 以及它们的状态。
> SENTINEL slaves <master_name>
返回指定 主节点 的 IP 地址和 端口。如果正在进行 failover 或者 failover 已经完成,将会显示被提升为 主节点 的 从节点 的 IP 地址和 端口。

> SENTINEL get-master-addr-by-name <master_name>
 

重置名字匹配该 正则表达式 的所有的 主节点 的状态信息,清除它之前的 状态信息,以及 从节点 的信息。
> SENTINEL reset <pattern>
强制当前 Sentinel 节点执行 failover,并且不需要得到其他 Sentinel 节点的同意。但是 failover 后会将 最新的配置 发送给其他 Sentinel 节点。 
    

>SENTINEL failover <master_name>

【6.2】常用命令

sentinel的基本状态信息
INFO

列出所有被监视的主服务器,以及这些主服务器的当前状态
SENTINEL masters

列出指定主redis的从节点状态情况
SENTINEL slaves <master-name>

列出指定主redis的监控哨兵信息,不包含他自己
SENTINEL sentinels <master-name>

返回给定名字的主服务器的 IP 地址和端口号
SENTINEL get-master-addr-by-name <master-name>

重置所有名字和给定模式 pattern 相匹配的主服务器。重置操作清除主服务器目前的所有状态,包括正在执行中的故障转移,并移除目前已经发现和关联的,主服务器的所有从服务器和 Sentinel 。
SENTINEL <master-name>

当主服务器失效时 在不询问其他 Sentinel 意见的情况下,强制开始一次自动故障迁移,但是它会给其他sentinel发送一个最新的配置,其他sentinel会根据这个配置进行更新
SENTINEL failover <master-name>

检查当前在线的哨兵节点。如果一共有5个节点,设置4票,但检查后只有3节点在线,那一直无法进行监控切换
sentinel ckquorum <master-name>

将配置强制刷新到本地文件
sentinel flushconfig

取消当前哨兵对某主节点的监控
sentinel remove <master name>

 

二、相关实践

指定一个从做新主

  有时候需要将当前主节点机器下线,并指定一个高一些性能的从节点接替

  将其它从节点的slave-priority配置为0,然后在随意一台 Setinel 执行sentinel failover <master name>来手动强行切换主从

  配置后,需要再将其它节点的slave-priority再变回来,否则会影响之后的切换

添加一个从节点

  直接在新的从节点填写主节点信息,让他作为从节点启动即可。每10秒 Setinel 会发送info去检测主从信息

添加一个Setinel节点

  直接添加sentinel monitor mymaster 127.0.0.1 6379 1主节点的配置即可

【6.3】哨兵的主要配置文件参数

# redis进程是否以守护进程的方式运行,yes为是,no为否(不以守护进程的方式运行会占用一个终端)。
daemonize no
# 指定redis进程的PID文件存放位置
pidfile /var/run/redis.pid
# redis进程的端口号
port 6379
# 绑定的主机地址
bind 127.0.0.1
# 客户端闲置多长时间后关闭连接,默认此参数为0即关闭此功能
timeout 300
# redis日志级别,可用的级别有debug.verbose.notice.warning
loglevel verbose
# log文件输出位置,如果进程以守护进程的方式运行,此处又将输出文件设置为stdout的话,就会将日志信息输出到/dev/null里面去了
logfile stdout
# 设置数据库的数量,默认为0可以使用select <dbid>命令在连接上指定数据库id
databases 16
# 指定在多少时间内刷新次数达到多少的时候会将数据同步到数据文件
save <seconds> <changes>
# 指定存储至本地数据库时是否压缩文件,默认为yes即启用存储
rdbcompression yes
# 指定本地数据库文件名
dbfilename dump.db
# 指定本地数据问就按存放位置
dir ./
# 指定当本机为slave服务时,设置master服务的IP地址及端口,在redis启动的时候他会自动跟master进行数据同步
slaveof <masterip> <masterport>
# 当master设置了密码保护时,slave服务连接master的密码
masterauth <master-password>
# 设置redis连接密码,如果配置了连接密码,客户端在连接redis是需要通过AUTH<password>命令提供密码,默认关闭
requirepass footbared
# 设置同一时间最大客户连接数,默认无限制。redis可以同时连接的客户端数为redis程序可以打开的最大文件描述符,如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回 max number of clients reached 错误信息
maxclients 128
# 指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key。当此方法处理后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis新的vm机制,会把Key存放内存,Value会存放在swap区
maxmemory<bytes>
# 指定是否在每次更新操作后进行日志记录,Redis在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为redis本身同步数据文件是按上面save条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认为no。
appendonly no
# 指定跟新日志文件名默认为appendonly.aof
appendfilename appendonly.aof
# 指定更新日志的条件,有三个可选参数 - no:表示等操作系统进行数据缓存同步到磁盘(快),always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全), everysec:表示每秒同步一次(折衷,默认值);
appendfsync everysec

 

【附录】报错处理

(1)Duplicated master name 

    

java 连接 哨兵模式redis redis连接哨兵命令_服务器_07

 

   意思是说我们重复定义了2个不同值的 master name,这里推测应该是原本配置文件的配置和我们这里的配置不一样,导致冲突了。

  找一下之后,果然有,注释掉他

    

java 连接 哨兵模式redis redis连接哨兵命令_redis_08


 

  修改后,依然有其他选项值出现相关问题

     

java 连接 哨兵模式redis redis连接哨兵命令_数据_09

 

   最终解决办法,删掉原本的配置,只留下我们需要的配置。