Redis 的复制功能通过主从模式实现,允许用户为存储着目标数据库的服务器(主服务)创建多个拥有相同数据库副本的服务器(从服务)。让客户端的读请求可以分摊到从服务器中,从而提升性能。复制功能适合对数据一致性要求高、且读写比例不平衡的场景,例如读操作远多于写操作。
Sentinel,哨兵模式是Redis推荐的高可用性解决方案,用于解决和管理主从复制环境,确保主节点发生故障时能自动进行故障转移和主从切换。
集群是通过对数据进行分片,并在多个节点之间进行数据复制来提供高可用性和负载均衡。不同的节点负责不同的范围数据的读写。每个节点也有主从复制,确保当主节点发生故障时,从节点能进行故障转移。
1 复制
主服务与从服务的关系为一对多。从服务器本身也可以作为其他服务器的主服务器。
设置为从服务 | REPLICAOF host port 将当前服务器设置为服务器地址为host:port 的从服务。当前数据库会被清空,然后从主服务复制数据。 REPLICAOF no one 当前服务器取消复制,角色由从服务变为主服务。数据不会被清理。 |
ROLE | 查看当前服务器所属的角色(主服务或从服务)。 |
表 复制功能的主要命令
1.1 数据同步
图 从服务复制主服务的数据的流程
数据同步完成后,主服务每执行一个新的写命令,它就会将相同或具有相同效果的写命令发送给从服务器。
在配置中配置 “repl-diskless-sync yes ”,主服务在接收到REPLICAOF命令时,将不会再在本地创建RDB文件,而是通过套接字让从服务生成RDB文件,然后再进行导入。
1.1.1 数据不一致场景
1)异步更新引起的短暂不一致:在主服务执行完写命令之后,将相同命令发送给从服务,并且从服务成功执行该条命令这段时间,会出现不一致。
2)主服务执行完写命令之后,因故障突然下线,而导致从服务未能执行相关的写命令。
降低数据不一致的频率:
min-replicas-max-lag <interval>
min-replicas-to-write <num>
配置主服务,让其在至少有num个从服务,与其最后一次成功通信间隔不超过interval秒的情况下,才执行写命令。
1.1.2 复制缓冲区
复制缓冲区replication buffer,会在服务器成为从服务器的主服务时创建。用于存储最近一段时间内的写命令。以便新加入或从网络断开后重新连接的从服务器能增量地同步数据,而非全量同步。它有以下特点:
- 先进先出的队列,缓冲区有一个配置化的最大长度,当达到这个长度时,旧命令会被移除。
- 复制偏移量:主服务和从服务都会维护一个复制偏移量,用于跟踪它们已处理过的命令位置。当从服务重新连接时,如果其复制偏移量已不在队列中,则进行全量同步,否则增量同步(即只要执行离线期间未执行的写命令)。
1.2 脚本复制
从服务除了需要从主服务同步写命令外,还需要同步Lua脚本。
脚本传播 | 将被执行的脚本及参数复制到AOF文件以及从服务器中。 要求:脚本必须是纯函数,而非带有副作用的函数(在不同服务器上运行时可能产生不同的效果)。 |
命令传播 | 将执行脚本所产生的所有写命令用事务包裹起来,然后将事务复制到AOF文件以及从服务器中。 |
表 脚本复制模式
模式选择:
- 脚本体积不大,且执行的计算不多,但会产生大量命令调用。则使用脚本传播模式。
- 脚本体积大,执行的计算多,但只产生少量命令调用,则使用命令传播模式。
2 哨兵模式 Sentinel
Sentinel 是一个独立运行的进程,负责监控Redis主从集群的状态,执行故障的转移与配置更新。
通常部署多个Sentinel节点形成Sentinel集群,实现高可用与故障容错。
监控 | 定期向主节点和从节点发送PING命令,检查其健康状态。 |
故障转移 | 当主服务发生故障下线时,会选择合适的从服务来替代其成为主服务。当出故障的主服务重新上线时,会成为从服务。 |
事件通知 | 可以通过API等方式将故障信息通知管理员。 |
表 Sentinel的功能
2.1 配置
在sentinel.conf 文件中进行配置,该配置文件至少需要包含下面的选项:
sentinel monitor <master-name> <ip> <port> <quorum>
是用于指定需要监控的主服务器(一个sentinel可以监控多个主服务)。
master-name 用于指定主服务的名字。
ip及port 未主服务的ip地址和端口号。
quorum 用于指定判断这个主服务下线需要的Sentinel数量。
2.1.1 Sentinel的节点数量
推荐让多个Sentinel节点去监视一个主服务,且这些节点最好在不同服务器上。节点推荐数量为大等于3且奇数。配置quorum 是,其参数值应当为节点数量的半数以上。这样就符合少数服从多数的原则。
2.1.2 新主服务的选举规则
当现有的主服务下线时,Sentiner会根据以下规则选举出新的主服务。
- 首先从候选名单剔除不符合条件的从服务。
- 否决已下线及长时间没有回复心跳检测的。
- 否决长时间没有与主服务通信的。
- 否决所有优先级为0 的。
- 在剩余候选名单中选出主服务。
- 首先是优先级最高的。
- 然后是复制偏移量最大的。
- 最后运行ID(随机生成的)最小的。
在redis服务器中通过replica-priority选项来配置从服务器的优先级,默认值为100,值越小,优先级越高。但如果为0,则永远不会被选为主服务器。
3 集群 Cluster模式
图 Redis集群 Cluster模式
Cluster模式,将数据分为16384个槽位,每个节点管理一部分的槽位,当客户端发送请求时,会根据键的哈希值将请求路由到相应的节点。
每个节点又包括1个主节点及n(不小于1)个从节点。主节点负责客户端的读写请求。从节点则负责对主节点进行负责。当主节点发生故障的时候,从节点替换成为新的主节点。
3.1 分片与重分片
Cluster 将整个数据库空间划分为16384个槽位来实现数据分片。集群中的各个主节点分别负责处理其中的一部分槽。
当用户向集群中添加新节点时,可以通过发送几条简单的命令,让相应的槽及槽中存储的数据迁移至新节点。被移除的节点也会将自己负责处理的槽及数据转交给集群中其他节点负责。整个重分片过程都可以在线进行,无须因此而停机。
3.1.1 散列标签
默认情况下,集群根据用户输入的整个键来计算出所属的槽。有时,我们期望在同一节点存储多个相关联的键。 例如键值:user1和user2。
图 键user1 与 user2 的槽值
可以通过散列标签功能,来让这两个原本不属于同一个槽的键值,处于同一个槽。用大括号{}包围并且非空的字符串字串。
图 散列标签
注意:{user}1 与user1 在redis中不属于同一个键。