复制
一个 Redis 服务器执行 slaveof 命令,会向目标服务器建立主从关系,目标服务器称为主服务器(master),当前服务器称为从服务器(slave)。
复制功能共分为两个操作:
- 同步:将主服务器的数据库状态同步到从服务器;
- 命令传播:主服务器接收到的修改写入命令会传播给从服务器,从而保证主从状态一致。
同步
同步操作使用的是 PSYNC(旧版为 SYNC,只包含完整重同步),包含完整重同步和部分重同步。
当第一次执行复制操作时,会进行完整重同步,接收主服务器的全量数据。而部分重同步对应的是断线后重复制的情况,这时如果主从状态差别不大的时候,再进行完整重同步会是一个效率很低的操作,特别是当数据量很大的时候。
而部分重同步是将主从服务器之间的相差的数据进行同步,在保证了一致性的前提下,提高了复制的效率。
完整重同步
步骤如下:
- 从服务器向主服务器发送同步命令;
- 主服务器执行 BGSAVE 命令,将生成的 RDB 文件发送给从服务器;
- 从服务器接收并载入 RDB 文件,更新数据库状态与主服务器一致;
- 主服务器在执行 BGSAVE 命令同时会维护一个缓存区保存新接收的写入命令,最后会将该缓冲区的所有写入命令发送给从服务器执行,进而保证主从状态一致。
部分重同步
部分重同步主要依赖于复制偏移量和复制积压缓冲区。
复制偏移量在主服务器和从服务器各维护一份,保存的是主从服务器传播的字节数,主服务器保存的是向从服务器发送的字节数,从服务器保存的是从主服务器接收的字节数。当主从服务器的复制偏移量不相同时,说明主从服务器的状态不一致了。
复制积压缓冲区位于主服务器,底层数据结构是一个固定长度的队列。这里面保存着最近一段时间主服务器传播命令的字节数和对应的偏移量,当主从状态不一致时,根据从服务器保存的复制偏移量就可以将缓冲区中偏移量之后的数据同步到从服务器。
如果从服务器的偏移量不在复制积压缓冲区内,说明缺少的数据大于缓冲区长度,就需要进行完整重同步。
哨兵
哨兵(Sentinel)是 Redis 高可用的解决方案。下面介绍几个名词:
- Sentinel 实例:一种运行在特殊模式下的服务器;
- Sentinel 系统:由一个或多个 Sentinel 实例组成;
Sentinel 哨兵系统可以监视任意多个主服务器以及主服务器下所有从服务器。被监视的主服务器下线后,会自动将下线的主服务器属下的某个从服务器升级为新的主服务器,新的主服务器继续处理命令请求。
集群
Redis 集群是 Redis 提供的分布式数据库方案。集群通过分片来实现数据共享,并提供复制和故障转移功能。
一个 Redis 有多个节点组成,每个节点都是一个运行在集群模式下的 Redis 服务器。独立的节点通过 CLUSTER MEET 命令完成握手操作后,节点们才属于同一个集群。
Redis 集群通过分片的方式保存数据库的键值对,集群的整个数据库共分为 16384 个槽,只有当所有的槽都有对应的节点在处理时,集群才处于上线状态。
当客户端向集群中的节点发送操作键的命令时,接收到命令的节点会判断该键位于哪个槽,该槽由哪个节点负责处理,再向客户端发送MOVED错误并转向命令指向正确的节点处理。如果恰好是当前节点处理,则会直接处理返回。
集群中的节点分为主节点和从节点,主节点用于处理槽,从节点复制于某个主节点,在复制的主节点下线后,代替下线主节点继续处理命令请求。