1. 概述
Redis 作为一种高性能的内存数据库,普遍用于目前主流的分布式架构系统中。为了提高系统的容错率,使用多实例的 Redis 也是必不可免的,但同样复杂度也相比单实例高出很多。
那么如何保证 Redis 的高并发和高可用?
Redis 主要有三种集群方式用来保证高并发和高可用:主从复制,哨兵模式和集群。
2. 主从复制
在分布式系统中为了解决单点问题,通常会把数据复制多个副本部署到其他机器,满足故障恢复和负载均衡等需求。Redis 也是如此,它为我们提供了复制功能,实现了相同数据的多个 Redis 副本。
复制功能是高可用 Redis 的基础,哨兵和集群都是在复制的基础上实现高可用的。
在复制的概念中,数据库分为两类。一类是主数据库(master),一类是从数据库(slave)。 master 可以进行读写操作,当写操作发生变化时,会自动将数据同步给 slave。
slave 一般只提供读操作,并接收主数据库同步过来的数据。
一个 master 可以对应多个 slave。一个 slave 只能对应一个 master。
引入主从复制的目的有两个:
- 读写分离,分担 master 的压力;
- 二是容灾备份。
Redis 的复制拓扑结构可以支持单层或多层复制关系,根据拓扑复杂性可以分为以下三种:一主一从、一主多从、树状主从结构。
2.1 一主一从
1、建立复制
参与复制的 Redis 实例划分为主节点(master)和从节点(slave)。默认情况下,Redis 都是主节点。每个从节点只能有一个主节点,而主节点可以同时具有多个从节点。复制的数据流是单向的,只能由主节点复制到从节点。
配置复制的方式有以下三种 :
-
配置文件
配置文件中加入
slaveof {masterHost } {masterPort}
,随 Redis 启动生效。 -
启动命令
在 redis-server 启动命令后加入
--slaveof {masterHost} {masterPort }
生效。 -
客户端命令
Redis服务器启动后,直接使用命令
slaveof {masterHost} { masterPort}
生效。
综上所述,slaveof
命令在使用时,可以运行期动态配置,也可以提前写到配置文件中。
为了方便测试,我们在同一台虚拟机上启动 2 个 Redis 实例,端口分别为 6379 和 6380,由于在同一台机器上,所以需要修改 6380 的配置文件,主要修改以下几个选项:
# 端口号
port 6380
# 日志文件
logfile "/usr/local/redis/log/6380.log"
# 快照文件
dbfilename 6380-dump.rdb
# 快照文件存放路径
dir ../
此时分别启动 6379 和 6380,这里的 6379 端口由于之前的操作所以存在一部分数据,而 6380 由于上面配置文件的改动,所以并不会存在数据。
6379:
6380:
注:可通过以下命令进入指定端口的客户端
./redis-cli -h ip -p port -a password
# 进入 6380 无密码
./redis-cli -h 127.0.0.1 -p 6380
然后在127.0.0.1:6380
执行如下命令:
slaveof 127.0.0.1 6379
slaveof
配置都是在从节点发起,这时 6379 作为主节点,6380 作为从节点。
复制关系建立后再去执行命令,可以看到如下:
slaveof
本身是异步命令,执行 slaveof
命令时,节点只保存主节点信息后返回,后续复制流程在节点内部异步执行。主从节点复制成功建立后,可以使用 info replication
命令查看复制相关状态。
2、断开复制
slaveof
命令不但可以建立复制,还可以在从节点执行以下命令来断开与主节点复制关系。
slaveof no one
例如在 6380 节点上执行 slaveof no one
来断开复制。流程如下:
- 断开与主节点复制关系;
- 从节点晋升为主节点。
从节点断开复制后并不会抛弃原有数据,只是无法再获取主节点上的数据变化。
3、切主
通过 slaveof
命令还可以实现切主操作,所谓切主是指把当前从节点对主节点的复制切换到另一个主节点。执行 slaveof {newMasterIp} {newMasterPort}
命令即可。
流程如下:
- 断开与旧主节点复制关系;
- 与新主节点建立复制关系;
- 删除从节点当前所有数据;
- 对新主节点进行复制操作。
4、只读
默认情况下,从节点使用以下命令配置为只读模式。
slave-read-only = yes
由于复制只能从主节点到从节点,对于从节点的任何修改主节点都无法感知,修改从节点会造成主从数据不一致。因此建议线上不要修改从节点的只读模式。
5、传输延迟
实际上,主从节点一般部署在不同机器上,复制时的网络延迟就成为需要考虑的问题,Redis 为我们提供了以下参数用于控制是否关闭 TCP_NODELAY,默认关闭。
repl-disable-tcp-nodelay no
当关闭时,主节点产生的命令数据无论大小都会及时地发送给从节点,这样主从之间延迟会变小,但增加了网络带宽的消耗。适用于主从之间的网络环境良好的场景,如同机架或同机房部署。
当开启时,主节点会合并较小的 TCP 数据包从而节省带宽。默认发送时间间隔取决于 Linux 的内核,一般默认为 40 毫秒。这种配置节省了带宽但增大主从之间的延迟。适用于主从网络环境复杂或带宽紧张的场景,如跨机房部署。
2.2 一主多从
一主多从针对读较多的场景,读由多个从节点来分担,但节点越多,主节点同步到从节点的次数也越多,影响带宽,也加重主节点的稳定。
在实际场景中,主从节点一般部署在不同机器上,上面演示的操作虽然在一台机器,但实际上就是一主一从的模式,这里演示在 3 台虚拟机上演示一主多从。
IP | 端口 | 角色 |
---|---|---|
192.168.153.128 | 6379 | master |
192.168.153.129 | 6379 | slave |
192.168.153.130 | 6379 | slave |
对于配置方式同样采取上述方式进行配置,但还存在slaveof
命令之外的配置方式,在redis.conf
配置文件中可通过配置replicaof
的方式来配置:
replicaof <masterip> <masterport>
在未配置之前,我们查看主节点和两个从节点的数据:
然后通过配置文件的方式来配置并启动。
1、主节点配置
实际上主节点无需做过多配置,但为了安全性可以配置从节点密码(这里不对配置文件做过多介绍,见文末附):
masterauth:123456789
我这里为了方便演示不做任何配置。
2、从节点配置
两从节点和主节点配置也类似,但从节点需要指定主节点的 IP 和端口,如下:
# slave1
replicaof 192.168.153.128 6379
# slave2
replicaof 192.168.153.128 6379
3、启动
在启动从节点时发现同步失败,报错如下:
1525:S 28 Dec 2021 20:50:29.690 # Error condition on socket for SYNC: Connection refused
1525:S 28 Dec 2021 20:50:30.714 * Connecting to MASTER 192.168.153.129:6379
1525:S 28 Dec 2021 20:50:30.714 * MASTER <-> REPLICA sync started
首先想到的是防火墙问题,在网上寻找解决方案时说是没有开放端口,防火墙相关操作如下:
# 查看状态
systemctl status firewalld
# 启动
systemctl start firewalld
# 开放端口
firewall-cmd --add-port=6379/