全是干货的技术号: 本文已收录在github,欢迎 star/fork: https://github.com/Wasabi1234/Java-Interview-Tutorial
在Redis复制的基础上(不包括Redis Cluster或Redis Sentinel作为附加层提供的高可用功能),使用和配置主从复制非常简单,能使得从 Redis 服务器(下文称 slave)能精确得复制主 Redis 服务器(下文称 master)的内容。每次当 slave 和 master 之间的连接断开时, slave 会自动重连到 master 上,并且无论这期间 master 发生了什么, slave 都将尝试让自身成为 master 的精确副本。
该系统的运行依靠三个重要机制:
Redis使用默认的异步复制,低延迟且高性能,适用于大多数 Redis 场景。但是,slave会异步确认其从master周期接收到的数据量。
客户端可使用 WAIT 命令来请求同步复制某些特定的数据。但是,WAIT 命令只能确保在其他 Redis 实例中有指定数量的已确认的副本:在故障转移期间,由于不同原因的故障转移或是由于 Redis 持久性的实际配置,故障转移期间确认的写入操作可能仍然会丢失。
redis.conf
以避免对磁盘进行持久化,然后连接一个 slave ,配置为不定期保存或是启用 AOF。但是,这个设置必须小心处理,因为重启的 master 将从一个空数据集开始:如果一个 slave 试图与它同步,那么这个 slave 也会被清空!如下两种实现方式:
无需重启,但是不便于配置的管理。
slaveof ip port
slave-read-only yes
虽然可统一配置,但是需要重启。
bgsave
,在本地生成一份RDB快照client-output-buffer-limit slave 256MB 64MB 60RDB生成、RDB通过网络拷贝、slave旧数据的清理、slave aof rewrite,很耗费时间
如果复制的数据量在4G~6G之间,那么很可能全量复制时间消耗到1分半到2分钟
master 开启一个后台save进程,以便生成一个 RDB 文件。同时它开始缓冲所有从客户端接收到的新的写入命令。当后台save完成RDB文件时, master 将该RDB数据集文件发给 slave, slave会先将其写入磁盘,然后再从磁盘加载到内存。再然后 master 会发送所有缓存的写命令发给 slave。这个过程以指令流的形式完成并且和 Redis 协议本身的格式相同。
当主从之间的连接因为一些原因崩溃之后, slave 能够自动重连。如果 master 收到了多个 slave 要求同步的请求,它会执行一个单独的后台保存,以便于为多个 slave 服务。
在使用 Redis 复制功能时的设置中,推荐在 master 和 slave 中启用持久化。
当不可能启用时,例如由于非常慢的磁盘性能而导致的延迟问题,应该配置实例来避免重启后自动重新开始复制。
关闭持久化并配置了自动重启的 master 是危险的:
当 Redis Sentinel 被用于高可用并且 master 关闭持久化,这时如果允许自动重启进程也是很危险的。例如, master 可以重启的足够快以致于 Sentinel 没有探测到故障,因此上述的故障模式也会发生。
任何时候数据安全性都是很重要的,所以如果 master 使用复制功能的同时未配置持久化,那么自动重启进程这项就该被禁用。
复制偏移量即使在没有一个 slave 连接到 master 时,也会自增,所以基本上每一对给定的
Replication ID, offset
都会标识一个 master 数据集的确切版本。
slave使用psync
从master复制,psync runid offset
master会根据自身情况返回响应信息:
slave 连接到 master 时,它们使用 PSYNC 命令来发送它们记录的旧的 master replication ID 和它们至今为止处理的偏移量。通过这种方式, master 能够仅发送 slave 所需的增量部分。
但若 master 的缓冲区中没有足够的命令积压缓冲记录,或者如果 slave 引用了不再知道的历史记录(replication ID),则会转而进行一个全量重同步:在这种情况下, slave 会得到一个完整的数据集副本,从头开始。即:
slave如果跟master有网络故障,断开连接会自动重连。 master如果发现有多个slave都重新连接,仅会启动一个rdb save操作,用一份数据服务所有slave。
host
和ip
,但复制流程尚未开始master host和ip配置在 redis.conf
中的 slaveof主从节点互相都会发送heartbeat信息。
master默认每隔10秒发送一次heartbeat,salve node每隔1秒发送一个heartbeat。
Redis 2.8开始支持主从复制的断点续传
主从复制过程,若网络连接中断,那么可以接着上次复制的地方,继续复制下去,而不是从头开始复制一份。
master和slave都要知道各自数据的offset,才能知晓互相之间的数据不一致情况。
master会在内存中维护一个backlog,默认1MB。master给slave复制数据时,也会将数据在backlog中同步写一份。
backlog主要是用做全量复制中断时候的增量复制
。
master和slave都会保存一个replica offset还有一个master id,offset就是保存在backlog中的。若master和slave网络连接中断,slave会让master从上次replica offset开始继续复制。但若没有找到对应offset,就会执行resynchronization。
根据host+ip定位master node,是不靠谱的,如果master node重启或者数据出现了变化,那么slave node应该根据不同的run id区分,run id不同就做全量复制。
如果需要不更改run id重启redis,可使用:
redis-cli debug reload
master在内存中直接创建RDB,然后发送给slave,不会在自己本地持久化。
只需要在配置文件中开启repl-diskless-sync yes
即可.
等待 5s 再开始复制,因为要等更多 slave 重连
repl-diskless-sync-delay 5
Redis 的过期机制可以限制 key 的生存时间。此功能取决于 Redis 实例计算时间的能力,但是,即使使用 Lua 脚本更改了这些 key,Redis slaves 也能正确地复制具有过期时间的 key。
为实现这功能,Redis 不能依靠主从使用同步时钟,因为这是一个无法解决的问题并且会导致 race condition 和数据不一致,所以 Redis 使用三种主要的技术使过期的 key 的复制能够正确工作:
一旦 slave 被提升 master ,它将开始独立过期 key,而不需要任何旧 master 帮助。
Redis 4.0 开始,当一个实例在故障转移后被提升为 master 时,它仍然能够与旧 master 的 slave 进行部分重同步。为此,slave 会记住旧 master 的旧 replication ID 和复制偏移量,因此即使询问旧的 replication ID,也可以将部分复制缓冲提供给连接的 slave 。
但是,升级的 slave 的新 replication ID 将不同,因为它构成了数据集的不同历史记录。例如,master 可以返回可用,并且可以在一段时间内继续接受写入命令,因此在被提升的 slave 中使用相同的 replication ID 将违反一对复制标识和偏移对只能标识单一数据集的规则。
另外,slave 在关机并重新启动后,能够在 RDB 文件中存储所需信息,以便与 master 进行重同步。这在升级的情况下很有用。当需要时,最好使用 SHUTDOWN 命令来执行 slave 的保存和退出操作。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。