Redis 主从复制
主从复制的好处:
-
读写分离(主库写、从库读),一般情况下是一个主数据库,多个从数据库(一主多从);
-
容灾的快速恢复,当某一台从机宕机后可以快速切换到另一台从机继续为应用提供服务。
搭建主从复制
我们使用docker创建多个redis容器实现主从复制。
- 我们下载好镜像后启动3个redis容器服务,分别映射到宿主机的6380、6381和6382端口
docker run --name redis-6380 -p 6380:6379 -d redis redis-server
docker run --name redis-6381 -p 6381:6379 -d redis redis-server
docker run --name redis-6382 -p 6382:6379 -d redis redis-server
-
查看3个容器的内网ip地址
docker inspect redis-6380
3个redis容器的内网ip分别为
redis-6380 172.17.0.4
redis-6381 172.17.0.5
redis-6382 172.17.0.6
我们进入redis容器内部,查看redis容器角色,此时三个redis容器都是master,并没有主从关系
命令:
info replication
此时我们需要在两台从机上(redis-6381、redis-6382)执行命令slaveof <主机ip> <主机端口号>
slaveof 172.17.0.4 6379
此时我们在查看主机redis-6380 的info,此时有了两台从机
我们在主机redis-6380 写入数据:set k1 v1,在从机中也可以查到k1
注意:我们只能在主机中进行写操作,不能再从机中做写操作,如图我们在从机中写操作,会报错
主从复制原理
- Slave(从机)启动成功连接到master(主机)后会发送一个 sync命令(同步命令)
- Master接到命令启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,master将传送整个数据文件到slave,以完成一次完全同步。
- 全量复制:而slave服务在接收到数据库文件数据后,将其存盘并加载到内存中。
- 增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步。
- 当连接断开又重新连上之后,一般都会进行一个完整的重新同步,但是从Redis2.8开始,只重新同步一部分也可以。
Redis 主从复制的三种常见情况
一主二仆
即上面我们搭建的一个主机有两个从机,redis-6381和redis-6382是redis6380的从服务器
当主机挂掉后,如果没有再配置文件中写slaveof指定主机,在重新连接后从机角色将变回master,重新slaveof设置为从机后,主机中的数据会复制给从机达到数据同步。
薪火相传
我们不再把两个从机redis-6381和redis-6382指向主机redis-6380,而是redis-6382指向redis-6381,redis-6381指向redis-6380,即6382是6381的从服务器,6381是6380的从服务器,形成多级结构。
上一个slave可以是下一个slave的Master, slave同样可以接收其他slaves的连接和同步请求,那么该slave作为了链条中下一个的master,可以有效减轻master的写压力,去中心化降低风险。
一旦某个slave挂机,后面的slave都没法备份,主机挂了,从机还是从机,无法写数据了
反客为主
当一个master宕机后,后面的slave可以立刻升为master,其后面的slave不做任何修改
用slaveof no one 将从机变为可以主机,但是这样必须手动实现,要实现在主机宕机后,从机自动变为主机,就需要引入哨兵模式。
哨兵模式
是什么:反客为主的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库。
哨兵模式的使用
切换为一主二仆的模式
在redis-6381和redis-6382使用语句
slaveof 172.17.0.4 6379
作为redis-6380的从服务器
创建sentinel.conf 文件
在/mydata/redis/conf 创建sentinel.conf
sentinel.conf
sentinel monitor mymaster 172.17.0.4 6379 1
这里sentinel monitor代表监控,mymaster代表服务器的名称,可以自定义,172.17.0.4 表示监控的主服务器的ip,6379表示端口,1表示至少有多少个哨兵 同意迁移(认为主服务器不可用)的数量。
docker启动redis-sentinel哨兵服务
docker run -d --name redis-sentinel1 \
-v /mydata/redis/conf/sentinel.conf:/sentinel.conf \
--net=host \
redis redis-sentinel /sentinel.conf
查看哨兵日志
docker logs redis-sentinel1
停止主服务器
docker stop redis-6380
再次查看哨兵日志
此时redis-6381变为主机
如果当原来的主机redis-6380重新连接,那么redis-6380会变为新主机redis-6381的从机
复制延时
由于所有的写操作都是先在Master上操作,然后同步更新到Slave上,所以从Master同步到Slave机器有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,Slave机器数量的增加也会使这个问题更加严重。
选举规则
- 根据优先级,slave-priority/replica-priority,优先选择优先级靠前的。数字越小,优先级越高
- 根据偏移量,优先选择偏移量大的。偏移量是指获得原主机数据最全的
- 根据 runid,优先选择最小的服务。每个redis实例启动后都会随机生成一个40位的runnid
Java代码实现哨兵模式
很简单
HashSet<String> set = new HashSet<String>();
set.add("192.168.126.20:26379");
JedisSentinelPool pool = new JedisSentinelPool("mymaster", set);
参考文献: