前言
主从复制:
- 主从复制是高可用 Redis 的基础,哨兵和集群都是在主从复制基础上实现高可用的
- 主从复制主要实现了数据的多机备份,以及对于读操作的负载均衡和简单的故障恢复
- 缺陷是故障恢复无法自动化,写操作无法负载均衡,且存储能力受到单机的限制
哨兵:
- 在主从复制的基础上,哨兵实现了自动化的故障恢复
- 缺陷是写操作无法负载均衡,存储能力受到单机的限制
- 且哨兵无法对从节点进行自动故障转移,在读写分离场景下,从节点故障会导致读服务不可用,需要对从节点做额外的监控、切换操作
集群:
- 通过集群,Redis 解决了写操作无法负载均衡,以及存储能力受到单机限制的问题
- 实现了较为完善的高可用方案
一、Redis 主从复制
1.概述
- 主从复制,是指将一台 Redis 服务器的数据,复制到其他的 Redis 服务器,前者称为主节点(Master),后者称为从节点(Slave)
- 数据的复制是单向的,只能由主节点到从节点
- 默认情况下,每台 Redis 服务器都是主节点,且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点
2.作用
数据冗余:
- 主从复制实现了数据的热备份
- 是持久化之外的一种数据冗余方式
故障恢复:
- 当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复
- 实际上是一种服务的冗余
负载均衡:
- 在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写 Redis 数据时应用连接主节点,读 Redis 数据时应用连接从节点),分担服务器负载
- 尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高 Redis 服务器的并发量
高可用基石:
- 除了上述作用以外,主从复制还是哨兵和集群能够实施的基础
- 因此可以说,主从复制是 Redis 高可用的基础
3.工作流程
- 若启动一个 Slave 机器进程,则它会向 Master 机器发送一个"sync command"命令,请求同步连接
- 无论是第一次连接还是重新连接,Master 机器都会启动一个后台进程,将数据快照保存到数据文件中(执行 RDB 操作),同时 Master 还会记录修改数据的所有命令并缓存在数据文件中
- 后台进程完成缓存操作之后,Master 机器就会向 Slave 机器发送数据文件,Slave 端机器将数据文件保存到硬盘上,然后将其加载到内存中,接着 Master 机器就会将修改数据的所有操作一并发送给Slave端机器;若 Slave 出现故障导致宕机,则恢复正常后会自动重新连接
Master 机器收到 Slave 端机器的连接后,将其完整的数据文件发送给 Slave 端机器,如果 Mater 同时收到多个 Slave 发来的同步请求,则 Master 会在后台启动一个进程以保存数据文件,然后将其发送给所有的 Slave 端机器,确保所有的 Slave 端机器都正常
三、搭建 Redis 主从复制
主机 | 主机名 | 操作系统 | IP 地址 | 主要软件 |
---|---|---|---|---|
Master | CentOS 7-1 | CentOS 7 | 192.168.126.11 | squid-3.5.28.tar.gz |
Slave1 | CentOS 7-2 | CentOS 7 | 192.168.126.12 | squid-3.5.28.tar.gz |
Slave2 | CentOS 7-3 | CentOS 7 | 192.168.126.13 | squid-3.5.28.tar.gz |
1.安装 Redis
- 三台主机都需安装 Redis
- 下载软件包传送门:redis-5.0.7.tar.gz(提取码:qwer)
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
yum -y install gcc gcc-c++ make
cd /opt
#将软件包传至该目录下
tar zxvf redis-5.0.7.tar.gz -C /opt/
cd redis-5.0.7/
make -j 4 && make PREFIX=/usr/local/redis install
cd /opt/redis-5.0.7/utils/
./install_server.sh
#回车,直到出现以下选项,手动修改为“/usr/local/redis/bin/redis-server”
Please select the redis executable path [/usr/local/bin/redis-server] /usr/local/redis/bin/redis-server
ln -s /usr/local/redis/bin/* /usr/local/bin/
netstat -natp | grep "redis"
#当 install_server.sh 脚本运行完毕,Redis 服务就已经启动,默认侦听端口为 6379
2.修改 Redis 配置文件
Master:
vim /etc/redis/6379.conf
#bind 0.0.0.0 #70行,注释掉 bind 项,默认监听所有网卡
daemonize yes #137行,开启守护进程
logfile /var/1og/redis_ 6379.1og #172行,指定日志文件目录
dir /var/lib/redis/6379 #264行,指定工作目录
appendonly yes #700行,开启 AOF 持久化功能
Slave:
vim /etc/redis/6379. conf
bind 0.0.0.0 #70行,修改监听地址为 0.0.0.0
daemonize yes #137行,开启守护进程
logfile /var/log/redis_ 6379. log #172行,指定日志文件目录
dir /var/lib/redis/6379 #264行,指定工作目录
replicaof 192.168.126.11 6379 #288行,指定要同步的 Master 节点 IP 和端口
appendonly yes #700行,开启 AOF 持久化功能
/etc/init.d/redis_6379 restart
#重启服务使配置生效
3.验证主从效果
在 Master 上看日志:
tail -f /var/log/redis_6379.log
在 Master 上验证从节点:
redis-cli info replication
- 且在此时,只能在 Master
三、Redis 哨兵模式
哨兵的核心功能就是在主从复制的基础上,哨兵引入了主节点的自动故障转移
1.原理及作用
哨兵模式的原理:
- 哨兵(Sentinel)是一个分布式系统,用于对主从结构中的每台服务器进行监控,当出现故障时通过投票机制选择新的 Master 并将所有 slave 连接到新的 Master
- 整个运行哨兵的集群的数量不得少于 3 个节点
哨兵模式的作用:
- 监控:哨兵会不断地检查主节点和从节点是否运作正常
- 自动故障转移:当主节点不能正常工作时,哨兵会开始自动故障转移操作,它会将失效主节点的其中一个从节点升级为新的主节点,并让其他从节点改为复制新的主节点
- 通知(提醒):哨兵可以将故障转移的结果发送给客户端
2.结构组成
哨兵结构由两部分组成,哨兵节点和数据节点:
- 哨兵节点:哨兵系统由一个或多个哨兵节点组成,哨兵节点是特殊的 redis 节点,不存储数据
- 数据节点:主节点和从节点都是数据节点
3.工作过程
- 哨兵的启动依赖于主从模式,所以须把主从模式安装好的情况下再去做哨兵模式,所有节点上都需要部署哨兵模式,哨兵模式会监控所有的 Redis 工作节点是否正常
- 当 Master 出现问题的时候,因为其他节点与主节点失去联系,因此会投票,投票过半就认为这个 Master 的确出现问题,然后会通知哨兵间会推选出一个哨兵来进行故障转移工作(由该哨兵来指定哪个 slave 来做新的 master),然后从 Slaves 中选取一个作为新的 Master
- 筛选方式是哨兵互相发送消息,并且参与投票,票多者当选
- 需要特别注意的是,客观下线是主节点才有的概念,即如果从节点和哨兵节点发生故障,被哨兵主观下线后,将不会再有后续的客观下线和故障转移操作(及哨兵模式只负责 Master 的方面,而不管 Slaves)
- 当某个哨兵发现主服务器挂掉了,会将 master 中的 SentinelRedistance 中的 master 改为SRI_S_DOWN(主观下线),并通知其他哨兵,告诉他们发现 master 挂掉了
- 其他哨兵在接收到该哨兵发送的信息后,也会尝试去连接 master,如果超过半数(配置文件中设置的)确认 master 挂掉后,会将 master 中的 SentinelRedistance 中的 master 改为 SRI_O_DOWN(客观下线)
4.搭建 Redis 哨兵模式
4.1 修改 Redis 哨兵模式的配置文件
vim /opt/redis-5.0.7/sentinel.conf
protected- mode no #17行,关闭保护模式
port 26379 #21行,Redis哨兵默认的监听端口
daemonize yes #26行,指定sentinel为后台启动
logfile "/var/log/sentinel.log" #36行,指定日志存放路径
dir "/var/lib/redis/6379" #65行,指定数据库存放路径
sentinel monitor mymaster 192.168.126.11 6379 2
#84行,修改,指定该哨兵节点监控 192.168.126.11:6379 这个主节点,该主节点的名称是 mymaster
#最后的 2 的含义与主节点的故障判定有关:至少需要 2 个哨兵节点同意,才能判定主节点故障并进行故障转移
sentinel down-after -milliseconds mymaster 30000#113行,判定服务器 down 掉的时间周期,默认 30000毫秒 (30秒)
sentinel failover-timeout mymaster 180000 #146行,故障节点的最大超时时间为 180000 (180秒)
4.2 启动哨兵模式
先启动 Master,再启动 Slave
cd /opt/redis-5.0.7/
redis-sentinel sentinel.conf &
4.3 查看哨兵信息
redis-cli -p 26379 info Sentinel
4.4 模拟故障
ps -ef | grep "redis"
#查看 redis-server 的进程号
kill -9 [进程号]
#杀死 Master 节点上的 redis-server 的进程号
4.5 验证结果
tail /var/log/sentinel.log
redis-cli -p 26379 info Sentinel
四、Redis 群集模式
1.概述
- 集群,即 Redis Cluster, 是 Redis 3.0 开始引入的分布式存储方案
- 集群由多个节点(Node)组成,Redis 的数据分布在这些节点中。
- 集群中的节点分为主节点和从节点:只有主节点负责读写请求和集群信息的维护,从节点只进行主节点数据和状态信息的复制
2.作用
2.1 数据分区
- 数据分区(或称数据分片)是集群最核心的功能
- 集群将数据分散到多个节点,一方面突破了 Redis 单机内存大小的限制,存储容量大大增加,另一方面每个主节点都可以对外提供读服务和写服务,大大提高了集群的响应能力
- Redis 单机内存大小受限问题,在介绍持久化和主从复制时都有提及
- 例如,如果单机内存太大,bgsave 和 bgrewriteaof 的 fork 操作可能导致主进程阻塞,主从环境下主机切换时可能导致从节点长时间无法提供服务,全量复制阶段主节点的复制缓冲区可能溢出
2.2 高可用
- 集群支持主从复制和主节点的自动故障转移(与哨兵类似),当任意节点发送故障时,集群仍然可以对外提供服务
2.2.1 Redis 集群的数据分片
- Redis 集群引入了哈希槽的概念,有 16384 个哈希槽(编号 0~16383)
- 集群的每个节点负责一部分哈希槽,每个 Key 通过 CRC16 校验后对 16384 取余来决定放置哪个哈希槽,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作
- 以 3 个节点组成的集群为例:
- 节点 A 包含 0~5469 号的哈希槽
- 节点 B 包含 5461~10922 号的哈希槽
- 节点 C 包含 10923~16383 号的哈希槽
2.2.2 Redis 集群的主从复制模型
- 集群中具有 A、B、C 三个节点,如果节点 B 失败了,整个集群就会因为缺少 5461~10922 这个范围的槽而不可用
- 为每个节点添加一个从节点(a、b、c),即整个集群便有了三个 Master 节点和三个 slave 节点,在节点 B 失败后,集群选举 b 为主节点继续服务,当 B 和 b 都失败后,整个集群将不可用
五、搭建 Redis 群集模式
1.准备
- redis 的集群一般需要 6 个节点(3 主 3 从)
- 方便起见,这里所有节点在同一台服务器上模拟,以端口号进行区分:3 个主节点端口号为 6001/6002/6003,对应的从节点端口号为 6004/6005/6006
cd /etc/redis/
mkdir -p redis-cluster/redis600{1..6)
#
for i in {1..6}
do
cp /opt/redis-5.0.7/redis.conf /etc/redis/redis-cluster/redis600$i
cp /opt/redis-5.0.7/src/redis-cli /opt/redis-5.0.7/src/redis-server /etc/redis/redis-cluster/redis600$i
done
ls -R
2开启群集功能
#其他五个文件夹的配置文件以此类推修改,注意六个端口都不一样
cd /etc/redis/redis-cluster/redis6001
vim redis. conf
#bind 127.0.0.1 #69行,注释掉 bind 项,默认监听所有网卡
protected-mode no #88行,修改,关闭保护模式
port 6001 #92行,修改,redis 监听端口,
daemonize yes #136行,开启守护进程,以独立进程启动
appendonly yes #699行,修改,开启 AOF 持久化
cluster-enabled yes #832行,取消注释,开启群集功能
cluster-config-file nodes-6001.conf #840行,取消注释,群集名称文件设置
cluster-node-t imeout 15000 #846行,取消注释群集超时时间设置
3.启动 redis 节点
#分别进入那六个文件夹,执行命令"redis-server redis.conf"来启动 redis 节点
cd /etc/redis/redis-cluster/redis6001
redis-server redis.conf
for i in {1..6}
do
cd /etc/redis/redis-cluster/redis600$i
redis-server redis.conf
done
ps -ef | grep "redis"
4.启动集群
redis-cli --cluster create 127.0.0.1:6001 127.0.0.1:6002 127.0.0.1:6003 127.0.0.1:6004 127.0.0.1:6005 127.0.0.1:6006 --cluster-replicas 1
#六个实例分为三组,每组一主一从,前面的做主节点,后面的做从节点
#下面交互的时候需要输入 yes 才可以创建
#-replicas 1 表示每个主节点有一个从节点
5.测试集群
redis-cli -p 6001 -c
#加 -c 参数,节点之间就可以互相跳转
127.0.0.1:6001> CLUSTER SLOTS
#查看节点的哈希槽编号范围
127.0.0.1:6001> set name wanger
-> Redirected to slot [5798] located at 127.0.0.1:6002
OK
#新建一个键的值
127.0.0.1:6002> CLUSTER KEYSLOT name
(integer) 5798
#查看 name 键的槽编号
ctrl+c
#退出
redis-cli -p 6001 -c
127.0.0.1:6001> KEYS *
(empty list or set)
127.0.0.1:6001>
ctrl+c
redis-cli -p 6005 -c
127.0.0.1:6005> KEYS *
1) "name"
#可以发现,对应的 slave 节点也有这条数据,但是别的节点没有