14redis主从集群结构
1.什么是主从集群分布

一个负责写,其余负责读,这样的redis就是主从分布形式,可以有效降低读写压力。
主从分布除了性能上的优势外,还能有效应该redis宕机的问题。如果主节点(负责写操作的节点)宕机后,可以在几个从节点中选一个当作新的主节点。
但是如何实现重新选择主节点呢?需要使用哨兵机制,使用之前学过的sentinel。

Sentinel基于心跳机制监测服务状态,每隔1秒向集群的每个实例发送ping命令:
- 主观下线:如果某sentinel节点发现某实例未在规定时间响应,则认为该实例主观下线。
- 客观下线:若超过指定数量(quorum)的sentinel都认为该实例主观下线,则该实例客观下线。quorum值最好超过Sentinel实例数量的一半。

一旦发现master故障,sentinel需要在salve中选择一个作为新的master,选择依据是这样的:
- 首先会判断slave节点与master节点断开时间长短,如果超过指定值(down-after-milliseconds * 10)则会排除该slave节点
- 然后判断slave节点的slave-priority值,越小优先级越高,如果是0则永不参与选举
- 如果slave-prority一样,则判断slave节点的offset值,越大说明数据越新,优先级越高
- 最后是判断slave节点的运行id大小,越小优先级越高。
当选出一个新的master后,该如何实现切换呢?
流程如下:
- sentinel给备选的slave1节点发送slaveof no one命令,让该节点成为master
- sentinel给所有其它slave发送slaveof 192.168.150.101 7002 命令(这个ip根据实际情况改变),让这些slave成为新master的从节点,开始从新的master上同步数据。
- 最后,sentinel将故障节点标记为slave,当故障节点恢复后会自动成为新的master的slave节点

2.在项目中搭建主从集群分布
2.1创建redis-slave和sentinel文件结构
我们在/root/redis中添加两个slave文件夹,三个sentinel文件夹

slave中的文件结构如下(data文件夹中没有内容,conf中有redis.conf文件)

redis.conf文件内容如下:(slave1中的replica-announce-port是6380,slave2中replica-announce-port是6381)
# 允许从库使用密码连接主库
masterauth 123456
requirepass 123456
replica-announce-ip 39.107.193.66
replica-announce-port 6380
sentinel中的文件结构如下(data中什么都没有)

sentinel.conf:(这个sentinel monitor mymaster的0.0.0.1需要改成自己的redis主节点的IP地址)
port 26379
dir /data
sentinel resolve-hostnames yes
sentinel monitor mymaster 0.0.0.1 6379 2
sentinel auth-pass mymaster 123456
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 10000
sentinel parallel-syncs mymaster 1
2.2创建容器
docker run -d \
--name redis-slave1 \
--network hm-net \
-p 6380:6379 \
-v /root/redis/slave1/conf/redis.conf:/etc/redis/redis.conf \
-v /root/redis/slave1/data:/data \
redis redis-server /etc/redis/redis.conf \
--appendonly yes \
--requirepass 123456 \
--masterauth 123456 \
--replica-announce-ip 39.107.193.66 \
--replica-announce-port 6380
docker run -d \
--name redis-slave2 \
--network hm-net \
-p 6381:6379 \
-v /root/redis/slave2/conf/redis.conf:/etc/redis/redis.conf \
-v /root/redis/slave2/data:/data \
redis redis-server /etc/redis/redis.conf \
--appendonly yes \
--requirepass 123456 \
--masterauth 123456 \
--replica-announce-ip 39.107.193.66 \
--replica-announce-port 6381
docker run -d \
--name redis-sentinel1 \
--network hm-net \
--add-host=redis:$REDIS_IP \
-p 26379:26379 \
-v /root/redis/sentinel1/sentinel.conf:/etc/redis/sentinel.conf \
-v /root/redis/sentinel1/data:/data \
redis redis-sentinel /etc/redis/sentinel.conf
docker run -d \
--name redis-sentinel2 \
--network hm-net \
--add-host=redis:$REDIS_IP \
-p 26380:26379 \
-v /root/redis/sentinel2/sentinel.conf:/etc/redis/sentinel.conf \
-v /root/redis/sentinel2/data:/data \
redis redis-sentinel /etc/redis/sentinel.conf
docker run -d \
--name redis-sentinel3 \
--network hm-net \
--add-host=redis:$REDIS_IP \
-p 26381:26379 \
-v /root/redis/sentinel3/sentinel.conf:/etc/redis/sentinel.conf \
-v /root/redis/sentinel3/data:/data \
redis redis-sentinel /etc/redis/sentinel.conf
2.3修改nacos配置文件
shared-redis.yaml文件修改为:
spring:
redis:
password: 123456
sentinel:
master: mymaster
nodes: 0.0.0.1:26379,0.0.0.1:26380,0.0.0.1:26381
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 0
max-wait: 100ms
2.4项目中配置读写分离
common模块中RedisConfig.java文件中添加一个新的Bean
@Bean
public LettuceClientConfigurationBuilderCustomizer clientConfigurationBuilderCustomizer() {
// 可选:ReadFrom.REPLICA_PREFERRED、MASTER、MASTER_PREFERRED、REPLICA
return clientConfigurationBuilder -> clientConfigurationBuilder.readFrom(ReadFrom.REPLICA_PREFERRED);
}
这个bean中配置的就是读写策略,包括四种:
- MASTER:从主节点读取
- MASTER_PREFERRED:优先从master节点读取,master不可用才读取replica
- REPLICA:从slave(replica)节点读取
- REPLICA _PREFERRED:优先从slave(replica)节点读取,所有的slave都不可用才读取master
项目下载地址
gupengzu/high-concurrency-project at 14redis-Master-Slave-Cluster