redis的复制很简单,由于资源限制,本例中采用两台虚拟机,每台虚拟机安装两个redis实例,共四个来测试
一、安装redis
https://www.cnblogs.com/qq931399960/p/10616459.html
二、当前安装的redis分别为
192.168.102.69:6379 (master)
192.168.102.69:6380 (slave)
192.168.102.52:6379 (slave)
192.168.102.52:6379 (slave)
三、配置主从复制
5.0版本使用REPLICAOF代替了之前版本的SLAVEOF,如果使用5.0及之后版本,则建议新命令REPLICAOF。
1、命令行方式
分别登录各slave redis命令行,执行auth xxx赋权,执行如下命令(重启之后无效)
REPLICAOF 192.168.102.69
CONFIG SET masterauth
若取消复制,则执行如下命令即可
REPLICAOF no one
2、配置方式(永久生效,本例中使用配置方式)
redis slave配置文件中添加如下配置,重启redis
replicaof 192.168.102.69
masterauth
若取消复制,只需要去掉上述配置,重启即可
四、验证
1、登录从实例,查看info
2、登录主实例,查看info
重启之后,replication id和offset会被重置
主实例添加key,从实例查询,已同步,ok
五、配置只有N个连接复制的时候才允许主实例写操作
个人觉得,若使redis节点高可用,则该项应该使用默认配置,否则可能会出现几个节点不可用,造成写操作失败。
该功能工作原理如下:
1、从实例每秒ping主实例,确认已处理的复制流的数量
2、redis主实例记住最后接收到的从实例ping的时间
3、用户配置从实例的最小数量在小于指定的最大延迟(秒)时间时可写。
该功能有两个配置控制(5.0版本之前replicas改为slaves)
min-replicas-to-write <number of slaves> (默认0)
min-replicas-max-lag <number of seconds> (默认10)
在redis master配置文件中添加配置
min-replicas-to-write
min-replicas-max-lag
意为,当至少4个slave连接master的延迟时间小于10秒时,主实例才可以进行写操作。
也可以通过命令行在重启之前生效
127.0.0.1:> CONFIG SET min-replicas-to-write
OK
127.0.0.1:> CONFIG GET min-replicas-to-write
) "min-replicas-to-write"
) ""
127.0.0.1:>
登录master,执行测试
如下为在redis官网获取到的一些信息
从实例在与主实例的连接断开后,会自动重连,并且尝试作为主实例的一个精确副本。其工作机制如下
1、当主从实例正常连接时,主实例发送命令流给从实例来保证数据的一致性
2、由于网络问题或者检测到超时等引起的主从连接断开,从实例将重新连接主实例并尝试进行部分再同步,也就是说,从实例将获取在连接断开期间丢失的命令流。
3、当部分再同步不可实现,从实例将会请求一个全量再同步。其中包括主实例创建一个所有数据的快照,并且发送给从实例,然后继续发送数据集改变时的命令流。
默认情况下,redis使用高性能,低延迟的异步复制。redis从实例异步的获取接收到的主实例数据量,因此主实例不用每次都等待从实例处理命令,但是主实例嫩巩固知道从实例的命令的执行状态
redis基本复制规则
1、redis使用异步复制,异步进行从实例到主实例的数据处理量的确认
2、主实例可以有多个从实例
3、从实例可以从其他从实例处接受数据,从redis4.0起,所有子从实例都从主实例获取精确的复制流
4、在主实例侧,redis复制是非阻塞的。当一个或者多个从实例执行初始化同步或者部分再同步时,主实例将继续处理查询请求。
5、在从实例侧,复制也基本上是非阻塞的。当从实例正在执行初始化同步时,它可以使用老版本的数据集处理查询。另外,可以在从实例中配置当复制流停止后,返回一个错误给客户端。但是在数据初始化同步之后,需要删除旧数据,加载新数据,在这一时期,从实例将会阻塞所有接收到的连接(对于一个非常大数据集,可能会持续几秒)。自从redis4.0,可以配置在另外一个线程中删除旧数据,但是仍然在主线程中加载新的初始化数据,并且阻塞从实例。
6、redis复制可以应用于可扩展性,比如有多个从实例提只读服务,或者仅仅只是用于数据安全和高可用
7、可以使用复制来避免主实例将全部数据集写入到磁盘中。这种使用方式一般在主实例中禁止了持久化,但必须谨慎的设置该功能,因为主实例启动后,将会清空所有数据,如果从实例向主实例获取数据,那么从实例的数据也将为空
强烈建议在主从实例中都打开持久化。
每个redis主实例都有一个relication id,它由一个大的伪随机字符串组成,标记数据集的给定描述。每个主实例还具有一个偏移量(offset),这个偏移量会一直增加,即使没有从节点连接,复制偏移量也会增加,重启之前replication id不会变化,重启之后,replication id和offset都会发生变化。一般replciation id和offset来确定主实例的一个准确的版本。
当从实例连接到主实例,从实例通过PSYNC命令来发送他们的最新的旧主实例replication id和offset,使用这种方式,主服务器可以只发送所需的增量部分命令流。但是如果主实例缓冲区没有足够的backlog,或者从实例指向了一个位置的历史replication id,那么将会发生全量再同步。
全量再同步工作原理
主实例启动一个后台保存进程生成RDB文件,如此同时,开始缓存所有从客户端获取的写命令,当后台保存进程结束,主实例将这个RDB数据库文件传送给从实例,从实例将其保存在磁盘,并且加载到内存,之后主实例发送所有缓存的命令给从实例。
SYNC是一个旧的命令,不支持部分再同步,在新版本中已经使用PSYNC代替,考虑到向后兼容,SYNC命令没有去除
主从连接断开后,从节点可以自动重新连接主实例。若果主实例接收到多个并发的同步请求,其将只执行一个后台保存进程生成RDB文件,然后将该RDB文件发送给以上并发同步的各请求
Replication id的解释
如果两个实例具有相同的replication id和offset,那么他们具有相同的数据集。每次主实例重启或者从实例提升为主实例,对于这个实例来讲,将会产生新的replication id,连接到主实例的从实例将在握手之后继承其replication id。因此具有相同id 的两个实例是有关联的,因为他们可能在不同的
时间点获取到了相同的数据。对于一个保存有最新数据的给定历史节点,偏移量作为一个逻辑时间来理解。例如:A和B具有相同的replication id,但是其中一个的偏移量为1000,另外一个偏移量为1023,这意味着第一个实例少执行了一些命令,也可以说,A实例,执行一些命令之后可以达到B实例的状态。
redis具有两个replication id的原因在于,提升为主实例的从实例。在故障转移中,被提升为主实例的从实例仍然需要记住它过去的replication id,因为这个replication id是之前主实例的一个id之一,在这种情况下,其他将与新主实例进行同步的从实例使用之前旧的主实例的replciation id与新的主实例之间可以执行部分同步。这和预期一致,因为当从实例提升为主实例,它将辅id设置为主id,在id转换时,记录偏移量,之后选出一个新的随机replication id,因为一个新的历史记录开始。档处理新从实例连接,主实例将用当前的id和辅id匹配它们的id和offset,简而言之,故障转移之后,连接到一个新的主实例的从实例不需要执行一个全量同步。
故障转移之后改变replication id的原因在于
由于一些分区,有可能旧的主实例仍然作为主实例在工作,保留相同的replication id违背了一个相同id和相同offset意味着它们具有相同的数据集的规则。
只读从实例
自从2.6版本,从实例默认支持只读模式,可以通过配置文件中修改slave-read-only来设置,也可以通过命令行config set来设置,前者永久生效。但这并不意味着redis从实例就是严格的不能写,因为一些管理命令,比如DEBUG/CONFIG仍然可以使用,可以通过rename-command指令来关闭相关命令以提高安全性。从实例也可以配置为可写,但在4.0版本之前,可写从实例不能兼容expire命令,也即是,使用expire或者其他命令设置一个key的ttl最大值,当key到达了指定时间之后,使用读命令已经不能获取到key,但是通过dbsize等命令获取key的数量时,依然包含了该key并且该key依然在占用内存。redis 4.0 RC3之后版本解决了该问题,并且可写从实例可以和主实例一样可以通过ttl剔除过期数据。
自从redis4.0,从实例仅本地可写,但子从实例始终都是从主实例同步数据,如
A -- >B --> C
上述A为主实例,B为可写从实例,C为只读从实例,C中的数据内容将与A一致,C不会不同在B中写入,但在A中不存在的数据。
Redis复制处理expires
redis使用三种技术来使expire key生效
1、从实例不过期key,他们等待主实例key过期,当主实例key过期,生成一个DEL命令,发送给从实例。
2、由于主控驱动过期,有时可能主实例还没有能够提供DEL命令,从实例中还存在逻辑上已经失效的key,此时如果将该key返回给客户端,这就与逻不符。为了解决这个问题,从实例在不违法数据集一致性的情况下,使用它的逻辑时钟一遍报告一个key并不只存在于读取操作中(?),这样,从实例可以避免上报逻辑上已经过期的key仍然存在。
3、Lua脚本执行期间,不执行key过期,所以整个脚本执行期间,要么一个key不存在,要么一个key一直存在,防止key在脚本执行中间过期。
消息和角色命令
INFO
INFO REPLICATION
ROLE