Redis集群与主从复制配置

young 478 2021-10-18

做集群的原因

  1. 性能,高并发的情况下,性能更好
  2. 扩展,水平扩容
  3. 可用性、安全,防止单点故障

主从复制

集群中,有一个主节点master,给客户端来访问,其他节点都是从节点slave,主从直接通过数据同步,实现数据一致,如果主节点发生故障,会将一个从节点提升为主节点,让客户端访问。

主从复制配置

在配置文件中添加或者在客户端执行slaveof 192.168.30.131 6379(配置或命令)

./redis-server --slaveof 192.168.30.131 6379 (启动参数)

配置完之后启动redis,可以在客户端通过info replication查看节点信息

从节点默认是只读的

执行slaveof no one会断开主从的连接

主从复制原理

三个阶段

  1. 连接阶段,slave节点启动的时候会记录master的信息

    replicationCron定时任务,每隔1秒会检查有没有master信息,有的话就去连接,连接成功后,从节点会建立用来处理数据复制的文件事件处理器,专门负责后续的数据复制工作(接收主节点发过来的数据文件,接收主节点持续添加的命令)

  2. 数据同步阶段

    master将全量数据复制给从节点的时候,会通过一个bgsave的命令,生成一个rdb的快照文件,把这个文件通过和从节点之间建立的网络连接,将这个文件发送给从节点。

    如果slave数据已经有自己的数据了,它在接收全量数据之前,会清空自己的数据,然后在用rdb文件加载数据。

    在生产rdb文件的时候,会将新写入的命令缓存在内存中,当slave节点写入了rdb的数据后,master就将缓存的写的命令发送给slave

  3. 命令传播阶段

    master持续接收客户端的命令,持续写入,会通过异步的复制,将命令传播到所有的从节点。

    如果因为网络问题,从节点断开了一段时间和主节点的连接,从节点会漏掉一部分命令。

    info replication中记录主节点和从节点之间记录的偏移量,通过偏移量去确定主从复制有没有完毕

主从复制的不足

  1. 单个节点数据量过大时,同步比较耗时
  2. 需要手动切换主从,master挂掉了需要手动将某个从节点切换成主节点

Sentinel哨兵

开启哨兵模式,至少需要3个Sentinel实例(奇数个,否则无法选举Leader)。

IP地址	          节点角色&端口
192.168.8.203	Master:6379 / Sentinel : 26379
192.168.8.204	Slave :6379 / Sentinel : 26379
192.168.8.205	Slave :6379 / Sentinel : 26379

在204和205的redis.conf配置中添加一行

slaveof 192.168.8.203 6379

在203、204、205创建sentinel配置文件(单例安装后根目录下默认有sentinel.conf,可以先备份默认的配置)

cd /usr/local/soft/redis-5.0.5
mkdir logs
mkdir rdbs
mkdir sentinel-tmp
cp sentinel.conf sentinel.conf.bak
>sentinel.conf
vim sentinel.conf

sentinel.conf配置文件内容,三台机器相同

# 后台启动
daemonize yes
# 端口
port 26379
# no-可以在外网访问
protected-mode no
# 工作目录
dir "/usr/local/soft/redis-5.0.5/sentinel-tmp"
# 要监控的主节点 redis-master这个名字和主节点ip端口要统一,表示监听的master
sentinel monitor redis-master 192.168.8.203 6379 2
# master宕机多久后,哨兵主观认为master下线(毫秒)
sentinel down-after-milliseconds redis-master 30000
# 同一个master两次故障转移的时间间隔,毫秒
# slave从一个错误的master同步数据的开始计算时间
# 取消正在进行的故障转移,至少需要的时间
sentinel failover-timeout redis-master 180000
# 当发生故障转移的时候,最多可以有多少个slave同时对master进行同步,数字越小,时间越长,同步时的redis是不可用的
sentinel parallel-syncs redis-master 1

在3台机器上分别启动Redis和Sentinel

cd /usr/local/soft/redis-5.0.5/src
./redis-server ../redis.conf
./redis-sentinel ../sentinel.conf

哨兵节点的另一种启动方式:

./redis-server ../sentinel.conf --sentinel

在3台机器上查看集群状态:

$ /usr/local/soft/redis-5.0.5/src/redis-cli
redis> info replication

模拟master宕机,在203执行:

redis> shutdown

注意看sentinel.conf里面的redis-master被修改了,变成了当前master的IP端口。

$ /usr/local/soft/redis-5.0.5/src/redis-cli
redis> info replication

这个时候会有一个slave节点被Sentinel设置为master。
再次启动master,它不一定会被选举为master。

客户端连接

JedisSentinelPool pool;
String masterName ="redis-master";
Set<String> sentinels = new HashSet<>;
sentinels.add("192.168.30.131:26379");
sentinels.add("192.168.30.132:26379");
sentinels.add("192.168.30.133:26379");
pool = new JedisSentinelPool(masterName,sentinels);
pool.getResource().set("qingshan","qq"+System.currentTimeMillis());
System.out.println(pool.getResource().get("qingshan"));

SpringBoot 中

spring.redis.sentinel.master=redis-master
spring.redis.sentinel.nodes=192.168.30.131:26379,192.168.30.132:26379,192.168.30.133:26379

# 连接池最大连接数(使用负值表示没有限制) 默认8
spring.redis.lettuce.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)默认-1
spring.redis.lettuce.pool.max-wait=-1s
# 连接池中最大空闲连接 默认8
spring.redis.lettuce.pool.max-idle=8
# 连接池中最小空闲连接 默认0
spring.redis.lettuce.pool.min-idle=0

Sentinel原理

服务下线

主观下线和客观下线

Sentinel对监控的服务节点,以1秒钟一次的频率发送PING命令,在一段时间(down-after-milliseconds)内没有收到回复,就会认为是主观下线,及当前哨兵认为它下线了,可能是网络问题,其他哨兵并没有认为它下线,如果一个maste被标记为主观下线,哨兵节点会询问其他哨兵节点,如果超过一半以上的哨兵节点告知下线,此时为客观下线

一旦master客观下线,就要进行故障转移

现在Sentinel的节点中,选取一个Leader,采用Raft算法(共识算法,先到先得,少数服从多数)选举,当有了Leader节点之后,对一个节点执行slaveof no one,使其不再成为slave节点,再对其他节点执行slave of xxx

master节点选举的决定因素

  1. 断开连接的时长,一直和哨兵保持连接的slave才有选举权
  2. 优先级,在redis.conf中配置replica-priority,数值越小,优先级越高
  3. offset复制的数据越多
  4. 进程id最小的

功能:

  1. 监控,不断检测主服务器和从服务器是否正常
  2. 通知,一个被监控的redis的服务出现问题,Sentinel会通过api发出通知
  3. 自动故障转移,主服务器发生故障,Sentinel会做故障转移并发出通知,当只有一个master时,主从自动切换时,会出现数据丢失
  4. 配置提供者,实现配置管理,客户端会连接到Sentinel的节点,获取他监控到的当前的master的地址