redis哨兵模式应用

Windows版本redis高可用方案探究

2019-12-12阅读 1220

前言

本篇文章专注于讲解redis在windows环境下使用Redis Sentinel(哨兵)实现高可用方案。

想要在windows环境下实现redis高可用,先要准备以下材料或知识点。

  1. redis 3.2.100 目前在windows版本最新的redis是3.2.100,可以到这里下载
  2. Redis Sentinel redis本身不支持高可用方案,通过sentinel对redis进行监控及动态调节等。

搭建redis主从

下载的压缩文件内容如下图所示。

 

具体结构如下图所示

 

应用层连接redis集群,集群包括3个redis服务(1主2从)和3个哨兵。

哨兵用于监控主redis可用性。若长时间不可用,则哨兵进行投票选举出新的主redis。原来的主redis降级为从redis。哨兵会将所有redis的配置进行自动更新。

配置主redis-28380

将redis复制一份。一个文件夹用于部署redis服务,一个文件夹用于部署哨兵。

 

规定redis服务端口为28380~28382。将redis.windiws-service.config改名为redis-28380.conf。打开进行修改。

  1. 修改绑定端口 注释掉bind 127.0.0.1,默认为监听所有ip。
  2. 将保护模式关闭 修改protected-mode yesprotected-mode no,默认redis开启了保护模式,只允许本机通过127.0.0.1访问,其他ip无法访问。
  3. 修改监听端口 修改port 6379port 28380
  4. 修改日志等级 修改loglevel debugloglevel notice
  5. 修改日志文件名 修改logfile "server_log.txt"logfile "server_log_28380.txt"
  6. 修改windows日志的事件名 修改syslog-ident redissyslog-ident "redis-28380"
  7. 修改不保存rdb文件 注释掉一下三行,由于rdb会每次全量写文件,当数据量较大时会对redis稳定性造成一定影响,尤其是rbd保存失败时会一定时间内拒绝写入数据。 save 900 1 save 300 10 save 60 10000
  8. 创建密码 修改# requirepass foobaredrequirepass "test1" 新增masterauth "test1"

若要设置密码,单台redis设置requirepass即可。集群redis必须同时设置requirepassmasterauth。若主redis没有设置masterauth当它变为从时,就认为主无密码。若从redis没有设置requirepass,当它变为主时,会没有密码。以上两种情况自动切换都无法自动连接到新的主。 9. 启用aof保存 修改appendonly noappendonly yes 修改appendfilename "appendonly.aof"appendfilename "appendonly_28380.aof"aof写入的是redis命令,每次向文件后面添加,因此对IO性能影响较小。最坏情况主redis丢失1s的数据。

配置改好后保存,这个当作主redis的配置。将改配置复制2份,分别改名为redis-28381.conf和redis-28382.conf

配置从redis-23381

  1. 修改监听端口 修改port 28380port 28381
  2. 修改日志文件名 修改logfile "server_log-28380.txt"logfile "server_log_28381.txt"
  3. 修改windows日志的事件名 修改syslog-ident "redis-28380"syslog-ident "redis-28381"
  4. 修改从库对应的主库ip 修改# slaveof <masterip> <masterport>slaveof 127.0.0.1 28380 23880做为主库,填写的就是28380的端口
  5. 修改从库竞选主库优先级 修改slave-priority 100slave-priority 99将每个从库设置为不通的优先级,数字较低的优先被竞选为主库。
  6. 修改aof保存的文件名 修改appendfilename "appendonly_28380.aof"appendfilename "appendonly_28381.aof"

配置从redis-23382

  1. 修改监听端口 修改port 28380port 28382
  2. 修改日志文件名 修改logfile "server_log-28380.txt"logfile "server_log_28382.txt"
  3. 修改windows日志的事件名 修改syslog-ident "redis-28380"syslog-ident "redis-28382"
  4. 修改从库对应的主库ip 修改# slaveof <masterip> <masterport>slaveof 127.0.0.1 28380 23880做为主库,填写的就是28380的端口
  5. 修改从库竞选主库优先级 修改slave-priority 100slave-priority 98将每个从库设置为不通的优先级,数字较低的优先被竞选为主库。
  6. 修改aof保存的文件名 修改appendfilename "appendonly_28380.aof"appendfilename "appendonly_28382.aof"

将redis部署为服务

通过命令redis-server --service-install 配置名 --service-name 服务名 将redis安装为服务。

先cd到redis所在目录,在cmd命令行中输入一下三条语句将三个redis安装成功为windows服务。

redis-server --service-install redis-28380.conf --service-name redis-28380
redis-server --service-install redis-28381.conf --service-name redis-28381
redis-server --service-install redis-28382.conf --service-name redis-28382

设置服务别名是为了在服务中能更好的看到哪个是哪个服务,否则默认都是redis服务。

 

启动redis

可以直接在服务中右键启动或者通过命令redis-server --service-start --service-name 服务名 启动指定服务。

通过redis-cli 连接到各个redis服务。

F:\Study\redis> redis-cli -p 28380 -a test1
127.0.0.1:28380> info Replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=28382,state=online,offset=183,lag=1
slave1:ip=127.0.0.1,port=28381,state=online,offset=183,lag=1
master_repl_offset:183
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:182

可以看到我们的主从配置已经生效了。

连接到从库28381

F:\Study\redis>  redis-cli -p 28381 -a test1
127.0.0.1:28381>  info Replication
# Replication
role:slave
master_host:127.0.0.1
master_port:28380
master_link_status:up
master_last_io_seconds_ago:9
master_sync_in_progress:0
slave_repl_offset:323
slave_priority:99
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

连接到从库28382

F:\Study\redis>  redis-cli -p 28382 -a test1
127.0.0.1:28382> info Replication
# Replication
role:slave
master_host:127.0.0.1
master_port:28380
master_link_status:up
master_last_io_seconds_ago:8
master_sync_in_progress:0
slave_repl_offset:379
slave_priority:99
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

现在我们往主库写入数据会自动并主动同步到从库。

配置中默认配了以下配置了slave-read-only yes,从库是只读的,不允许写入。

配置哨兵

设置三个哨兵端口为 24381~24383

配置哨兵24381

dir ./
logfile "sentinel.28481.txt"
bind 127.0.0.1
port 28481
sentinel monitor master 127.0.0.1 28380 2
sentinel down-after-milliseconds master 5000
sentinel failover-timeout master 30000
sentinel auth-pass 127.0.0.1 28380 test1
  • sentinel monitor master 127.0.0.1 28380 2 设置主redis的别名为master,后面都通过master表示主redis。后面的2表示2个哨兵检测到主redis挂了即为挂了,需要重新选举出新的主redis,而原来的主redis降级为从redis。
  • sentinel down-after-milliseconds master 5000 哨兵多久连不上主redis即认为它挂了
  • sentinel failover-timeout master 30000 投票选举超时时间,超过时间没有选出则该轮投票失败。
  • sentinel auth-pass master test1 主redis的密码 。

由于哨兵只能设置主的密码,因此主从的密码应该设置为一样的。 由于我在本地测试直接使用127.0.0.1,正常情况下redis和哨兵部署集群肯定是在不通机子上。哨兵则必须绑定ip,否则哨兵自动切换主从。通过在哨兵的配置中加入bind XXXX。 配置哨兵24382

dir ./
logfile "sentinel.28482.txt"
bind 127.0.0.1
port 28482
sentinel monitor master 127.0.0.1 28380 2
sentinel down-after-milliseconds master 5000
sentinel failover-timeout master 30000
sentinel auth-pass 127.0.0.1 28380 test1

配置哨兵24383

dir ./
logfile "sentinel.28483.txt"
bind 127.0.0.1
port 28483
sentinel monitor master 127.0.0.1 28380 2
sentinel down-after-milliseconds master 5000
sentinel failover-timeout master 30000
sentinel auth-pass 127.0.0.1 28380 test1

启动哨兵

通过命令redis-server.exe 配置 --sentinel 启动哨兵

redis-server redis-sentinel-28481.conf --sentinel
redis-server redis-sentinel-28482.conf --sentinel
redis-server redis-sentinel-28483.conf --sentinel

启动哨兵28481后查看日志

[8464] 21 Nov 02:02:05.258 # +tilt #tilt mode entered
[8464] 21 Nov 08:33:01.513 # +tilt #tilt mode entered
[8464] 21 Nov 08:33:31.561 # -tilt #tilt mode exited
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 3.2.100 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                   
 (    '      ,       .-`  | `,    )     Running in sentinel mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 28481
 |    `-._   `._    /     _.-'    |     PID: 22332
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           http://redis.io        
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'                                               

[22332] 05 Jan 12:01:48.399 # Sentinel ID is 48693b2911456ef3da6ebfd14d1adf46e76fbb8b
[22332] 05 Jan 12:01:48.399 # +monitor master master 127.0.0.1 28382 quorum 2
[22332] 05 Jan 12:01:53.399 # +sdown sentinel ce50397a76e2e3ca165ce407859cbc94d7caf504 127.0.0.1 28482 @ master 127.0.0.1 28382
[22332] 05 Jan 12:01:53.399 # +sdown sentinel 162c66f370550a9926b794abecfb431cf3f8bcc9 127.0.0.1 28483 @ master 127.0.0.1 28382
[22332] 05 Jan 12:02:13.404 # +sdown master master 127.0.0.1 28382

同时启动完会自动在哨兵的配置文件中生成一些配置,完整的redis-sentinel-28481.conf配置如下

dir "F:\\Study\\redis\\redis-sentinel"
logfile "sentinel.28481.txt"
port 28481
sentinel myid 48693b2911456ef3da6ebfd14d1adf46e76fbb8b
sentinel monitor master 127.0.0.1 28381 2
sentinel down-after-milliseconds master 5000
sentinel failover-timeout master 30000
# Generated by CONFIG REWRITE
sentinel auth-pass master test1
sentinel config-epoch master 11
sentinel leader-epoch master 11
sentinel known-slave master 127.0.0.1 28382
sentinel known-slave master 127.0.0.1 28380
sentinel known-sentinel master 127.0.0.1 28482 ce50397a76e2e3ca165ce407859cbc94d7caf504
sentinel known-sentinel master 127.0.0.1 28483 162c66f370550a9926b794abecfb431cf3f8bcc9
sentinel current-epoch 11

启动后会为哨兵生成一个id,同时会记录一些关键信息。

主从自动切换

将主redis关闭,让哨兵自动切换主从。

哨兵24381日志

[22332] 05 Jan 12:34:49.286 # +sdown master master 127.0.0.1 28380
[22332] 05 Jan 12:34:49.295 # +new-epoch 16
[22332] 05 Jan 12:34:49.296 # +vote-for-leader ce50397a76e2e3ca165ce407859cbc94d7caf504 16
[22332] 05 Jan 12:34:49.363 # +odown master master 127.0.0.1 28380 #quorum 3/2
[22332] 05 Jan 12:34:49.363 # Next failover delay: I will not start a failover before Sat Jan 05 12:35:49 2019
[22332] 05 Jan 12:34:50.397 # +config-update-from sentinel ce50397a76e2e3ca165ce407859cbc94d7caf504 127.0.0.1 28482 @ master 127.0.0.1 28380
[22332] 05 Jan 12:34:50.397 # +switch-master master 127.0.0.1 28380 127.0.0.1 28382
[22332] 05 Jan 12:34:50.397 * +slave slave 127.0.0.1:28381 127.0.0.1 28381 @ master 127.0.0.1 28382
[22332] 05 Jan 12:34:50.397 * +slave slave 127.0.0.1:28380 127.0.0.1 28380 @ master 127.0.0.1 28382
[22332] 05 Jan 12:34:55.442 # +sdown slave 127.0.0.1:28380 127.0.0.1 28380 @ master 127.0.0.1 28382

哨兵24382日志

[8760] 05 Jan 12:34:49.237 # +sdown master master 127.0.0.1 28380
[8760] 05 Jan 12:34:49.292 # +odown master master 127.0.0.1 28380 #quorum 2/2
[8760] 05 Jan 12:34:49.292 # +new-epoch 16
[8760] 05 Jan 12:34:49.292 # +try-failover master master 127.0.0.1 28380
[8760] 05 Jan 12:34:49.293 # +vote-for-leader ce50397a76e2e3ca165ce407859cbc94d7caf504 16
[8760] 05 Jan 12:34:49.296 # 162c66f370550a9926b794abecfb431cf3f8bcc9 voted for ce50397a76e2e3ca165ce407859cbc94d7caf504 16
[8760] 05 Jan 12:34:49.296 # 48693b2911456ef3da6ebfd14d1adf46e76fbb8b voted for ce50397a76e2e3ca165ce407859cbc94d7caf504 16
[8760] 05 Jan 12:34:49.394 # +elected-leader master master 127.0.0.1 28380
[8760] 05 Jan 12:34:49.394 # +failover-state-select-slave master master 127.0.0.1 28380
[8760] 05 Jan 12:34:49.470 # +selected-slave slave 127.0.0.1:28382 127.0.0.1 28382 @ master 127.0.0.1 28380
[8760] 05 Jan 12:34:49.470 * +failover-state-send-slaveof-noone slave 127.0.0.1:28382 127.0.0.1 28382 @ master 127.0.0.1 28380
[8760] 05 Jan 12:34:49.541 * +failover-state-wait-promotion slave 127.0.0.1:28382 127.0.0.1 28382 @ master 127.0.0.1 28380
[8760] 05 Jan 12:34:50.341 # +promoted-slave slave 127.0.0.1:28382 127.0.0.1 28382 @ master 127.0.0.1 28380
[8760] 05 Jan 12:34:50.341 # +failover-state-reconf-slaves master master 127.0.0.1 28380
[8760] 05 Jan 12:34:50.396 * +slave-reconf-sent slave 127.0.0.1:28381 127.0.0.1 28381 @ master 127.0.0.1 28380
[8760] 05 Jan 12:34:51.380 * +slave-reconf-inprog slave 127.0.0.1:28381 127.0.0.1 28381 @ master 127.0.0.1 28380
[8760] 05 Jan 12:34:51.446 # -odown master master 127.0.0.1 28380
[8760] 05 Jan 12:34:52.393 * +slave-reconf-done slave 127.0.0.1:28381 127.0.0.1 28381 @ master 127.0.0.1 28380
[8760] 05 Jan 12:34:52.468 # +failover-end master master 127.0.0.1 28380
[8760] 05 Jan 12:34:52.468 # +switch-master master 127.0.0.1 28380 127.0.0.1 28382
[8760] 05 Jan 12:34:52.469 * +slave slave 127.0.0.1:28381 127.0.0.1 28381 @ master 127.0.0.1 28382
[8760] 05 Jan 12:34:52.469 * +slave slave 127.0.0.1:28380 127.0.0.1 28380 @ master 127.0.0.1 28382
[8760] 05 Jan 12:34:57.562 # +sdown slave 127.0.0.1:28380 127.0.0.1 28380 @ master 127.0.0.1 28382

哨兵24383日志

[26484] 05 Jan 12:34:49.161 # +sdown master master 127.0.0.1 28380
[26484] 05 Jan 12:34:49.294 # +new-epoch 16
[26484] 05 Jan 12:34:49.295 # +vote-for-leader ce50397a76e2e3ca165ce407859cbc94d7caf504 16
[26484] 05 Jan 12:34:50.284 # +odown master master 127.0.0.1 28380 #quorum 3/2
[26484] 05 Jan 12:34:50.284 # Next failover delay: I will not start a failover before Sat Jan 05 12:35:49 2019
[26484] 05 Jan 12:34:50.397 # +config-update-from sentinel ce50397a76e2e3ca165ce407859cbc94d7caf504 127.0.0.1 28482 @ master 127.0.0.1 28380
[26484] 05 Jan 12:34:50.397 # +switch-master master 127.0.0.1 28380 127.0.0.1 28382
[26484] 05 Jan 12:34:50.397 * +slave slave 127.0.0.1:28381 127.0.0.1 28381 @ master 127.0.0.1 28382
[26484] 05 Jan 12:34:50.397 * +slave slave 127.0.0.1:28380 127.0.0.1 28380 @ master 127.0.0.1 28382
[26484] 05 Jan 12:34:55.437 # +sdown slave 127.0.0.1:28380 127.0.0.1 28380 @ master 127.0.0.1 28382

具体投票过程这里不做具体分析。

当选出新的主redis,哨兵会对redis配置进行更新,将主redis的slaveof XXX XXX配置删除,将从的slaveof XXX XXX设置为主的地址。同时哨兵会监控redis28380。当28380恢复后会将slaveof XXX XXX添加到它的配置中。

连接到28382查看

127.0.0.1:28382> info Replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=28381,state=online,offset=193307,lag=1
slave1:ip=127.0.0.1,port=28380,state=online,offset=193441,lag=1
master_repl_offset:193575
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:193574

动态新增从库

若我们此时动态新增一个从redis,端口为28383,则复制一个28380的配置进行修改,将优先级改为97。并启动服务即可。

redis-28383日志如下

[14048] 05 Jan 12:55:20.421 * Redis 3.2.100 (00000000/0) 64 bit, standalone mode, port 28383, pid 14048 ready to start.
[14048] 05 Jan 12:55:20.422 # Server started, Redis version 3.2.100
[14048] 05 Jan 12:55:20.423 * The server is now ready to accept connections on port 28383
[14048] 05 Jan 12:55:20.424 * Connecting to MASTER 127.0.0.1:28382
[14048] 05 Jan 12:55:20.426 * MASTER <-> SLAVE sync started
[14048] 05 Jan 12:55:20.427 * Non blocking connect for SYNC fired the event.
[14048] 05 Jan 12:55:20.428 * Master replied to PING, replication can continue...
[14048] 05 Jan 12:55:20.428 * Partial resynchronization not possible (no cached master)
[14048] 05 Jan 12:55:20.432 * Full resync from master: 2c344529e4acdc44cd311818fe8179825877a9f4:241347
[14048] 05 Jan 12:55:20.653 * MASTER <-> SLAVE sync: receiving 107 bytes from master
[14048] 05 Jan 12:55:20.655 * MASTER <-> SLAVE sync: Flushing old data
[14048] 05 Jan 12:55:20.655 * MASTER <-> SLAVE sync: Loading DB in memory
[14048] 05 Jan 12:55:20.656 * MASTER <-> SLAVE sync: Finished with success
[14048] 05 Jan 12:55:20.660 * Background append only file rewriting started by pid 29392
[14048] 05 Jan 12:55:20.827 * AOF rewrite child asks to stop sending diffs.
[14048] 05 Jan 12:55:20.927 # fork operation complete
[14048] 05 Jan 12:55:20.928 * Background AOF rewrite terminated with success
[14048] 05 Jan 12:55:20.929 * Residual parent diff successfully flushed to the rewritten AOF (0.00 MB)
[14048] 05 Jan 12:55:20.931 * Background AOF rewrite finished successfully

再看下28382的主从连接信息

127.0.0.1:28382> info Replication
# Replication
role:master
connected_slaves:3
slave0:ip=127.0.0.1,port=28381,state=online,offset=268634,lag=0
slave1:ip=127.0.0.1,port=28380,state=online,offset=268768,lag=0
slave2:ip=127.0.0.1,port=28383,state=online,offset=268634,lag=0
master_repl_offset:268768
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:268767

哨兵也能检测到新的从库连接

`

22332 05 Jan 12:55:25.420 * +slave slave 127.0.0.1:28383 127.0.0.1 28383 @ master 127.0.0.1 28382`

通过上述配置,就完成了redis高可用方案。

程序连接redis高可用

我使用的是StackExchange.Redis连接redis。

它本身就支持主从连接,在建立连接的时候输入多个连接地址接口。由于从库不允许写入。因此它能辨别出哪个是主哪个是从。主从切换后写入数据的时候重新判定哪个是主库。

  1. 通过代码设置redis地址 ConfigurationOptions options = ConfigurationOptions.Parse("password=test1"); options.EndPoints.Add("127.0.0.1", 28380); options.EndPoints.Add("127.0.0.1", 28381); options.EndPoints.Add("127.0.0.1", 28382);
  2. 通过配置字符串设置 ConfigurationOptions options = ConfigurationOptions.Parse("127.0.0.1:28380,127.0.0.1:28381,127.0.0.1:28382,keepAlive=5,password=test1");总结

通过该篇文章详细的探究了window下的redis高可用方案如何实现。本文对具体配置没有做深入探究,仅仅为了抓住重点,具体配置其他的文档都介绍的比较详细,但是一些细节并没有说明,通过该片文章将reids高可用的坑都填满。若有错误,欢迎指正。

实例可以从这里下载

 

问题反馈

1、主从无法切换

检查配置文件 :

一、确保sentinel.conf配置文件不是完全拷贝的,这个文件会在运行之后自动添加一些数据,导致拷贝之后没有删除无法自动切换主从

二、确保 redis.conf中两个属性 requirepass masterauth 这两个密码配置都有 ,sentinel.conf中 sentinel auth-pass mymaster (password) 存在。为了主从能自由切换请给主从都配置好密码,而且要设置相同的密码(完成切换后,因为从没有配置masterauth,导致重启后连接不上主


三、每个redis.conf配置文件中 slaveof ip port 确保从redis配置中都有该项配置,确保sentinel.conf中
sentinel monitor mymaster masterip + port + num(该项为数字 一般设为 1 或者2 ) 确保该项在三台服务器上都一致


四、通过redis-cli 客户端连接上redis 进行auth认证 输入命令 info查看master以及slave情况

2. 远程客户端无法连接redis

 redis版本在3.2.x之后出现这个问题的 一定是没有把这个配置好 protected-mode no ; bind 注释掉

 protected-mode no(允许所有地址的访问,关闭了保护模式,便于测试,如果是yes则只允许本机,默认是yes。文档显示设置了bind和密码的话该设置不会生效) 

3.127.0.0.1的问题

sentine.conf配置解释

port 26379
protected-mode no(允许所有地址的访问,如果是yes则只允许本机,默认是yes。文档显示设置了bind和密码的话该设置不会生效)
logfile "/home/session/redis/logs/redis_26379.log"(日志地址,如果配置了该地址,则不会打印堆栈。)

//(sentinel的唯一ID)

sentinel myid e2a313dd66f8e8df829628d4580d77f840ebb068
sentinel monitor mymaster 172.18.50.117 7379 1

// 当前Sentinel节点监控 172.18.50.117:7379 这个主节点

// 2代表判断主节点失败至少需要2个Sentinel节点节点同意

// mymaster是主节点的别名

sentinel monitor mymaster 172.18.50.117 7379 2

//每个Sentinel节点都要定期PING命令来判断Redis数据节点和其余Sentinel节点是否可达,如果超过30000毫秒且没有回复,则判定不可达

sentinel down-after-milliseconds mymaster 30000

//当Sentinel节点集合对主节点故障判定达成一致时,Sentinel领导者节点会做故障转移操作,选出新的主节点,原来的从节点会向新的主节点发起复制操作,限制每次向新的主节点发起复制操作的从节点个数为1

//同步时允许最多几台slave同步master,数字越小同步时间越久,在同步的过程中不能提供服务,所以配置大了也不好,依情况而定)

sentinel parallel-syncs mymaster 1

//故障转移超时时间为180000毫秒

sentinel failover-timeout mymaster 180000

daemonize yes(守护线程模式)

dir "/tmp"

# Generated by CONFIG REWRITE   
maxclients 4064(自动生成,也可以自己配置)
sentinel failover-timeout mymaster 150000(多少毫米未切换完成则判定失败)
sentinel auth-pass mymaster phFUND_linux_redis(密码要配置)
sentinel config-epoch mymaster 4(自动生成)
sentinel leader-epoch mymaster 4(自动生成)
sentinel known-slave mymaster 172.18.50.117 6379(自动生成)
sentinel known-slave mymaster 172.18.50.117 7381(自动生成)
sentinel known-slave mymaster 172.18.50.117 7380(自动生成)
sentinel current-epoch 4(自动生成)

测试命令

sentienl常用命令:

1)进入sentinel : redis-cli -h <IP> -p <port>

2)查看集群所有master的状态:sentinel masters

3)查看某个master的所有slave:sentinel slaves <mastername>

4)使用PING命令检测是否启动

5)redis-cli -h 127.0.0.1 -p 26379 INFO Sentinel

➜   redis-cli -h 127.0.0.1 -p 6379 ping
PONG

 

 故障转移实验

先查看一下节点的进程pid

➜   ps -aux | grep redis
root     18225  0.1  0.0  40208 11212 ?        Ssl  22:10   0:05 redis-server 127.0.0.1:6379
root     18234  0.0  0.0  38160  8364 ?        Ssl  22:10   0:04 redis-server 127.0.0.1:6380
root     18244  0.0  0.0  38160  8308 ?        Ssl  22:10   0:04 redis-server 127.0.0.1:6381
root     20568  0.1  0.0  38160  8460 ?        Ssl  23:05   0:02 redis-sentinel *:26379 [sentinel]
root     20655  0.1  0.0  38160  8296 ?        Ssl  23:07   0:02 redis-sentinel *:26380 [sentinel]
root     20664  0.1  0.0  38160  8312 ?        Ssl  23:07   0:02 redis-sentinel *:26381 [sentinel]

 

我们干掉端口6379的主节点。

➜   sudo kill -9 18225
➜   ps -aux | grep redis
root     18234  0.0  0.0  38160  8364 ?        Ssl  22:10   0:05 redis-server 127.0.0.1:6380
root     18244  0.0  0.0  38160  8308 ?        Ssl  22:10   0:05 redis-server 127.0.0.1:6381
root     20568  0.1  0.0  38160  8460 ?        Ssl  23:05   0:03 redis-sentinel *:26379 [sentinel]
root     20655  0.1  0.0  38160  8296 ?        Ssl  23:07   0:03 redis-sentinel *:26380 [sentinel]
root     20664  0.1  0.0  38160  8312 ?        Ssl  23:07   0:03 redis-sentinel *:26381 [sentinel]

此时,Redis Sentinel对主节点进行客观下线(Objectively Down, 简称 ODOWN)的判断,确认主节点不可达,则通知从节点中止复制主节点的操作。

这里写图片描述

当主节点下线时长超过配置的下线时长30000秒,Redis Sentinel执行故障转移操作。

此时,我们查看一下Sentinel节点监控的主节点信息:

127.0.0.1:26379> sentinel masters 
1)  1) "name"
    2) "mymaster"
    3) "ip"
    4) "127.0.0.1"
    5) "port"
    6) "6380"           //可以看到主节点已经成为6380端口的节点
    7) "runid"
    8) "084850ab4ff6c2f2502b185c8eab5bdd25a26ce2"
    9) "flags"
   10) "master"
    ..............

看一下Sentinel节点监控的从节点信息:

127.0.0.1:26379> sentinel slaves mymaster
1)  1) "name"
    2) "127.0.0.1:6379"             //ip:port
    3) "ip"
    4) "127.0.0.1"
    5) "port"
    6) "6379"
    7) "runid"
    8) ""
    9) "flags"
   10) "s_down,slave,disconnected"  //端口6379的原主节点已经断开了连接
   ..............
2)  1) "name"
    2) "127.0.0.1:6381"             
    3) "ip"
    4) "127.0.0.1"
    5) "port"
    6) "6381"
    7) "runid"
    8) "24495fe180e4fd64ac47467e0b2652894406e9e4"
    9) "flags"
   10) "slave"                      //本来的从节点,还是从节点的role
    ..............

由以上信息可得,端口为6380的Redis数据节点成为新的主节点,端口为6379的旧主节点断开连接。如图所示:

这里写图片描述

我们在试着重启端口6379的数据节点。

➜   sudo redis-server redis-6379.conf 
➜   ps -aux | grep redis              
root     18234  0.1  0.0  40208 11392 ?        Ssl  5月22   0:06 redis-server 127.0.0.1:6380
root     18244  0.1  0.0  40208 10356 ?        Ssl  5月22   0:07 redis-server 127.0.0.1:6381
root     20568  0.1  0.0  38160  8460 ?        Ssl  5月22   0:05 redis-sentinel *:26379 [sentinel]
root     20655  0.1  0.0  38160  8296 ?        Ssl  5月22   0:05 redis-sentinel *:26380 [sentinel]
root     20664  0.1  0.0  38160  8312 ?        Ssl  5月22   0:05 redis-sentinel *:26381 [sentinel]
menwen   22475  0.0  0.0  14216  5920 pts/2    S+   5月22   0:00 redis-cli -p 26379
// 6379的数据节点已重启
root     22617  0.0  0.0  38160  8304 ?        Ssl  00:00   0:00 redis-server 127.0.0.1:6379   

看看发生什么:

127.0.0.1:26379> sentinel slaves mymaster
1)  1) "name"
    2) "127.0.0.1:6379"     //6379端口的节点重启后,变成了"活"的从节点
    3) "ip"
    4) "127.0.0.1"
    5) "port"
    6) "6379"
    7) "runid"
    8) "de1b5c28483cf150d9550f8e338886706e952346"
    9) "flags"
   10) "slave"
    ..............
2)  1) "name"               //6381端口的节点没有变化,仍是从节点
    2) "127.0.0.1:6381"
    ..............

他被降级成为端口6380的从节点。

这里写图片描述

从上面的逻辑架构和故障转移试验中,可以看出Redis Sentinel的以下几个功能。

  • 监控Sentinel节点会定期检测Redis数据节点和其余Sentinel节点是否可达。
  • 通知Sentinel节点会将故障转移通知给应用方。
  • 主节点故障转移:实现从节点晋升为主节点并维护后续正确的主从关系。
  • 配置提供者:在Redis Sentinel结构中,客户端在初始化的时候连接的是Sentinel节点集合,从中获取主节点信息。
  •  

项目和环境介绍

因为公司的测试环境的Redis老是挂,导致系统启动报错。一直没人管,所幸我自己看看。

问题:一台master挂掉,无法进行故障转移,不能选举从。

先上个测试环境的架构图: 

分片规则是在应用层实现的,比较简单,直接用hash值对接连数取模计算节点,没有用一致性hash,扩展性很差。

一般不建议这样配置,一个哨兵挂了,会导致两个主从集群的监控都出问题。

建议用这个作者的设置:https://blog.csdn.net/men_wen/article/details/72724406

 

因为测试环境只有两台服务器,一般哨兵不太可能会挂,所以我改成了如下:

哨兵模式优缺点

优点:
1、哨兵集群,基于主从复制模式,所有的主从配置优点,它都有
2、主从可以切换,故障可以转移,高可用性的系统
3、哨兵模式就是主从模式的升级,手动到自动,更加健壮
缺点:
1、Redis不好在线扩容的,集群容量一旦到达上限,在线扩容就十分麻烦
2、哨兵模式的配置繁琐

推送的消息内容

以下是Sentinel推送的所有消息。从Sentinel的推送消息,基本上可以看到Sentinel运行的整个流程。

  • +monitor quorum 有新的master被监控。
  • +reset-master master器已被重置。
  • +slave 一个新的slave已经被Sentinel检测到并关联到对应的master。
  • -pubsub-link 订阅连接断线。
  • -cmd-link 命令连接断开。
  • +pubsub-link 推送订阅连接连上的消息。
  • +cmd-link 推送命令连接连上的消息。
  • -cmd-link-reconnection 命令连接重连出错。
  • -pubsub-link-reconnection 订阅连接重连出错。
  • +reboot 节点重启,更换了新的runid。
  • +role-change new reported role is 通过解析info信息发现role可能有变化,role发生变化。
  • -role-change new reported role is 通过解析info信息发现role可能有变化,role没有发生变化。
  • +promoted-slave 故障转移过测中,新的master自己确认了master的角色。
  • +failover-state-reconf-slaves 该消息紧接着+promoted-slave消息,此时故障转移已经进入了reconf-slaves状态。
  • +convert-to-slave 新的master一段时间没有确认自己的master角色,而且它原来的master已经运行正常了,则重新复制原来的master,自己重新做回slave。
  • +fix-slave-config slave现在的master地址和Sentinel保存的master不一致,则让slave重新复制Sentinel认为的master。
  • +slave-reconf-inprog slave正在复制master。
  • +slave-reconf-done slave复制master完成。 * -dup-sentinel #duplicate of : or 通过hello频道得到的Sentinel信息与已经保存的Sentinel信息产生冲突,需要被移除 —— 当 Sentinel 实例重启的时候,就会出现这种情况。
  • +sentinel 一个新的Sentinel已经被Sentinel检测到并关联到对应的master。
  • +new-epoch 当前epoch被更新。
  • +config-update-from leader完成故障转移后,其他Sentinel通过hello频道获得新的配置信息。
  • +switch-master <master-name> <old master ip> <old master port> <new master ip> <new master port> 配置变更,maseter的IP和port已经改变。这是绝大多数外部用户都关心的信息。
  • -monitor 去掉了对该master的监控。
  • +set
  • +sdown 给定的实例现在处于主观下线状态。
  • -sdown 给定的实例已经不再处于主观下线状态。
  • +odown #quorum / 给定的实例现在处于客观下线状态。
  • -odown 给定的实例已经不再处于客观下线状态。
  • +vote-for-leader 把某个Sentinel设置为leader。
  • +try-failover 尝试故障迁移操作,等待被大多数Sentinel选中。
  • -failover-abort-not-elected Sentinel 的当选时间已过,取消故障转移计划。
  • +elected-leader 赢得指定epoch的选举,可以进行故障迁移操作。
  • +failover-state-select-slave 故障转移步骤中开始选择slave
  • -failover-abort-no-good-slave Sentinel没有找到合适的slave提升为master,一段时间后将重试,但是也可能在重试的时候出现相同的找不到合适slave的情况。
  • +selected-slave 故障转移中,选出了slave作为新的master。
  • +failover-state-send-slaveof-noone 故障转移中,选出了slave作为新的master后准备把slave提升为master。
  • -failover-abort-slave-timeout slave提升为master超时。
  • +failover-state-wait-promotion 新master执行slaveof no one成功。
  • +failover-end-for-timeout 故障转移超过时间,还有slave没有复制完新的master。
  • +failover-end 故障转移顺利结束。
  • +slave-reconf-sent-be 故障转移超过时间,还有slave没有复制完新的master。这些slave将直接发送复制新master命令后就完成了整个故障转移操作。
  • -slave-reconf-sent-timeout 超时的slave也正常完成复制工作。
  • +slave-reconf-sent leader Sentinel 向slave发送了复制命令,为slave设置新的master。
  • -tilt #tilt mode exited 退出 tilt 模式。
  • +tilt #tilt mode entered 进入 tilt 模式。

参考文档

  1. redis sentinel配置(windows环境)
  2. Redis 复制、Sentinel的搭建和原理说明
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以通过以下步骤将Spring Boot集成Redis哨兵模式: 1. 添加Redis依赖:在`pom.xml`文件中添加Spring Data Redis的依赖。 ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 2. 配置Redis哨兵模式:在`application.properties`或`application.yml`中添加以下配置。 ```yaml spring.redis.sentinel.master=your_master_name spring.redis.sentinel.nodes=host1:port1,host2:port2,host3:port3 ``` 确保将上述配置中的 `your_master_name` 替换为你实际的 Redis 主节点名称,以及将 `host1:port1,host2:port2,host3:port3` 替换为实际的哨兵节点的主机和端口信息。 3. 创建Redis配置类:创建一个`RedisConfig`类,并使用`RedisSentinelConfiguration`进行配置。 ```java @Configuration public class RedisConfig { @Value("${spring.redis.sentinel.master}") private String sentinelMaster; @Value("${spring.redis.sentinel.nodes}") private String sentinelNodes; @Bean public RedisConnectionFactory redisConnectionFactory() { RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration() .master(sentinelMaster); List<RedisNode> nodes = new ArrayList<>(); String[] hostsAndPorts = sentinelNodes.split(","); for (String hostAndPort : hostsAndPorts) { String[] parts = hostAndPort.split(":"); nodes.add(new RedisNode(parts[0].trim(), Integer.parseInt(parts[1].trim()))); } sentinelConfig.setSentinels(nodes); return new LettuceConnectionFactory(sentinelConfig); } @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); // 可以根据需要自定义序列化器等配置 return template; } } ``` 在上述配置类中,我们使用`RedisSentinelConfiguration`配置哨兵模式,并使用`LettuceConnectionFactory`作为连接工厂。 4. 使用Redis:现在你可以在Spring Boot应用程序中使用`RedisTemplate`来与Redis进行交互。例如: ```java @RestController public class MyController { @Autowired private RedisTemplate<String, Object> redisTemplate; @GetMapping("/set") public void setValue() { redisTemplate.opsForValue().set("key", "value"); } @GetMapping("/get") public String getValue() { return (String) redisTemplate.opsForValue().get("key"); } } ``` 在上述示例中,我们注入了`RedisTemplate`,并使用其`opsForValue()`方法来进行常见的键值对操作。 这样就完成了Spring Boot集成Redis哨兵模式的配置。你可以根据实际需求使用更多的Redis功能和操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值