1、Redis高可用Sentinel
哨兵模式概述 哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。 这里的哨兵有两个作用
通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器。
当哨兵监测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机。
然而一个哨兵进程对Redis服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式。
用文字描述一下故障切换(failover)的过程。假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象成为主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线。这样对于客户端而言,一切都是透明的。
1.1、高可用介绍
? 高可用是分布式系统架构设计中必须考虑的因素之一,它是通过架构设计减少系统不能提供服务的时间。保证高可用通常遵循下面几点:
- 单点是系统高可用的大敌,应该尽量在系统设计的过程中避免单点。
- 通过架构设计而保证系统高可用的,其核心准则是:冗余。
- 每次出现故障需要人工介入恢复,会增加系统不可用的时间,实现自动故障转移。
1.2、手动主从切换
? 为了更好说明Redis高可用Sentinel,先手动实现redis的主从切换。
1.2.1、环境准备
? 一旦主节点宕机,就需要把从节点晋升成主节点,同时需要修改应用方的主节点地址,还需要命令所有从节点去复制新的主节点,整个过程需要人工操作。redis安装可以参考:https://blog.csdn.net/yizhan_csdn/article/details/120546366?spm=1001.2014.3001.5501。
cd /usr/local/redis/
# 创建从节点1
cp redis/ redis01 -R
# 创建从节点2
cp redis/ redis02 -R
# 修改节点1的配置
vim redis.conf
port 6380
slaveof 127.0.0.1 6379
# 修改节点2的配置
vim redis.conf
port 6381
slaveof 127.0.0.1 6379
#分别启动节点1和节点2
/usr/local/redis01/bin/redis-server /usr/local/redis01/redis.conf
/usr/local/redis02/bin/redis-server /usr/local/redis02/redis.conf
**说明:**创建的节点1和节点2中如果有dump.rdb和appendonly.aof文件,需要先删除在启动。
role:master # 主节点
connected_slaves:2 # 有两个从节点
slave0:ip=10.211.55.4,port=6381,state=online,offset=425,lag=1
slave1:ip=10.211.55.4,port=6380,state=online,offset=425,lag=1
# Replication
role:slave #从节点
#主从服务器的IP和端口
master_host:10.211.55.4
master_port:6379
master_link_status:up #状态为在线
1.2.2、主从切换
主服务下线
? 使用redis-cli登录主服务,执行shutdown关闭主服务,然后进入节点1或节点2的服务,执行info查看信息
# Replication
role:slave
master_host:10.211.55.4
master_port:6379
master_link_status:down # 代表下线
主从切换
使用客户端redis-cli 登录6380的客户端,执行以下命令
slaveof no one
修改6381对应的主服务器,使用客户端redis-cli 登录6381的客户端,执行以下命令
slaveof 127.0.0.1 6380
再次执行info命令,可以看到主从服务器都切换成功。现在变成了一主一从,对外是正常的。
1.3、 Sentinel实现高可用
1.3.1、Sentinel介绍
? 在上述的例子中,主节点宕机,需要把从节点晋升成主节点,同时需要修改应用方的主节点地址,还需要命令所有从节点去复制新的主节点。
? 这整个过程都是人工,费事费力,还会造成一段时间内服务不可用,而且需要人一直都在。这不是一种好的方式,更多时候,我们优先考虑Sentinel(哨兵)。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DiFvCF4k-1632920865574)(file:///Users/apple/Downloads/%E5%8D%81%E6%AC%A1%E6%96%B92.0%E5%BE%AE%E6%9C%8D%E5%8A%A1%E5%AE%9E%E6%88%98-%E8%AE%B2%E4%B9%89%E5%8F%8A%E8%B5%84%E6%96%99/HTML%E7%89%88%E8%AE%B2%E4%B9%89/day06/assets/1560267330173.png)]
1.3.2、Sentinel安装
? Sentinel在redis的安装包中有,我们直接使用就可以了,但是先需要修改配置文件,配置文件在下载后的redis压缩包内有,将他拷贝到安装好后的redis中即可。
- 将解压后的redis安装包中的sentinel.conf 复制到主节点的目录中,并添加以下内容:
# 外部可以访问
bind 0.0.0.0
sentinel monitor mymaster 127.0.0.1 6379 1
sentinel down-after-milliseconds mymaster 10000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1
**说明:**以上配置有的在sentinel.conf文件中已经存在,需将他们注释掉。
参数说明:
-
sentinel monitor mymaster 127.0.0.1 6379 1 mymaster 主节点名,可以任意起名,但必须和后面的配置保持一致。 127.0.0.1 6379 主节点连接地址。 1 将主服务器判断为失效需要投票,这里设置至少需要 1个 Sentinel 同意。 -
sentinel down-after-milliseconds mymaster 10000 设置Sentinel认为服务?已经断线所需的毫秒数。 -
sentinel failover-timeout mymaster 60000 设置failover(故障转移)的过期时间。当failover开始后,在此时间内仍然没有触发任何failoer操作,当前 sentinel 会认为此次failoer失败。 -
sentinel parallel-syncs mymaster 1 设置在执行故障转移时, 最多可以有多少个从服务器同时对新的主服务?进行同步, 这个数字越小,表示同时进行同步的从服务器越少,那么完成故障转移所需的时间就越长。 如果从服务器允许使用过期数据集, 那么我们可能不希望所有从服务器都在同一时间向新的主服务器发送同步请求, 因为从服务器在载入主服务?发来的RDB文件时, 会造成从服务?在一段时间内不能处理命令请求。如果全部从服务器一起对新的主服务器进行同步, 那么就可能会造成所有从服务?在短时间内全部不可用的情况出现。
配置文件修改后,在任意节点的bin目录中,执行以下命令启动sentinel:
/usr/local/redis/bin/redis-sentinel sentinel01.conf
启动后输出:
# Sentinel ID is 73a0012f68cf32906cf8566cf4c4c0e7dfefa1f0
+monitor master mymaster 127.0.0.1 6379 quorum 1
+reboot master mymaster 127.0.0.1 6379
+slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
+slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
6379的是主节点,6380和6381是从节点
1.3.3.1、测试主节点宕机
将6379主节点关闭,Sentinel提示如下:
+sdown master mymaster 127.0.0.1 6379 #主节点宕机
+odown master mymaster 127.0.0.1 6379 #quorum 1/1
+new-epoch 1
+try-failover master mymaster 127.0.0.1 6379 #尝试故障转移
+vote-for-leader 00a6933e0cfa2b1bf0c3aab0d6b7a1a6455832ec 1 #选举领导
+elected-leader master mymaster 127.0.0.1 6379
+failover-state-select-slave master mymaster 127.0.0.1 6379 #故障转移选择从服务
+selected-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
#故障转移状态发送 发送到6380
+failover-state-send-slaveof-noone slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
+failover-state-wait-promotion slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
+promoted-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
+failover-state-reconf-slaves master mymaster 127.0.0.1 6379
+slave-reconf-sent slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
+slave-reconf-inprog slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
+slave-reconf-done slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
+failover-end master mymaster 127.0.0.1 6379 #故障转移结束,原来的主服务是6379
+switch-master mymaster 127.0.0.1 6379 127.0.0.1 6380 #转换主服务,由原来的6379转为现在的6380
+slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
+slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
+sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
根据提示信息,6379故障转移到了6380,通过投票选择6380为新的主服务器。
在6380执行info
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6381,state=online,offset=80531,lag=1
在6381执行info
# Replication
role:slave
master_host:127.0.0.1
master_port:6380
master_link_status:up
1.3.3、Sentinel原理
? Sentinel主要是监控服务器的状态,并决定是否进行故障转移。如何进行故障转移在前面的部分已经给大家演示过人工的操作,那么Sentinel是如何判断服务是否下线呢,主要分为主观下线和客观下线:
-
主观下线:
-
客观下线
-
概念: 多个 Sentinel 实例在对同一个服务?做出 SDOWN 判断, 并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后, 得出的服务?下线判断ODOWN。 (一个Sentinel 可以通过向另一个 Sentinel 发送命令来询问对方是否认为给定的服务器已下线) -
特点: 从主观下线状态切换到客观下线状态并没有使用严格的法定人数算法(strong quorum algorithm),而是使用了流言传播(Gossip): 如果Sentinel在给定的时间范围内, 从其他Sentinel那里接收到了足够数量的主服务?下线报告, 那么 Sentinel 就会将主服务器的状态从主观下线改变为客观下线。 -
注意点: 客观下线条件只适用于主服务?,对于其他类型的 Redis 实例, Sentinel 在将它们判断为下线前不不需要进行协商, 所以从服务器或者其他 Sentinel 不会达到客观下线条件。 只要一个 Sentinel 发现某个主服务器进入了客观下线状态, 这个Sentinel就可能会被其他 Sentinel 推选出,并对失效的主服务?执行自动故障迁移操作。
1.4、整合SpringBoot
设置密码
? Redis 4.0.14默认开启保护模式protected-mode yes,我们要正常访问需要先设置redis的访问密码,然后才可以进行测试,在所有的redis配置文件redis.conf中,添加如下配置:
# 设置密码
requirepass 123456
?
# 设置访问主服务器密码
masterauth 123456
在Sentinel哨兵的配置文件sentinel01.conf中添加以下设置:
sentinel auth-pass mymaster 123456
整合SpringBoot
创建maven工程并在pom.xml添加以下依赖:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies>
编写application.yml配置文件:
spring:
redis:
password: 123456
sentinel:
master: mymaster
nodes: 192.168.200.129:26379
编写启动类:
@SpringBootApplication
public class RedisApplication {
public static void main(String[] args) {
SpringApplication.run(RedisApplication.class, args);
}
}
编写测试类:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = RedisApplication.class)
public class RedisTest {
@Autowired
private StringRedisTemplate redisTemplate;
@Test
public void test() {
redisTemplate.opsForValue().set("test", "redis");
redisTemplate.opsForValue().get("test");
}
}
|