写点什么

java 开发框架 Redis 之 sentinel 和集群

  • 2022 年 1 月 10 日
  • 本文字数:6422 字

    阅读完需:约 21 分钟

​ 一. redis 高可用方案–sentinel(哨兵模式)

当我们搭建好 redis 主从复制方案后会发现一个问题,那就是当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费事费力,java培训同时在手动切过程中也会导致 redis 服务器写入功能不可用。所以需要一种方法可以完成 Master 故障后可以自动的将一个 Slave 切换为 Master,这个时候就有了 sentinel 哨兵模式。

哨兵模式简介:

sentinel 是官方提供的高可用方案,其原理是哨兵通过发送命令,等待 Redis 服务器响应,从而监控运行的多个 Redis 实例。同时 sentinel 是一个分布式系统,可以在一个架构中运行多个 Sentinel 进程,可以做到 sentinel 的高可用。


sentinel 工作过程:

  • 通过向主服务器和从服务器发送 ping 命令,让服务器返回运行状态。

  • 当哨兵监测到 master 宕机,会自动将一个 slave 切换成 master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机。

关于 sentinel 的三个定时任务:

  • 每 1 秒每个 sentinel 对其他 sentinel 和 redis 节点执行 ping 操作,心跳检测。

  • 每 10 秒每个 sentinel 会对 master 和 slave 执行 info 命令,目的是发现 slave 结点,确定主从关系。

  • 每 2 秒每个 sentinel 通过 master 节点的 channel 交换信息(pub/sub)。master 节点上有一个发布订阅的频道(sentinel:hello)。sentinel 节点通过__sentinel__:hello 频道进行信息交换(对节点的"看法"和自身的信息),达成共识.

sentinel 网络:

sentinel 是一个分布式系统,可以在一个架构中运行多个 Sentinel 进程。所以监控同一个 Master 的 Sentinel 会自动连接,组成一个分布式的 Sentinel 网络,互相通信并交换彼此关于被监视服务器信息。


sentinel 网络故障修复原理:

1.主观下线:

当主服务器发生故障时,此时一个 sentinel 发现了故障,系统并不会马上进行 failover 过程(这个现象称为主观下线),它会向网络中的其他 Sentinel 进行确认。

2.客观下线:

接着其他 Sentinel 也陆续发现故障,这个时候其中一个 Sentinel 就会发起投票。一定数量的哨兵(在配置文件中指定)确认 Master 被标记为主观下线,此时将 Master 标记为客观下线。

3.sentinel 的 leader 选举:

要想完成故障切换(将故障 master 剔除,并将一个 slave 提升为 master)就必须先选举一个 leader。最先发现故障的 sentinel 向其他哨兵发起请求成为 leader,其他哨兵在没有同意别的哨兵的 leader 请求时,就会把票投给该 sentinel。当半数以上的 sentinel 投票通过后就认定该 sentinel 为 leader。接下来的故障切换有该 leader 完成。

4.master 选举:

leader 选好后将故障 master 剔除,从 slave 中挑选一个成为 master。遵照的原则如下:

  • slave 的优先级

  • slave 从 master 那同步的数据量,那个 slave 多就优先。

5.新 Master 再通过发布订阅模式通知所有 sentinel 更新监控主机信息。

6.故障的主服务器修复后将成为从服务器继续工作。

故障发生


故障切换



Master 重新上线后


哨兵模式配置

本实验在一台机器上完成,创建不同端口的 redis 实例。


1.创建 redis 实例

[root@redis ~]# nohup redis-server --port 6380 >> /data/redis/log/6380.log 2>&1 & [root@redis ~]# nohup redis-server --port 6381 >> /data/redis/log/6381.log 2>&1 & [root@redis ~]# nohup redis-server --port 6382 >> /data/redis/log/6382.log 2>&1 & 
[root@redis ~]# ps -ef |grep redisroot 16421 16314 0 03:01 pts/1 00:00:00 redis-server *:6380root 16427 16314 0 03:01 pts/1 00:00:00 redis-server *:6381root 16431 16314 0 03:01 pts/1 00:00:00 redis-server *:6382root 16436 16314 0 03:01 pts/1 00:00:00 grep --color=auto redis
复制代码


2.连接数据库并设置主从复制

[root@redis ~]# redis-cli -p 6380127.0.0.1:6380> 
[root@redis ~]# redis-cli -p 6381127.0.0.1:6381> SLAVEOF 127.0.0.1 6380 #将6380设置为masterOK[root@redis ~]# redis-cli -p 6382127.0.0.1:6382> SLAVEOF 127.0.0.1 6380OK
复制代码


3.搭建哨兵模式集群

创建 sentinel 配置文件

[root@redis conf]# cat sentinel1.conf port 26300                              #指定sentinel进程端口号sentinel monitor redis1 127.0.0.1 6380 2  #Sentinel monitor <name> <ip> <port> <quorum>
[root@redis conf]# cat sentinel2.conf port 26301sentinel monitor redis1 127.0.0.1 6380 2
复制代码


  • name :redis 主服务名称,可以自行命名,但是在一个 sentinel 网络中,一个 redis 主服务只能有一个名称;

  • ip 和 port :redis 主服务的 IP 地址和端口号.

  • quorum :表示要将这个主服务器判断为失效并下线至少需要 2 个 sentinel 同意

  • protected-mode :关闭保护模式(默认情况下,redis node 和 sentinel 的 protected-mode 都是 yes,在搭建集群时,若想从远程连接 redis 集群,需要将 redis node 和 sentinel 的 protected-mode 修改为 no,若只修改 redis node,从远程连接 sentinel 后,依然是无法正常使用的,且 sentinel 的配置文件中没有 protected-mode 配置项,需要手工添加。依据 redis 文档的说明,若 protected-mode 设置为 no 后,需要增加密码证或是 IP 限制等保护机制,否则是极度危险的。)

启动 sentinel

[root@redis ~]# nohup redis-sentinel /data/redis/conf/sentinel1.conf >> /data/redis/log/sentinel1.log 2>&1 &[1] 16522[root@redis ~]# nohup redis-sentinel /data/redis/conf/sentinel2.conf >> /data/redis/log/sentinel2.log 2>&1 &[2] 16526[root@redis ~]# ps -ef |grep sentinelroot      16522  16440  0 03:55 pts/2    00:00:00 redis-sentinel *:26300 [sentinel]root      16526  16440  0 03:55 pts/2    00:00:00 redis-sentinel *:26301 [sentinel]
复制代码


4.测试。模拟主节点故障,查看故障后主从环境改变

关闭主节点

[root@redis ~]#  ps -ef |grep redis-serverroot      16604  16440  0 04:12 pts/2    00:00:02 redis-server *:6381root      16608  16440  0 04:12 pts/2    00:00:03 redis-server *:6382root      16702  16314  0 04:46 pts/1    00:00:00 redis-server *:6380[root@redis ~]# kill 16702
复制代码


此时查看 6381 和 6382 的日志文件,在 6382 的日志文件中发现了如下内容,说明此时已经将 6381 切换为主节点。


再次启动 6380 时,6380 成为 slave,6381 时 master


最后查看一下 sentinel 配置文件:

cat /data/redis/conf/sentinel2.confport 26301sentinel myid 74cdfbb5ae55a77ad4d05d5d9d50fd64725e192a
# Generated by CONFIG REWRITEdir "/root"protected-mode nosentinel deny-scripts-reconfig yessentinel monitor redis1 127.0.0.1 6381 1 #主节点sentinel config-epoch redis1 1sentinel leader-epoch redis1 1sentinel known-replica redis1 127.0.0.1 6382 #从节点sentinel known-replica redis1 127.0.0.1 6380sentinel known-sentinel redis1 127.0.0.1 26300 9539652da78b0385479a827e753deceaef864989sentinel current-epoch 1
复制代码


二. redis 高可用方案–集群

使用哨兵模式,解决了主节点故障自动切换的问题,但是却不可以动态扩充 redis。所以在 redis3.0 之后提出了集群模式。

redis 集群设计:

redis 集群采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接。


特点:

  • 所有的 redis 节点彼此互联(PING-PONG 机制),内部使用二进制协议优化传输速度和带宽。

  • 节点的失效是通过集群中超过半数的节点检测失效时才生效。

  • 集群是一个整体,客户端与 redis 节点直连,不需要中间 proxy 层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。

  • Redis 集群预分好 16384 个桶,当需要在 Redis 集群中放置一个 key-value 时,根据 CRC16(key) mod 16384 的值,决定将一个 key 放到哪个桶中。

redis 集群节点分配和数据分配

节点分配:

Redis 集群预分好 16384 个桶,采用哈希槽 (hash slot)的方式来平均分配 16384 个 slot 。以三个节点为例,

  • 节点 1:0-5460;

  • 节点 2:5461-10922;

  • 节点 3:10923-16383.

若存入一个值,按照哈希槽算法得到 6587,那么就会将数据存入节点 2。取数据时也是从节点 2 上取。

当新增一个节点时:

采用从各个节点的前面各拿取一部分槽到新节点上,如添加节点 4,哈希槽就为,0-1364,5461-6826,10923-12287。

redis 集群的主从模式

为了保证数据高可用,集群应建立在主从基础之上。一个主节点对应一个从节点。主节点提供数据存取,从节点提供数据读取,当主节点故障后,就会有这个从节点选取一个来充当主节点,从而保证集群正常运行。

但是在一个集群中,一对主从节点同时故障,那么集群将失去服务能力。

redis 集群搭建:

redis 集群中至少应该有奇数个节点,所以至少有三个节点,每个节点至少有一个备份节点,所以本次实验使用 6 个节点(主节点、备份节点由 redis-cluster 集群确定)。

实验在两台机器进行,每台机器启动三个基于不同端口 redis 实例,6 个实例两两对应主从。


1.创建一个目录 redis_cluster,用来存放每个实例所用的配置文件.

[root@redis redis]# mkdir redis_cluster[root@redis redis]# mkdir -p redis_cluster/7001[root@redis redis]# cp -r conf/redis.conf redis_cluster/
复制代码


2.修改配置文件,将修改好的文件复制 5 份分别放置不同 redis 配置目录下。

修改配置文件

vim 7001/redis.conf修改一下几项bind 192.168.126.162  (本机IP)port 7001                                    #redis端口daemonize yes                               #redis在后台启动logfile "/data/redis/log/logs"pidfile /var/run/redis_7001.pidcluster-enabled yes                    #开启集群功能cluster-config-file nodes-7001.conf    #集群配置文件cluster-node-timeout 5000          #姐点之间通讯时间appendonly yes                      #开启AOF持久化方式
复制代码


创建目录 7002 到 7006,其中 7004 到 7005 创建在 192.168.126.161 上。再把配置文件复制到 700*目录下,修改配置文件中端口号和 ip。

[root@redis redis_cluster]# cp -rp 7001 7002[root@redis redis_cluster]# cp -rp 7001 7003
[root@redis redis_cluster]# vim 7002/redis.conf #修改端口为7002 [root@redis redis_cluster]# vim 7003/redis.conf 将配置文件目录拷贝到192.168.126.161上[root@redis redis_cluster]# scp -rp 7001 192.168.126.161:/usr/local/redis/redis_cluster/
修改配置文件(端口号和ip)[root@centosm redis_cluster]# ls7004 7005 7006
复制代码


3.启动 redis,可以使用脚本启动

[root@redis redis_cluster]# ls7001  7002  7003  start.sh[root@redis redis_cluster]# cat start.sh     #另一台机器相同操作cd 7001redis-server redis.confcd ../7002redis-server redis.confcd ../7003redis-server redis.conf#192.168.126.162[root@redis redis_cluster]# ps -ef |grep redisroot       1757      1  2 12:36 ?        00:00:00 redis-server 192.168.126.162:7001 [cluster]root       1762      1  1 12:36 ?        00:00:00 redis-server 192.168.126.162:7002 [cluster]root       1767      1  1 12:36 ?        00:00:00 redis-server 192.168.126.162:7003 [cluster]

#192.168.126.161[root@centosm redis_cluster]# ps -ef |grep redisroot 11906 1 0 23:07 ? 00:00:00 redis-server 192.168.126.161:7004 [cluster]root 11911 1 0 23:07 ? 00:00:00 redis-server 192.168.126.161:7005 [cluster]root 11913 1 0 23:07 ? 00:00:00 redis-server 192.168.126.161:7006 [cluster]
复制代码


4.开始创建集群

搭建集群的话,如果 redis 版本小于 5.0 就需要使用一个工具 redis-trib(脚本文件),这个工具在 redis 解压文件的源代码里。因为这个工具是一个 ruby 脚本文件,所以这个工具的运行需要 ruby 的运行环境,所以需要安装 ruby

yum install ruby -y
yum install rubygems -y
gem install redis
复制代码


当前 redis 版本大于 5.0,所以不用 ruby,可以直接创建。

redis-cli --cluster create 192.168.126.162:7001 192.168.126.162:7002 192.168.126.162:7003 192.168.126.161:7004 192.168.126.161:7005 192.168.126.161:7006 --cluster-replicas 1
复制代码


–cluster-replicas 1:主从比例为 1:1

[root@redis redis_cluster]# redis-cli --cluster create 192.168.126.162:7001 192.168.126.162:7002 192.168.126.162:7003 192.168.126.161:7004 192.168.126.161:7005 192.168.126.161:7006 --cluster-replicas 1>>> Performing hash slots allocation on 6 nodes...      #对6个节点进行哈希槽位分配,实际分配三个主节点即可。Master[0] -> Slots 0 - 5460Master[1] -> Slots 5461 - 10922Master[2] -> Slots 10923 - 16383Adding replica 192.168.126.161:7006 to 192.168.126.162:7001  #三个主节点7001 7004 7002Adding replica 192.168.126.162:7003 to 192.168.126.161:7004   #三个从节点7006 7005 7003Adding replica 192.168.126.161:7005 to 192.168.126.162:7002M: fb89e991f2fca476964195f496428c0de3e57f76 192.168.126.162:7001   slots:[0-5460] (5461 slots) masterM: 54788eed17c99719f0d9e49b4933f8fc6e900cd9 192.168.126.162:7002   slots:[10923-16383] (5461 slots) masterS: 0d4d849e80a4f12e546fa3df7fcec42cb65951b2 192.168.126.162:7003   replicates 4fbffafb9088e65f60526147f4bff5260ea897f0M: 4fbffafb9088e65f60526147f4bff5260ea897f0 192.168.126.161:7004   slots:[5461-10922] (5462 slots) masterS: 6f44fa89577fd53ff8d703390e3908b7db5cb88c 192.168.126.161:7005   replicates 54788eed17c99719f0d9e49b4933f8fc6e900cd9S: 3f224e631bffba6d3978412df83c11b9d53f5799 192.168.126.161:7006   replicates fb89e991f2fca476964195f496428c0de3e57f76Can I set the above configuration? (type 'yes' to accept): yes>>> Nodes configuration updated>>> Assign a different config epoch to each node>>> Sending CLUSTER MEET messages to join the clusterWaiting for the cluster to join......>>> Performing Cluster Check (using node 192.168.126.162:7001)M: fb89e991f2fca476964195f496428c0de3e57f76 192.168.126.162:7001   slots:[0-5460] (5461 slots) master   1 additional replica(s)S: 0d4d849e80a4f12e546fa3df7fcec42cb65951b2 192.168.126.162:7003   slots: (0 slots) slave   replicates 4fbffafb9088e65f60526147f4bff5260ea897f0M: 54788eed17c99719f0d9e49b4933f8fc6e900cd9 192.168.126.162:7002   slots:[10923-16383] (5461 slots) master   1 additional replica(s)S: 6f44fa89577fd53ff8d703390e3908b7db5cb88c 192.168.126.161:7005   slots: (0 slots) slave   replicates 54788eed17c99719f0d9e49b4933f8fc6e900cd9S: 3f224e631bffba6d3978412df83c11b9d53f5799 192.168.126.161:7006   slots: (0 slots) slave   replicates fb89e991f2fca476964195f496428c0de3e57f76M: 4fbffafb9088e65f60526147f4bff5260ea897f0 192.168.126.161:7004   slots:[5461-10922] (5462 slots) master   1 additional replica(s)[OK] All nodes agree about slots configuration.   #所有节点同意分配hash槽>>> Check for open slots...>>> Check slots coverage...[OK] All 16384 slots covered.        #分配完毕,创建完成
复制代码


最后集群主从对应关系


可以看出主从节点在两个节点随机分配,且一对对应主从服务不会分配到同一台机器上。即使一台机器损坏,也不会影响 redis 继续提供服务。

文章来源:Java 基基

用户头像

关注尚硅谷,轻松学IT 2021.11.23 加入

还未添加个人简介

评论

发布
暂无评论
java开发框架Redis之sentinel和集群