Redis集群和高可用


虽然Redis可以实现单机的数据持久化,但无论是RDB也好或者AOF也好,都解决不了单点宕机问题,即一旦单台 redis服务器本身出现系统故障、硬件故障等问题后,就会直接造成数据的丢失。此外,单机的性能也是有极限的,因此需要使用另外的技术来解决单点故障和性能扩展的问题。

一、Redis主从复制

在这里插入图片描述

redis主从复制架构

主从模式(master/slave),可以实现Redis数据的跨主机备份。
程序端连接到高可用负载的VIP,然后连接到负载服务器设置的Redis后端real server,此模式不需要在程序里面配 置Redis服务器的真实IP地址,当后期Redis服务器IP地址发生变更只需要更改redis 相应的后端real server即可, 可避免更改程序中的IP地址设置。
在这里插入图片描述
主从复制特点:

  • 一个master可以有多个slave
  • 一个slave只能有一个master
  • 数据流向是从master到slave单向的

主从复制实现

Redis Slave 也要开启持久化并设置和master同样的连接密码,因为后期slave会有提升为master的可能,Slave 端切换master同步后会丢失之前的所有数据,而通过持久化可以恢复数据。

一旦某个Slave成为一个master的slave,Redis Slave服务会清空当前redis服务器上的所有数据并将master的数据导入到自己的内存,但是如果只是断开同步关系后,则不会删除当前已经同步过的数据。
当配置Redis复制功能时,强烈建议打开主服务器的持久化功能。否则的话,由于延迟等问题,部署的主节点Redis服务应该要避免自动启动。

在关闭主服务器上的持久化,并同时开启自动拉起进程的情况下,即便使用Sentinel来实现Redis的高可用性,也是非常危险的。因为主服务器可能拉起得非常快,以至于Sentinel在配置的心跳时间间隔内没有检测到主服务器已被重启,然后还是会执行上面的数据丢失的流程。无论何时,数据安全都是极其重要的,所以应该禁止主服务器关闭持久化的同时自动启动。

命令行配置

命令解释
info replication查看主从状态
repliacaof 或者 ( slaveof )添加主从配置 例子: repliacaof 192.168.91.100 6379
CONFIG SET masterauth 123456临时设置密码
repliacaof masterip masterport临时添加主设置
REPLICAOF no one取消 主从配置

启用主从同步
默认redis 状态为master,需要转换为slave角色并指向master服务器的IP+PORT+Password在从节点执行 REPLICAOF MASTER_IP PORT 指令可以启用主从同步复制功能,早期版本使用 SLAVEOF 指令。

配置操作
主上面的配置

[root@localhost ~]#vim /etc/redis/6379.conf 
70 bind 0.0.0.0
监听端口改为任意端口
requirepass  12345
设置密码

172 logfile /var/log/redis_6379.log
指定日志文件目录
264 dir /var/lib/redis/6379
指定工作目录
700 appendonly yes
开启AOF持久化功能

在这里插入图片描述

从的配置

70 bind 0.0.0.0
将监听端口改为任意端口
172 logfile /var/log/redis_6379.log
指定日志文件目录
264 dir /var/lib/redis/6379
指定工作目录
288  replicaof 192.168.91.100 6379
设置 主从配置
masterauth   123456
如果有密码  设置此行

700 appendonly yes
开启AOF持久化功能

在这里插入图片描述
在这里插入图片描述
主从复制成功。

删除主从同步
在从节点执行 REPLIATOF NO ONE 指令可以取消主从复制。

主从复制故障恢复

从down掉。
在这里插入图片描述
master节点故障和恢复
在这里插入图片描述
master故障后,只能手动提升一个slave为新master,不支持自动切换。之后将其他的slave节点重新指定新的master为master节点。
Master的切换会导致master_replid发生变化,slave之前的master_replid就和当前master不一致从而会引发所有 slave的全量同步。

在这里插入图片描述

主从复制优化

主从复制过程

Redis主从复制分为全量同步和增量同步。
全量复制过程
在这里插入图片描述
首次主从同步是全量同步,主从同步可以让从服务器从主服务器同步数据,而且从服务器还可再有其它的从服务器,即另外一台redis服务器可以从一台从服务器进行数据同步,redis 的主从同步是非阻塞的,master收到从服务器的psync(2.8版本之前是SYNC)命令,会fork一个子进程在后台执行bgsave命令,并将新写入的数据写入到一个缓冲区中,bgsave执行完成之后,将生成的RDB文件发送给slave,然后master再将缓冲区的内容以redis协议格式再全部发送给slave,slave 先删除旧数据,slave将收到后的RDB文件载入自己的内存,再加载所有收到缓冲区的内容 从而这样一次完整的数据同步Redis全量复制一般发生在Slave首次初始化阶段,这时Slave需要将Master上的所有数据都复制一份。

增量复制过程
在这里插入图片描述
全量同步之后再次需要同步时,从服务器只要发送当前的offset位置(等同于MySQL的binlog的位置)给主服务器,然后主服务器根据相应的位置将之后的数据(包括写在缓冲区的积压数据)发送给从服务器,再次将其保存到从节点内存即可。

主从同步具体过程
1)从服务器连接主服务器,发送PSYNC(同步)命令。
2)主服务器接收到PSYNC命令后,开始执行BGSAVE命令生成RDB快照文件并使用缓冲区记录此后执行的所有写命令。
3)主服务器BGSAVE执行完后,向所有从服务器发送RDB快照文件,并在发送期间继续记录被执行的写命令。
4)从服务器收到快照文件后丢弃所有旧数据,载入收到的快照至内存。
5)主服务器快照发送完毕后,开始向从服务器发送缓冲区中的写命令。
6)从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令。
7)后期同步会先发送自己slave_repl_offset位置,只同步新增加的数据,不再全量同步。

在这里插入图片描述
在这里插入图片描述
复制缓冲区(环形队列)配置参数:

复制缓冲区大小,建议要设置足够大
repl-backlog-size 1mb 


Redis同时也提供了当没有slave需要同步的时候,
多久可以释放环形队列:repl-backlog-ttl  3600   最长保持时间  3600

Redis 环形队列(Circular Queue)是一种特殊的队列数据结构,它在 Redis 中通常使用列表(List)来实现。环形队列的主要特点是当队列达到最大长度时,新元素会覆盖最旧的元素,形成一个循环。
作用:
复制缓冲区
作用:存储最近执行的写命令,用于主从复制。
实现:固定大小的循环缓冲区。
重要性:支持部分重同步,提高复制效率。

初次同步:
主节点生成RDB文件发送给从节点
同时将新写入的命令存入复制缓冲区

断线重连:
从节点重连后,请求部分重同步
主节点检查复制缓冲区,决定是否可以部分重同步

避免全量复制

  • 第一次全量复制不可避免,后续的全量复制可以利用小主节点(内存小),业务低峰时进行全量。
  • 节点运行ID不匹配:主节点重启会导致RUNID变化,可能会触发全量复制,可以利用故障转移,例如哨兵或集群,而从节点重启动,不会导致全量复制。
  • 复制积压缓冲区不足: 当主节点生成的新数据大于缓冲区大小,从节点恢复和主节点连接后,会导致全量复制.解决方法将repl-backlog-size 调大。

避免复制风暴
单主节点复制风暴
当主节点重启,多从节点复制。通过更换拓扑即可解决该问题。
在这里插入图片描述
单机器多实例复制风暴
机器宕机后,大量全量复制
解决方法:主节点分散多机器。
在这里插入图片描述

主从同步优化配置

Redis在2.8版本之前没有提供增量部分复制的功能,当网络闪断或者slave Redis重启之后会导致主从之间的全量同步,即从2.8版本开始增加了部分复制的功能。

相关配置含义
repl-diskless-sync no是否使用无盘同步RDB文件,默认为no,no为不使用无盘,需要将RDB文件保存到磁盘后再发送给slave,yes为支持无盘,支持无盘就是RDB文件不需要保存至本地磁盘,而且直接通过socket文件发送给slave
repl-diskless-sync-delay 5无磁盘复制时,服务器等待的延迟时间
repl-ping-slave-period 10slave端向server端发送ping的时间间隔,默认为10秒
repl-timeout 60设置主从ping连接超时时间,超过此值无法连接,master_link_status显示为down,并记录错误日志
repl-disable-tcp-nodelay no是否启用TCP_NODELAY,如设置成yes,则redis会合并小的TCP包从而节省带宽, 但会增加同步延迟(40ms),造成master与slave数据不一致,假如设置成no,则redis master会立即发送同步数据,没有延迟,yes关注网络性能,no关注redis服务中的数据一致性。
repl-backlog-size 1mbmaster的写入数据缓冲区,用于记录自上一次同步后到下一次同步过程中间的写入命令,计算公式:repl-backlog-size = 允许从节点最大中断时长 * 主实例offset每秒写入量,比如master每秒最大写入64mb,最大允许60秒,那么就要设置为64mb*60秒=3840MB(3.8G),建议此值是设置的足够大
repl-backlog-ttl 36003600秒 如果一段时间后没有slave连接到master,则backlog size的内存将会被释放。如果值为0则 表示永远不释放这部份内存。
slave-priority 100slave端的优先级设置,值是一个整数,数字越小表示优先级越高。当master故障时将会按照优先级来选择slave端进行恢复,如果值设置为0,则表示该slave永远不会被选择。
min-replicas-to-write 1设置一个master的可用slave不能少于多少个,否则master无法执行写
min-slaves-max-lag 20设置至少有上面数量的slave延迟时间都大于多少秒时,master不接收写操作(拒绝写入)

二、哨兵模式 (Sentinel)

在这里插入图片描述

redis集群介绍

主从架构无法实现master和slave角色的自动切换,即当master出现redis服务异常、主机断电、磁盘损坏等问题导致master无法使用,而redis主从复制无法实现自动的故障转移(将slave 自动提升为新master),需要手动修改环境配置,才能切换到slave redis服务器,另外当单台Redis服务器性能无法满足业务写入需求的时候,也无法横向扩展Redis服务的并行写入性能。

需要解决以上的两个核心问题:

  • master和slave角色的无缝切换,让业务无感知从而不影响业务使用
  • 可横向动态扩展Redis服务器,从而实现多台服务器并行写入以实现更高并发的目的。

Redis 集群实现方式:

  • 客户端分片: 由应用决定将不同的KEY发送到不同的Redis服务器
  • 代理分片: 由代理决定将不同的KEY发送到不同的Redis服务器,代理程序如:codis,twemproxy等
  • Redis Cluster

哨兵 (Sentinel)工作原理

Sentinel架构
在这里插入图片描述
Sentinel 故障转移
在这里插入图片描述
Sentinel 进程是用于监控redis集群中Master主服务器工作的状态,在Master主服务器发生故障的时候,可以实现Master和Slave服务器的切换,保证系统的高可用,此功能在redis2.6+的版本已引用,Redis的哨兵模式到了2.8版本之后就稳定了下来。一般在生产环境也建议使用Redis的2.8版本的以后版本。

哨兵(Sentinel) 是一个分布式系统,可以在一个架构中运行多个哨兵(sentinel) 进程,这些进程使用流言协议(gossip protocols)来接收关于Master主服务器是否下线的信息,并使用投票协议(Agreement Protocols)来决定是否执行自动故障迁移,以及选择哪个Slave作为新的Master。

每个哨兵(Sentinel)进程会向其它哨兵(Sentinel)、Master、Slave定时发送消息,以确认对方是否”活”着,如果发现对方在指定配置时间(此项可配置)内未得到回应,则暂时认为对方已离线,也就是所谓的”主观认为宕机” (主观:是每个成员都具有的独自的而且可能相同也可能不同的意识),英文名称:Subjective Down,简称SDOWN。

有主观宕机,对应的有客观宕机。当“哨兵群”中的多数Sentinel进程在对Master主服务器做出SDOWN 的判断,并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后,得出的Master Server下线判断,这种方式就是“客观宕机”(客观:是不依赖于某种意识而已经实际存在的一切事物),英文名称是:Objectively Down, 简称 ODOWN。

通过一定的vote算法,从剩下的slave从服务器节点中,选一台提升为Master服务器节点,然后自动修改相关配置,并开启故障转移(failover)。Sentinel 机制可以解决master和slave角色的自动切换问题,但单个 Master 的性能瓶颈问题无法解决,类似于MySQL中的MHA功能。

Redis Sentinel中的Sentinel节点个数应该为大于等于3且最好为奇数,因为投票不会出现偶数的问题。

客户端初始化时连接的是Sentinel节点集合,不再是具体的Redis节点,但Sentinel只是配置中心不是代理。Redis Sentinel 节点与普通redis 没有区别,要实现读写分离依赖于客户端程序。redis 3.0 之前版本中,生产环境一般使用哨兵模式,3.0后推出redis cluster功能,可以支持更大规模的生产环境。

Sentinel的三个定时任务

  • 每10秒每个sentinel对master和slave执行info,​ 发现slave节点,确认主从关系。

  • 每2秒每个sentinel通过master节点的channel交换信息(pub/sub)。
    ​ 通过sentinel__:hello频道交互

​ 交互对节点的“看法”和自身信息

  • 每1秒每个sentinel对其他sentinel和redis执行ping。

实现哨兵

主从复制

实现哨兵的前提是已经实现了一个redis的主从复制的运行环境,从而实现一个一主两从基于哨兵的高可用。
注意:
master 的配置文件中masterauth 和slave 都必须相同。

先实现主从复制即可。过程同上,不再赘述。
在所有的主从节点配置

vim /etc/redis.conf
masterauth "123456"
requirepass "123456"

masterauth “123456”,设置主节点的认证密码,在主从复制中,从节点连接主节点时使用。当一个Redis实例作为从节点时,它需要这个密码来认证主节点,从节点使用这个密码向主节点证明自己有权限进行数据同步。主节点设置了访问密码后,从节点必须提供正确的密码才能连接。

requirepass “123456”,设置Redis服务器的访问密码。用于客户端连接Redis服务器时的认证。任何客户端(包括redis-cli)连接到这个Redis实例时,都需要提供这个密码,未提供正确密码的连接将被拒绝。

在这里插入图片描述
客户端登录未加密码登录,会显示权限拒绝。

在这里插入图片描述
使用-a选项,登录数据库,即不会出现权限拒绝。主从复制配置完成。

哨兵配置文件

sentinel配置
Sentinel实际上是一个特殊的redis服务器,有些redis指令支持,但很多指令并不支持。默认监听在26379/tcp端口。
哨兵可以不和Redis服务器部署在一起,但一般部署在一起以节约成本。

所有redis节点使用相同的配置文件。
如果是编译安装,在源码包目录下有sentinel.conf的配置文件,复制在安装目录即可。
在这里插入图片描述
哨兵配置文件
在这里插入图片描述

bind 0.0.0.0 
修改监听的IP地址
port 26379
默认的端口
daemonize no
Sentinel将在前台运行,不会成为守护进程。适合与systemd等进程管理工具一起使用。no则相反。
pidfile /apps/resdis/run/redis-sentinel.pid
指定进程ID文件的位置。即使在非守护进程模式下,也会创建此文件。
logfile /apps/redis/log/sentinel_26379.log
指定日志文件的位置。所有Sentinel的日志将写入此文件。
dir /tmp
设置Sentinel的工作目录。用于存储临时文件。
 sentinel monitor mymaster 192.168.232.10 6379 2
 mymaster是集群的名称,此行指定当前mymaster集群中master服务器的地址和端口。2为法定人数限制(quorum),即有几个sentinel认为master down了就进行故障转移,一般此值是所有sentinel节点(一般总数是>=3的 奇数,如:3,5,7等)的一半以上的整数值,比如,总数是3,即3/2=1.5,取整为2,是master的ODOWN客观下线的依据。
 sentinel auth-pass mymaster 123456
 mymaster集群中master的密码,注意此行要在上面行的下面
sentinel down-after-milliseconds mymaster 3000
(SDOWN)判断mymaster集群中所有节点的主观下线的时间,    单位:毫秒
sentinel parallel-syncs mymaster 1
发生故障转移后,可以同时向新master同步数据的slave的数量,数字越小总同步时间越长,但可以减轻新master的负载压力
sentinel failover-timeout mymaster 180000
所有slaves指向新的master所需的超时时间,单位:毫秒
sentinel deny-scripts-reconfig yes
禁止修改脚本

准备service文件

cat  >> /lib/systemd/system/redis-sentinel.service  <<eof
[Unit]
Description=Redis Sentinel
After=network.target
[Service]
ExecStart=/apps/redis/bin/redis-sentinel /apps/redis/etc/sentinel.conf --supervised systemd
ExecStop=/bin/kill -s QUIT $MAINPID
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
eof

systemctl daemon-reload 
systemctl start redis-sentinel.service

注意要更改配置文件的属主属组。

关闭主验证实验效果
在这里插入图片描述
发现只有sdwon,排查后端从的配置文件。
在这里插入图片描述
配置文件中的节点一致,起不来。
更改完myid后,配置成功。
在这里插入图片描述
在这里插入图片描述
配置成功。

三、Redis cluster架构

在这里插入图片描述

工作原理

在哨兵sentinel机制中,可以解决redis高可用问题,即当master故障后可以自动将slave提升为master,从而可以保证redis服务的正常使用,但是无法解决redis单机写入的瓶颈问题,即单机redis写入性能受限于单机的内存大小、并发数量、网卡速率等因素。为了解决单机性能的瓶颈,提高Redis 性能,可以使用分布式集群的解决方案。

早期Redis 分布式集群部署方案:

  1. 客户端分区:由客户端程序决定key写分配和写入的redis node,但是需要客户端自己实现写入分配、高可用管理和故障转移等。
  2. 代理方案:基于三方软件实现redis proxy,客户端先连接之代理层,由代理层实现key的写入分配,对客户端来说是有比较简单,但是对于集群管节点增减相对比较麻烦,而且代理本身也是单点和性能瓶颈。

redis 3.0版本之后推出了无中心架构的redis cluster机制,在无中心的redis集群当中,其每个节点保存当前节点数据和整个集群状态,每个节点都和其他所有节点连接。

Redis Cluster特点:

  1. 所有Redis节点使用(PING机制)互联。
  2. 集群中某个节点的是否失效,是由整个集群中超过半数的节点监测都失效,才能算真正的失效。
  3. 客户端不需要proxy即可直接连接redis,应用程序中需要配置有全部的redis服务器IP。
  4. redis cluster把所有的redis node 平均映射到 0-16383个槽位(slot)上,读写需要到指定的redis node上进行操作,因此有多少个redis node相当于redis 并发扩展了多少倍,每个redis node 承担16384/N个槽位。
  5. Redis cluster预先分配16384个(slot)槽位,当需要在redis集群中写入一个key -value的时候,会使用CRC16(key) mod 16384之后的值,决定将key写入值哪一个槽位从而决定写入哪一个Redis节点上,从而有效解决单机瓶颈。

Redis cluster架构

在这里插入图片描述
Redis cluster基本架构
假如三个主节点分别是:A, B, C 三个节点,采用哈希槽 (hash slot)的方式来分配16384个slot 的话它们三个节点分别承担的slot 区间可以是:

节点A覆盖 0-5460
节点B覆盖 5461-10922
节点C覆盖 10923-16383

在这里插入图片描述

Redis cluster主从架构
Redis cluster的架构虽然解决了并发的问题,但是又引入了一个新的问题,每个Redis master的高可用。如何解决?那就是对每个master 节点都实现主从复制,从而实现 redis 高可用性。
在这里插入图片描述
部署架构
6台服务器,分别是三组master/slave,适用于生产环境。
在这里插入图片描述

实现集群

架构:开启多实例来实现redis。
redis集群一般需要3个节点,3主3从。我们在同一台服务器上进行模拟:以端口号进行区分。
3个主节点的端口号:6001、6002、6003
对应的从节点的端口号:6004、6005、6006
端口号可能随机分配。

新建集群文件目录

cd  /apps/redis/
mkdir -p redis-cluster/redis600{1..6}

准备配置文件到每个文件夹

for i in {1..6}
do
cp /data/redis-5.0.7/redis.conf /apps/redis/redis-cluster/redis600$i
cp /data/redis-5.0.7/src/redis-cli /data/redis-5.0.7/src/redis-server /apps/redis/redis-cluster/redis600$i
done

在这里插入图片描述
开启集群功能

protected-mode no						#88行,修改,关闭保护模式
port 6001								#92行,修改,redis监听端口,
daemonize yes							#136行,开启守护进程,以独立进程启动  如果是 systemd 启动不需要修改
cluster-enabled yes						#832行,取消注释,开启群集功能
cluster-config-file nodes-6001.conf		#840行,取消注释,群集名称文件设置
cluster-node-timeout 15000				#846行,取消注释群集超时时间设置
appendonly yes							#700行,修改,开启AOF持久化
sed -i.bak  's/bind 127.0.0.1/bind 0.0.0.0/' redis.conf 
sed -i.bak  's/protected-mode yes/protected-mode no/' redis.conf 
sed -i.bak  's/^port .*/port 6001/' redis.conf
sed -i.bak  's/^daemonize .*/daemonize yes/' redis.conf 
sed -i.bak  's/^# cluster-enabled .*/cluster-enabled yes/' redis.conf 
sed -i.bak  's/^# cluster-config-file .*/cluster-config-file nodes-6001.conf/' redis.conf 
sed -i.bak  's/^# cluster-node-timeout .*/cluster-node-timeout 15000/' redis.conf
sed -i.bak  's/appendonly no/appendonly yes/' redis.conf

复制配置文件

for i in {2..6}
do
\cp -f  ./redis.conf   /apps/redis/redis-cluster/redis600${i}
done
并修改监听端口

脚本启动

for d in {1..6}
do
cd /apps/redis/redis-cluster/redis600$d
redis-server redis.conf
done

在这里插入图片描述
启动集群

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
六个实例分为三组,每组一主一从,前面的做主节点,后面的做从节点。
--replicas 1 表示每个主节点有1个从节点。

在这里插入图片描述
测试集群

redis-cli -p 6001  -c
加上-c参数,节点之间就可以互相跳转
cluster slots 查看节点的哈希槽编号范围

在这里插入图片描述
查看节点信息。
在这里插入图片描述

  • 15
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值