Redis Replication
2017-06-12 15:23
155 查看
Redis复制非常易于使用和配置主从复制,所谓主从复制即允许slave服务是master服务的正确考贝,关于Redis复制有以下几个要点:
Redis使用异步复制。然而,从Redis 2.8开始,slave服务器定期的从复制流获取数据。
一个master服务可以有多个slave服务。
slave从服务可以接收来自其他slave从服务的连接。除了大量slave从服务连接到master服务外,slaves也可以在层叠状结构中被其他从服务连接。
Redis复制在master一方是无阻塞的。这表示当一个或者多个slaves执行初始同步时,master服务器将持续处理请求。
Redis复制在slave一方也是无阻塞的。尽管slave正在执行初始同步,如果你在Redis配置文件中(redis.conf)设置了,那么它就同样可以使用老版本的数据处理请求。否则,你可以配置Redis在其同步时返回一个错误给客户端请求。然而,在初始同步以后,老的数据集必须被删除,新的数据必须被加载,此期间,slave将阻塞客户端的连接(如果是非常大的数据集可以达到好几秒)。
Redis复制同时也是可扩展的,为了拥有多个slaves用于只读查询或者是数据冗余。
也可以使用Redis复制来避免master将全部的数据集持久化到磁盘的消耗:一个典型的涉及到配置你的redis.conf来避免持久化到硬盘的技术,然后连接到配置的slave服务以时时保存,或者启用AOF。但是这种设置必须小心处理,因为一个master服务是以空的数据集重启的:如果slaves试图从他同步数据,那么slaves数据集也将会被清空。
为了更好的理解为什么master持久化关闭后配置成自动重启是危险的,查看如下master和其所有slaves数据被擦去的失败模型:
1.我们设置节点A作为master,关闭了其持久化功能,节点B和节点C从节点A复制数据集。
2.然后系统崩溃了,但是它有一些自动重启的系统来重启Redis进程。但因为持久化关闭了,此节点将以空数据集重启。
3.然后节点B与节点C从A同步数据,所以节点B与节点C的数据集也空了。
任何时候数据安全都是重要的,如果Redis复制用于配置禁用持久化的master,必须也禁用Redis实例的自动重启功能。
如果这是重连并且master拥有足够的储备,那么只有并异(slave丢失的)会被发送,否则一个叫做full resynchronization的操作被触发。
当full resynchronization被触发时,master服务会开启一个后台进保存进程用于生成一个RDB文件,同时开始缓存从客户接收的所有新的写操作命令,当后台保存完成后,master迁移RDB文件到slave,slave接收RDB然后存储到磁盘并且加载到内存。然后master将所有缓存的命令发送给slave,以一个命令流的方式发送,并且是以Redis协议自身相同的格式发送。
master-slave链接由于某些原因断开时,slaves能够自动重连。如果master接收到多个同时发生的slave同步请求,它会开启一个单独的后台保存进程给它们提供服务。
这项工作是通过在master这边内存中创建一个复制流的备份。master和所有的slaves商定一个复制偏移量和一个master运行ID,所以当连接断开时,slave会重新连接并请求master继续同步。假设master运行ID是一致的,并且指定的复制偏移量是在复制备份中是可用的,那么同步将从其此点也即上次失败的位置重新开始。如果两个条件中的任何一个不满足,那么完整的重新同步操作将被执行。因为master运行ID是不会持久化到磁盘的,所以当slave重新启动时将会触发完全同步操作。
新的部分重新同步功能内部使用PSYNC命令,而老的实现则使用SYNC命令。
注:Redis slave能够检查是否正在会话的服务支持PSYNC命令,如果不支持,以SYNC命令代替。
在慢磁盘情况下,这样的操作对于Redis来说是个很有压力的操作。Redis2.8.18是第一个支持无磁盘复制的版本。此种设置下,子进程会直接将RDB文件发送给slaves,而不需要使用磁盘作为中间存储。
当然你需要把192.168.1.1 6379 替换为你的master IP地址(或者主机名)和端口号。另外,你也可以调用SLAVEOF命令,然后master主机就会对此slave进行同步。
无磁盘复制可以通过repl-diskless-sync配置指令启用。且于开始传输前等待更多slaves连接的延迟由repl-diskless-sync-delay配置指令控制。详细查看redis配置指令。
只读slaves拒绝所有的写操作命令,所以不可能发生发生在slave进行写操作错误。这不是表示此机制的设计目的是为将slave实例暴露在不可信客户端存在的网络环境中,因为一些像DEBUG或者CONFIG这样的管理员命令是依然可用的(危险依然存在)。但是,只读slave的安全性可以通过redis.conf文件中rename-command指令配置提高。
你可能会好奇为什么只读slave可以回复为可写slave和为什么有一些可写slave实例。尽管那些可写特性在主从同步或者slave重启时会被清除,但是在可写的slave中存存放临时数据少量使用场景同样也是合法的。
例如执行比较慢的set或者zset操作和将它们存储在本地key空间都是可写slave实例的使用场景。
但是要注意,在Redis 4.0之前可写slaves是不能够处理还有生存时间的未过期的keys的。也就是说如果你使用EXPIRE命令或者其他命令给key设置了最大的生存时间,那么可写slaves将忽略此key,并且你在使用读相关命令访问他的时候,它也是不可见的。你只能在keys的计数中看到,并且它仍然使用内存。所以4.0之前的可写slaves在处理含有生存时间的Key时是有问题的。
使用客户端运行时配置:
config set masterauth
但是,因为Redis使用的是异步复制,不可能确保slave一定能接收到master指向它的复制流,所以总是有一个数据丢失的窗口。如下是此机制的工作原理:
slaves每秒都ping master。
master记录每个slave ping的最后时间。
用户配置一个最小数目的slave(N),限于不大于一个最大秒数的迟滞时间(M)。
如果少于M秒内有至少N个slave连接,master将接受此写操作。如果不满足条件,则返回错误。
此操作由两个配置指令控制:
min-slaves-to-write
min-slaves-max-lag
要实现此功能需要,Redis不能依赖于master与slave的同步时钟,因为这不能解决问题并且会导致竞争条件和不同的数据集,所以Redis使用了三项主要技术以保证含过期时间的keys的复制正常生活:
Slaves实例不对Keys进行过期操作,而是等待master过期这些Keys。当Master对一个key进行过期操作(或者由于LRU算法进行删除)时,它将同时给它所有的slaves发送一个删除命令(DEL)。
尽管Master驱动过期,但是有时候slaves实例的内存中还是有可能存在理论上已过期的keys,原因是master不能及时的发送DEL命令。为了处理此种情况,slaves实例则会依据本地时钟回复对于理论上已过期的Keys的查询操作说key已不存在,即与此时数据集不一致。
在LUA脚本执行期间,不会有keys过期操作执行。当一个LUA脚本运行时,从概念上讲master处时间是冻结的,用于保证在脚本执行整个过程中keys要么是存在的要么是不存的,防止脚本执行过程中keys过期。
注:一旦一个slave实例转换成master,它能够独立进行过期keys操作,不需要老的master提供任何帮助。
Redis使用异步复制。然而,从Redis 2.8开始,slave服务器定期的从复制流获取数据。
一个master服务可以有多个slave服务。
slave从服务可以接收来自其他slave从服务的连接。除了大量slave从服务连接到master服务外,slaves也可以在层叠状结构中被其他从服务连接。
Redis复制在master一方是无阻塞的。这表示当一个或者多个slaves执行初始同步时,master服务器将持续处理请求。
Redis复制在slave一方也是无阻塞的。尽管slave正在执行初始同步,如果你在Redis配置文件中(redis.conf)设置了,那么它就同样可以使用老版本的数据处理请求。否则,你可以配置Redis在其同步时返回一个错误给客户端请求。然而,在初始同步以后,老的数据集必须被删除,新的数据必须被加载,此期间,slave将阻塞客户端的连接(如果是非常大的数据集可以达到好几秒)。
Redis复制同时也是可扩展的,为了拥有多个slaves用于只读查询或者是数据冗余。
也可以使用Redis复制来避免master将全部的数据集持久化到磁盘的消耗:一个典型的涉及到配置你的redis.conf来避免持久化到硬盘的技术,然后连接到配置的slave服务以时时保存,或者启用AOF。但是这种设置必须小心处理,因为一个master服务是以空的数据集重启的:如果slaves试图从他同步数据,那么slaves数据集也将会被清空。
关闭持久化后复制的安全性
Redis复制被使用的设置里,强烈建议开启master的持久化功能,或者因为延迟等问题不能开启时,Redis实例要被配置为操作系统重启避免自动重启。为了更好的理解为什么master持久化关闭后配置成自动重启是危险的,查看如下master和其所有slaves数据被擦去的失败模型:
1.我们设置节点A作为master,关闭了其持久化功能,节点B和节点C从节点A复制数据集。
2.然后系统崩溃了,但是它有一些自动重启的系统来重启Redis进程。但因为持久化关闭了,此节点将以空数据集重启。
3.然后节点B与节点C从A同步数据,所以节点B与节点C的数据集也空了。
任何时候数据安全都是重要的,如果Redis复制用于配置禁用持久化的master,必须也禁用Redis实例的自动重启功能。
Redis复制怎么工作
如果你设置了一个slave从服务,连接它的时候发送个PSYNC命令。如果这是重连并且master拥有足够的储备,那么只有并异(slave丢失的)会被发送,否则一个叫做full resynchronization的操作被触发。
当full resynchronization被触发时,master服务会开启一个后台进保存进程用于生成一个RDB文件,同时开始缓存从客户接收的所有新的写操作命令,当后台保存完成后,master迁移RDB文件到slave,slave接收RDB然后存储到磁盘并且加载到内存。然后master将所有缓存的命令发送给slave,以一个命令流的方式发送,并且是以Redis协议自身相同的格式发送。
master-slave链接由于某些原因断开时,slaves能够自动重连。如果master接收到多个同时发生的slave同步请求,它会开启一个单独的后台保存进程给它们提供服务。
部分重新同步
从Redis2.8开始,master和slave通常可以在复制链接断开后继续复制进程,而不需要再次请求一次完全再次同步操作。这项工作是通过在master这边内存中创建一个复制流的备份。master和所有的slaves商定一个复制偏移量和一个master运行ID,所以当连接断开时,slave会重新连接并请求master继续同步。假设master运行ID是一致的,并且指定的复制偏移量是在复制备份中是可用的,那么同步将从其此点也即上次失败的位置重新开始。如果两个条件中的任何一个不满足,那么完整的重新同步操作将被执行。因为master运行ID是不会持久化到磁盘的,所以当slave重新启动时将会触发完全同步操作。
新的部分重新同步功能内部使用PSYNC命令,而老的实现则使用SYNC命令。
注:Redis slave能够检查是否正在会话的服务支持PSYNC命令,如果不支持,以SYNC命令代替。
无磁盘复制
正常情况下,一个完全的再同步操作需要在磁盘上创建一个RDB文件,然后再从磁盘加载此RDB文件用于给slaves反馈数据。在慢磁盘情况下,这样的操作对于Redis来说是个很有压力的操作。Redis2.8.18是第一个支持无磁盘复制的版本。此种设置下,子进程会直接将RDB文件发送给slaves,而不需要使用磁盘作为中间存储。
配置
配置slave副本很简单,仅仅需要下面一行加入到slave配置文件就可以:slaveof 192.168.1.1 6379
当然你需要把192.168.1.1 6379 替换为你的master IP地址(或者主机名)和端口号。另外,你也可以调用SLAVEOF命令,然后master主机就会对此slave进行同步。
无磁盘复制可以通过repl-diskless-sync配置指令启用。且于开始传输前等待更多slaves连接的延迟由repl-diskless-sync-delay配置指令控制。详细查看redis配置指令。
只读slave
从Redis2.6开始,slaves支持默认启用的只读模式。此行为是由redis.conf文件中的配置指令slave-read-only控制,或者可以通过CONFIG SET命令启用或者禁用。只读slaves拒绝所有的写操作命令,所以不可能发生发生在slave进行写操作错误。这不是表示此机制的设计目的是为将slave实例暴露在不可信客户端存在的网络环境中,因为一些像DEBUG或者CONFIG这样的管理员命令是依然可用的(危险依然存在)。但是,只读slave的安全性可以通过redis.conf文件中rename-command指令配置提高。
你可能会好奇为什么只读slave可以回复为可写slave和为什么有一些可写slave实例。尽管那些可写特性在主从同步或者slave重启时会被清除,但是在可写的slave中存存放临时数据少量使用场景同样也是合法的。
例如执行比较慢的set或者zset操作和将它们存储在本地key空间都是可写slave实例的使用场景。
但是要注意,在Redis 4.0之前可写slaves是不能够处理还有生存时间的未过期的keys的。也就是说如果你使用EXPIRE命令或者其他命令给key设置了最大的生存时间,那么可写slaves将忽略此key,并且你在使用读相关命令访问他的时候,它也是不可见的。你只能在keys的计数中看到,并且它仍然使用内存。所以4.0之前的可写slaves在处理含有生存时间的Key时是有问题的。
配置slave到master的认证
如果master通过requirepass指令指定了密码,那么配置slave认证操作可如下:使用客户端运行时配置:
config set masterauth
只有不少于N个副本才进行写操作
从Redis2.8开始,可以允许配置当前至少N个slaves连接到master时才接收写操作请求。但是,因为Redis使用的是异步复制,不可能确保slave一定能接收到master指向它的复制流,所以总是有一个数据丢失的窗口。如下是此机制的工作原理:
slaves每秒都ping master。
master记录每个slave ping的最后时间。
用户配置一个最小数目的slave(N),限于不大于一个最大秒数的迟滞时间(M)。
如果少于M秒内有至少N个slave连接,master将接受此写操作。如果不满足条件,则返回错误。
此操作由两个配置指令控制:
min-slaves-to-write
min-slaves-max-lag
redis复制怎么处理keys的过期
Redis过期机制允许keys拥有存活时间限制,此机制依赖于redis实例的计时功能,但是Redis slaves要确保正确的复制含有过期设置的keys,即使在这些Keys被使用Lua脚本修改的时候。要实现此功能需要,Redis不能依赖于master与slave的同步时钟,因为这不能解决问题并且会导致竞争条件和不同的数据集,所以Redis使用了三项主要技术以保证含过期时间的keys的复制正常生活:
Slaves实例不对Keys进行过期操作,而是等待master过期这些Keys。当Master对一个key进行过期操作(或者由于LRU算法进行删除)时,它将同时给它所有的slaves发送一个删除命令(DEL)。
尽管Master驱动过期,但是有时候slaves实例的内存中还是有可能存在理论上已过期的keys,原因是master不能及时的发送DEL命令。为了处理此种情况,slaves实例则会依据本地时钟回复对于理论上已过期的Keys的查询操作说key已不存在,即与此时数据集不一致。
在LUA脚本执行期间,不会有keys过期操作执行。当一个LUA脚本运行时,从概念上讲master处时间是冻结的,用于保证在脚本执行整个过程中keys要么是存在的要么是不存的,防止脚本执行过程中keys过期。
注:一旦一个slave实例转换成master,它能够独立进行过期keys操作,不需要老的master提供任何帮助。
相关文章推荐
- Redis make test error:Test replication partial resync: ok psync (diskless: yes, reconnect: 1)
- Redis 主从 Replication 的配置
- redis replication
- Redis命令参考之复制(Replication)
- Redis复制(Replication)
- 解决Redis的Test replication partial resync: ok psync (diskless: yes, reconnect: 1)
- Redis Replication & Sentinel
- (十三)redis 复制(Replication)
- Redis的replication
- Redis make test error:Test replication partial resync: ok psync (diskless: yes, reconnect: 1)
- Redis 主从复制--replication 代码分析
- Redis Replication
- Redis 主从 Replication 的配置
- Replication on redis
- redis 源码学习(复制 Replication)
- Redis 主从 Replication 的配置
- Mac下安装 redis 报Test replication partial resync: ok psync (diskless: yes, reconnect: 1)
- Redis (Replication) 主从原理和相关配置说明
- Redis replication
- 关于Redis中的Replication