做集群的原因
- 性能,高并发的情况下,性能更好
- 扩展,水平扩容
- 可用性、安全,防止单点故障
主从复制
集群中,有一个主节点master,给客户端来访问,其他节点都是从节点slave,主从直接通过数据同步,实现数据一致,如果主节点发生故障,会将一个从节点提升为主节点,让客户端访问。
主从复制配置
在配置文件中添加或者在客户端执行slaveof 192.168.30.131 6379(配置或命令)
./redis-server --slaveof 192.168.30.131 6379 (启动参数)
配置完之后启动redis,可以在客户端通过info replication
查看节点信息
从节点默认是只读的
执行slaveof no one会断开主从的连接
主从复制原理
三个阶段
-
连接阶段,slave节点启动的时候会记录master的信息
replicationCron定时任务,每隔1秒会检查有没有master信息,有的话就去连接,连接成功后,从节点会建立用来处理数据复制的文件事件处理器,专门负责后续的数据复制工作(接收主节点发过来的数据文件,接收主节点持续添加的命令)
-
数据同步阶段
master将全量数据复制给从节点的时候,会通过一个bgsave的命令,生成一个rdb的快照文件,把这个文件通过和从节点之间建立的网络连接,将这个文件发送给从节点。
如果slave数据已经有自己的数据了,它在接收全量数据之前,会清空自己的数据,然后在用rdb文件加载数据。
在生产rdb文件的时候,会将新写入的命令缓存在内存中,当slave节点写入了rdb的数据后,master就将缓存的写的命令发送给slave
-
命令传播阶段
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节点选举的决定因素
- 断开连接的时长,一直和哨兵保持连接的slave才有选举权
- 优先级,在redis.conf中配置replica-priority,数值越小,优先级越高
- offset复制的数据越多
- 进程id最小的
功能:
- 监控,不断检测主服务器和从服务器是否正常
- 通知,一个被监控的redis的服务出现问题,Sentinel会通过api发出通知
- 自动故障转移,主服务器发生故障,Sentinel会做故障转移并发出通知,当只有一个master时,主从自动切换时,会出现数据丢失
- 配置提供者,实现配置管理,客户端会连接到Sentinel的节点,获取他监控到的当前的master的地址