笔记整理自【尚硅谷】Redis 6 入门到精通 超详细 教程
Redis——主从复制
1. 简介
主机数据更新后根据配置和策略, 自动同步到备机的 master/slaver 机制,Master 以写为主,Slaver 以读为主。
主从复制的好处
- 读写分离,性能扩展
- 容灾快速恢复
2. 搭建 一主多从
一主两从
-
创建文件目录
mkdir /opt/etc
-
将 redis.conf 复制到当前目录
cp /etc/redis.conf /opt/etc/
-
创建 3 3 3 个 redis.conf 配置文件(一主两从)
vim redis6379.conf vim redis6380.conf vim redis6381.conf
-
配置文件内容:
include
引入公共部分,再进行单独的配置。# redis6379.conf include /opt/etc/redis.conf pidfile /var/run/redis_6379.pid port 6379 dbfilename dump6379.rdb # redis6380.conf include /opt/etc/redis.conf pidfile /var/run/redis_6380.pid port 6380 dbfilename dump6380.rdb # redis6381.conf include /opt/etc/redis.conf pidfile /var/run/redis_6381.pid port 6381 dbfilename dump6381.rdb
-
-
启动 3 3 3 台 redis 服务器
-
查看主机运行情况
info replication
目前 3 3 3 台服务器都是主机 master
-
配从不配主
slaveof <ip><port> # 成为某个实例的从服务器
在6380和6381上执行:
slaveof 127.0.0.1 6379
-
再次查看主机运行情况
6379 6379 6379 为主机 master, 6380 6380 6380 和 6381 6381 6381 为从机 slave。
成功搭建, master 负责写操作,slave 负责读操作。
3. 主从复制原理
- slave 启动成功连接到 master 后会发送一个 sync 命令(同步命令)。
- master 接到命令启动后台的存盘进程,对数据进行持久化操作,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,master 将传送整个数据文件(rdb)到 slave,以完成一次完全同步。
- 当主服务进行写操作后,和从服务器进行数据同步。
- 全量复制:而 slave 服务在接收到数据库文件数据后,将其存盘并加载到内存中。
- 从服务器主动(第一次)向主服务器发起请求就是全量复制。
- 增量复制:master 继续将新的所有收集到的修改命令依次传给 slave,完成同步。
- 每次主服务器进行写操作后,主动对从服务器进行同步,是增量复制。
- 只要是重新连接 master,一次完全同步(全量复制)将被自动执行。
4. 常用三招
Ⅰ. 一主二仆
-
切入点问题
- slave1、slave2 是从头开始复制还是从切入点开始复制?
- 假如此时 slave2 挂掉了,主机新添加了 k4 进来,那之前的 k1, k2, k3 是否也可以复制?
- 答案:从头开始复制, k1, k2, k3, k4 的数据都会被复制到重新启动的从机中。
- 从机重启需重设:
slaveof 127.0.0.1 6379
- slave1、slave2 是从头开始复制还是从切入点开始复制?
-
从机是否可以写?set 可否?
-
否。
-
在从机上写数据报错
-
-
主机 shutdown 后情况如何?从机是上位还是原地待命?
- 从机原地待命,依旧是主机的 slave,但此时显示主机已经 down 掉了。
- 主机重新启动后,一切正常。
-
主机又回来了后,主机新增记录,从机还能否顺利复制?
- 能,一切正常。
-
其中一台从机 down 后情况如何?依照原有它能跟上大部队吗?
- 能,从机启动后,会从头开始复制主机的内容。
Ⅱ. 薪火相传
-
上一个 slave 可以是下一个 slave 的 master,slave 同样可以接收其他 slave 的连接和同步请求,那么该 slave 作为了链条中下一个的 master,可以有效减轻 master 的写压力,去中心化降低风险。
slaveof <ip><port> slaveof 127.0.0.1 6380
6379 6379 6379 为主机 master, 6380 6380 6380 和 6381 6381 6381 为从机 slave,但此时 6381 6381 6381 主机为 6380 6380 6380。
-
中途变更转向:会清除之前的数据,重新建立拷贝最新的。
-
当某个 slave 宕机,后面的 slave 都没法备份。
- 即当主机挂掉,从机还是从机,但是无法继续写数据。
Ⅲ. 反客为主
-
当一个 master 宕机后,后面的 slave 可以立刻升为 master,其后面的 slave 不用做任何修改。
-
此时 master 6379 6379 6379 down,将 6380 6380 6380 从机变为主机:
slaveof no one
-
缺点:还需要手动完成。
- 解决:参考下方哨兵模式。
-
5. 哨兵模式(Sentinel)
Ⅰ. 概述
反客为主的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库。
- Sentinel 哨兵主要用来监控 redis 主从集群,提高了 redis 主从集群的可用性。
- 哨兵机制解决了主从复制架构中的主节点宕掉后从节点无法作为主节点对外服务的问题
- Sentinel(哨兵)是 Redis 的高可用性解决方案:由一个或多个 Sentinel 实例 组成的 Sentinel 系统可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器。简单的说哨兵就是带有自动故障转移功能的主从架构。
Ⅱ. 哨兵模式实现机制
哨兵可以设置多个,哨兵刚开始监控主节点,向主节点发送心跳检测,检测主节点是否还在运行,一旦半数以上的哨兵判断主节点已经挂掉了 ,那么就会从从节点中选举出一个节点作为主节点对外服务。
#pic_center)
Ⅲ. 配置哨兵模式
-
调整为一主二仆模式
- 6379 6379 6379 为主机 master, 6380 6380 6380 和 6381 6381 6381 为从机 slave。
-
创建 sentinel.conf 文件
-
名字一定不能错
vim /opt/etc/sentinel.conf
-
-
配置哨兵
sentinel monitor mymaster 192.168.232.102 6379 1 # mymaster:监控对象起的服务器名称 # 1:至少有多少个哨兵同意迁移的数量。
-
启动哨兵
redis-sentinel /opt/etc/sentinel.conf
Ⅳ. 故障恢复
哨兵对 Redis 的主从服务进行监控,如果主机挂掉了会选举新的主机,保证整个系统的高可用。
-
主机挂掉,会从机选举中产生新的主机。
-
大概 10 10 10 秒左右可以看到哨兵窗口日志,切换了新的主机
通过哨兵,将主机切换为 6381 6381 6381
-
哪个从机会被选举为主机呢?根据优先级别:slave-priority
- 参考下方选举规则。
-
原主机宕机重启后会变为从机。
-
选举规则
按下列三项顺序判断选举哪个节点作为主机:
-
根据优先级别,slave-priority/replica-priority,优先选择优先级靠前的。
- 优先级在
redis.conf
中默认:replica-priority 100
,值越小优先级越高。
- 优先级在
-
偏移量是指获得原主机数据最全的,优先选择偏移量大的。
-
每个 redis 实例启动后都会随机生成一个 40 位的 runid,优先选择 runid 最小的服务。
Java代码
private static JedisSentinelPool jedisSentinelPool = null;
public static Jedis getJedisFromSentinel() {
if (jedisSentinelPool == null) {
Set<String> sentinelSet = new HashSet<>();
sentinelSet.add("192.168.11.103:26379");// 26379:哨兵Sentinel端口号
JedisPoolConfig jedisPoolConfig =new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(10); // 最大可用连接数
jedisPoolConfig.setMaxIdle(5); // 最大闲置连接数
jedisPoolConfig.setMinIdle(5); // 最小闲置连接数
jedisPoolConfig.setBlockWhenExhausted(true); // 连接耗尽是否等待
jedisPoolConfig.setMaxWaitMillis(2000); // 等待时间
jedisPoolConfig.setTestOnBorrow(true); // 取连接的时候进行一下测试 ping pong
jedisSentinelPool = new JedisSentinelPool("mymaster", sentinelSet, jedisPoolConfig); // mymaster:主机的名字
return jedisSentinelPool.getResource();
} else {
return jedisSentinelPool.getResource();
}
}
Ⅴ. 存在的问题
复制延时
- 由于所有的写操作都是先在 master 上操作,然后同步更新到 slave 上,所以从 master 同步到 slave 从机有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,slave 机器数量的增加也会使这个问题更加严重。
集群模式
- 虽然哨兵解决了主从复制架构中的主节点挂掉后从节点无法对外服务的缺陷,但是仍然存在着整个结构只有一台服务进行工作的问题,在高并发情况下显然是会崩掉的,而且由于做持久化,久而久之 AOF 文件会越来越大,服务器迟早会崩掉,所有我们要做成集群的模式,多台 Redis 对外进行服务,实现高可用。