主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。
前者称为主节点(master),后者成为从节点(slave);数据的复制是单向,主要是由主节点到从节点。一个master挂载多个slave节点,当master服务宕机,会在多个slave节点中选举产生一个新的master节点,从而保证服务的高可用性。
主从模式配置很简单,只需要在从节点配置主节点的ip和端口即可
slaveof
# 例如
# slaveof 192.168.1.214 6379
启动主从节点的所有服务,查看日志即刻看到主从节点之间的服务连接。
从上面很容易就想到一个问题,既然主从复制,意味着master和slave的数据一样,存在数据冗余的问题。
在程序设计上,为了高可用性和高性能,是允许有冗余存在的,但是可以避免宕机影响用户体验。
优点:
当开启主从模式的时候,他的具体工作机制如下:
打开一个命令窗口,在其中运行如下命令创建一个名为redis-master的Redis容器。端口为6379
docker run -itd --name redis-master -p 6379:6379 redis:latest
新建一个命令窗口,在其中运行如下命令创建一个名为redis-slave1的容器,它的端口是6380.这里是在一台电脑上运行,所以用端口号来区别一台主Redis容器和另外两台从Redis容器。在真实项目里,多台Redis会部署在不同的服务器上,所以可以都用6379端口。
docker run -itd --name redis-slave1 -p 6380:6380 redis:latest
新建一个命令窗口,在其中运行如下命令创建一个名为redis-slave2的容器
docker run -itd --name redis-slave2 -p 6381:6381 redis:latest
回到包含redis-master容器的命令窗口,在其中运行docker inspect redis-master
命令查看redis-master容器的信息,在其中能通过IPAddress项看到该容器的IP地址,这里是172.17.0.2。在真实项目里,Redis服务器所在的IP地址是固定的,而通过Docker容器启动的Redis服务器的IP地址是动态的,所以这里要用上述命来获取IP地址。
运行docker exec -it redis-slave1 /bin/bash
进入redis-slave1容器,并使用redis-cli进入redis客户端,在redis客户端里运行如下的slaveof命令,指定当前Redis服务器为从服务器。该命令的格式是slaveof ip port
,这里指向172.17.0.2:6379所在的主服务器。
同样,在redis-slave2容器的命令窗口里运行如下的slaveof命令,指定当前Redis服务器为从服务器
从上面可以看到role为master,连接配置的从服务器有2台,分别是redis-slave1和redis-slave2
在redis-slave1和redis-slave中,可以看到主服务器的ip和它的连接状态
在redis-master中设置个值set name ‘Peter’,再到从服务器上查看是否复制成功。
redis-master
读写分离时,master会异步将数据复制到slave,如果这时slave发生阻塞,则会延迟master数据的写命令,造成数据不一致的情况
解决方法:可以对slave的偏移量进行监控,如果发现某台slave的偏移量有问题,则将数据读取操作切换到master,但本身这个监控开销比较高,所以关于这个问题,大部分的情况是可以直接使用而不去考虑的。
redis复制有全量复制和部分复制两种,而全量复制的开销是很大的,下面有几种出现全量复制的情况,可以尽量去规避全量复制。
a.我们将原来master与slave中间加一个或多个slave,再在slave上加若干个slave,这样可以分担所有slave对master复制的压力。(这种架构还是有问题:读写分离的时候,slave1也发生了故障,怎么去处理?)
b.如果只是实现高可用,而不做读写分离,那当master宕机,直接晋升一台slave即可。
(2)单机器复制风暴:机器宕机后的大量全量复制,如下图:
当machine-A这个机器宕机重启,会导致该机器所有master下的所有slave同时产生复制
解决:
1.主节点分散多机器(将master分散到不同机器上部署)
2.还有我们可以采用高可用手段(slave晋升master)就不会有类似问题了。