一、Redis 集群概述
Redis 主从复制
到 目前 为止,我们所学习的 Redis 都是 单机版 的,这也就意味着一旦我们所依赖的 Redis 服务宕机了,我们的主流程也会受到一定的影响,这当然是我们不能够接受的。
所以一开始我们的想法是:搞一台备用机。这样我们就可以在一台服务器出现问题的时候切换动态地到另一台去:

幸运的是,两个节点数据的同步我们可以使用 Redis 的 主从同步 功能帮助到我们,这样一来,有个备份,心里就踏实多了。

Redis 哨兵
后来因为某种神秘力量,Redis 老会在莫名其妙的时间点出问题 (比如半夜 2 点),我总不能 24 小时时刻守在电脑旁边切换节点吧,于是另一个想法又开始了:给所有的节点找一个 "管家",自动帮我监听照顾节点的状态并切换:

这大概就是 Redis 哨兵 (Sentinel) 的简单理解啦。什么?管家宕机了怎么办?相较于有大量请求的 Redis 服务来说,管家宕机的概率就要小得多啦.. 如果真的宕机了,我们也可以直接切换成当前可用的节点保证可用..

Redis 集群化
好了,通过上面的一些解决方案我们对 Redis 的 稳定性 稍微有了一些底气了,但单台节点的计算能力始终有限,所谓人多力量大,如果我们把 多个节点组合 成 一个可用的工作节点,那就大大增加了 Redis 的 高可用、可扩展、分布式、容错 等特性:

二、主从复制

主从复制,是指将一台 Redis 服务器的数据,复制到其他的 Redis 服务器。前者称为 主节点(master),后者称为 从节点(slave)。且数据的复制是 单向 的,只能由主节点到从节点。Redis 主从复制支持 主从同步 和 从从同步 两种,后者是 Redis 后续版本新增的功能,以减轻主节点的同步负担。
主从复制主要的作用
- 数据冗余: 主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
- 故障恢复: 当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复 (实际上是一种服务的冗余)。
- 负载均衡: 在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务 (即写 Redis 数据时应用连接主节点,读 Redis 数据时应用连接从节点),分担服务器负载。尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高 Redis 服务器的并发量。
- 高可用基石: 除了上述作用以外,主从复制还是哨兵和集群能够实施的 基础,因此说主从复制是 Redis 高可用的基础。
■快速体验
在 Redis 中,用户可以通过执行 SLAVEOF
命令或者设置 slaveof
选项,让一个服务器去复制另一个服务器,以下三种方式是 完全等效 的:
- 配置文件:在从服务器的配置文件中加入:
slaveof <masterip> <masterport>
- 启动命令:redis-server 启动命令后加入
--slaveof <masterip> <masterport>
- 客户端命令:Redis 服务器启动后,直接通过客户端执行命令:
slaveof <masterip> <masterport>
,让该 Redis 实例成为从节点。
需要注意的是:主从复制的开启,完全是在从节点发起的,不需要我们在主节点做任何事情。
第一步:本地启动两个节点
在正确安装好 Redis 之后,我们可以使用 redis-server --port <port>
的方式指定创建两个不同端口的 Redis 实例,例如,下方我分别创建了一个 6379
和 6380
的两个 Redis 实例:
# 创建一个端口为 6379 的 Redis 实例
redis-server --port 6379
# 创建一个端口为 6380 的 Redis 实例
redis-server --port 6380
此时两个 Redis 节点启动后,都默认为 主节点。
第二步:建立复制
我们在 6380
端口的节点中执行 slaveof
命令,使之变为从节点:
# 在 6380 端口的 Redis 实例中使用控制台
redis-cli -p 6380
# 成为本地 6379 端口实例的从节点
127.0.0.1:6380> SLAVEOF 127.0.0.1ø 6379
OK
第三步:观察效果
下面我们来验证一下,主节点的数据是否会复制到从节点之中:
- 先在 从节点 中查询一个 不存在 的 key:
127.0.0.1:6380> GET mykey
(nil)
- 再在 主节点 中添加这个 key:
127.0.0.1:6379> SET mykey myvalue
OK
- 此时再从 从节点 中查询,会发现已经从 主节点 同步到 从节点:
127.0.0.1:6380> GET mykey
"myvalue"
第四步:断开复制
通过 slaveof <masterip> <masterport>
命令建立主从复制关系以后,可以通过 slaveof no one
断开。需要注意的是,从节点断开复制后,不会删除已有的数据,只是不再接受主节点新的数据变化。
从节点执行 slaveof no one
之后,从节点和主节点分别打印日志如下:、
# 从节点打印日志
61496:M 17 Mar 2020 08:10:22.749 # Connection with master lost.
61496:M 17 Mar 2020 08:10:22.749 * Caching the disconnected master state.
61496:M 17 Mar 2020 08:10:22.749 * Discarding previously cached master state.
61496:M 17 Mar 2020 08:10:22.749 * MASTER MODE enabled (user request from 'id=4 addr=127.0.0.1:55096 fd=8 name= age=1664 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=34 qbuf-free=32734 obl=0 oll=0 omem=0 events=r cmd=slaveof')
# 主节点打印日志
61467:M 17 Mar 2020 08:10:22.749 # Connection with replica 127.0.0.1:6380 lost.
■实现原理简析

为了节省篇幅,我把主要的步骤都 浓缩 在了上图中,其实也可以 简化成三个阶段:准备阶段-数据同步阶段-命令传播阶段。下面我们来进行一些必要的说明。
身份验证 | 主从复制安全问题
在上面的 快速体验 过程中,你会发现 slaveof
这个命令居然不需要验证?这意味着只要知道了 ip 和端口就可以随意拷贝服务器上的数据了?

那当然不能够了,我们可以通过在 主节点 配置 requirepas