一、概述
1.redis 集群有三种模式,分别是主从同步/复制、哨兵模式、Cluster,下面会介绍这三种模式的工作方式,以及搭建Cluster集群
2.在Redis中,实现高可用的技术主要包括持久化、主从复制、哨兵和集群,下面分别说明它们的作用,以及解决了什么样的问题。
持久化:持久化是最简单的高可用方法(有时甚至不被归为高可用的手段),主要作用是数据备份,即将数据存储在硬盘,保证数据不会因进程退出而丢失。
主从复制:主从复制是高可用Redis的基础,哨兵和集群都是在主从复制基础上实现高可用的。主从复制主要实现了数据的多机备份,以及对于读操作的负载均衡和简单的故障恢复。缺陷:故障恢复无法自动化;写操作无法负载均衡;存储能力受到单机的限制。
哨兵:在主从复制的基础上,哨兵实现了自动化的故障恢复。缺陷:写操作无法负载均衡;存储能力受到单机的限制。
集群:通过集群,Redis解决了写操作无法负载均衡,以及存储能力受到单机限制的问题,实现了较为完善的高可用方案。
(一)集群介绍
1.redis是一个开源的key
value储存系统,受到了广大互联网公司的使用开发,redis3.0版本之前只支持单例模式,在3.0版本后及以后才有支持集群
redis集群采用p2p模式,是完全去中心化的,不存在中心节点或者代理节点
2.为了实现集群的高可用,及判断节点是否健康(内否正常使用),redis-cluster有一个投票容错机制;如果集群中超过一半的节点投票认为一个节点挂了(没有从节点)这个集群就会停止服务;因为集群内置了16384个slot(哈希槽),并且把所有的物理节点映射到这个16384[0-16384]个slot上,或者说把这些slot均等的分配给了各个节点,当需要在redis集群存放一个数据(key-value)时,redis会先对这个key进行crc16算法,然后得到一个结果,再把这个结果对16384进行求余这个余数会对应[0-16383]其中一个槽,进而决定key-value储存到哪个节点中,所以一旦莫格节点挂了,该节点对应的slot就无法使用,那么就会导致集群无法正常工作
示例(三个节点):
节点A覆盖0-5460;
节点B覆盖5461-10922;
节点C覆盖10923-16383
即每个节点有5460个哈希槽
新增一个节点:
节点A覆盖1365-5460
节点B覆盖6827-10922
节点C覆盖12288-163838
节点D覆盖0-1364,5461-6826,10923-12287
综上所述,每个redis集群理论上最多可以有16384个节点
二、Redis主从复制的概念
1.主从复制概念
通过持久化功能,redis保证了即使在服务器重启的情况下也不会丢失(或少量丢失)数据,因为持久化会把内存中的数据保存到硬盘上,重启会从硬盘上加载数据,但是由于数据是存储在一台服务器上的,如果这台服务器出现硬盘故障等问题,也会导致数据丢失。为了避免单点故障,通常的做法是将数据库复制多个副本以部署在不同的服务器上,这样即使有一台服务器出现故障,其他服务器依然可以继续提供服务,为此,redis提供了复制(replication)功能,可以实现当一台数据库中的数据更新后,自动将更新的数据同步到其他数据库上。
在复制的概念中,数据库分为两类,一类是主数据库(master),另一类是从数据(slave)。主数据可以进行读写操作,当写操作导致数据变化时会自动将数据同步给从数据库,而从数据库一般是只读的,并接受主数据同步过来的数据。一个主数据库可以拥有多个从数据库,而一个从数据库只能拥有一个主数据库
2.Redis主从复制的作用
数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。
3.Redis主从复制的流程
1)若启动一个Slave机器进程,则它会向Master机器发送一个“sync command”命令,请求同步连接。
2)无论是第一次连接还是重新连接,Master机器都会启动一个后台进程,将数据快照保存到数据文件中(执行rdb操作),同时Master还会记录修改数据的所有命令并缓存在数据文件中。
3)后台进程完成缓存操作之后,Maste机器就会向Slave机器发送数据文件,Slave端机器将数据文件保存到硬盘上,然后将其加载到内存中,接着Master机器就会将修改数据的所有操作一并发送给Slave端机器。若Slave出现故障导致宕机,则恢复正常后会自动重新连接。
4)Master机器收到Slave端机器的连接后,将其完整的数据文件发送给Slave端机器,如果Mater同时收到多个Slave发来的同步请求,则Master会在后台启动一个进程以保存数据文件,然后将其发送给所有的Slave端机器,确保所有的Slave端机器都正常。
三、哨兵模式(Sentinel)
1.哨兵模式集群架构
哨兵是redis集群架构中非常重要的一个组件,哨兵的出现主要是解决了主从复制出现故障时需要人为干预的问题。
哨兵模式的结构
1.1哨兵结构由两部分组成,哨兵节点和数据节点:
哨兵节点:哨兵系统由一个或多个哨兵节点组成,哨兵节点是特殊的redis节点,不存储数据。
数据节点:主节点和从节点都是数据节点。
哨兵的启动依赖于主从模式,所以须把主从模式安装好的情况下再去做哨兵模式,所有节点上都需要部署哨兵模式,哨兵模式会监控所有的 Redis 工作节点是否正常,当 Master 出现问题的时候,因为其他节点与主节点失去联系,因此会投票,投票过半就认为这个 Master 的确出现问题,然后会通知哨兵间,然后从 Slaves 中选取一个作为新的 Master。
需要特别注意的是,客观下线是主节点才有的概念;如果从节点和哨兵节点发生故障,被哨兵主观下线后,不会再有后续的客观下线和故障转移操作。
2.哨兵模式的作用
集群监控:负责监控redis master 和 slave进程是否正常工作
消息通知:如果某个redis实例有故障,那么哨兵负责发送消息作为报警通知给管理员
故障转移:如果master node挂掉了,会自动转移到slave node上
配置中心:如果故障转移发生了,通知client客户端的新的master地址
使用一个或者多个哨兵(Sentine)实例组成的系统,对redis节点进行监控,在主节点故障的情况下,能将从节点中的一个升级为主节点,进行故障转移,保证系统的可用性
3.哨兵监控整个系统节点的过程
【1】首先主节点的信息是配置在哨兵的配置文件中
【2】哨兵节点会和配置的主节点建立起两条连接命令连接和订阅连接
PS:redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接受消息
【3】哨兵会通过命令连接每10s发送一次INFO命令,通过INFO命令,主节点会返回自己的run_id 和自己的从节点信息
【4】哨兵会对这些从节点也建立两条连接命令连接和订阅连接
【5】哨兵通过命令连接向从节点发送INFO命令,获取到他的一些信息:
run_id(redis服务器id)
role(职能)
从服务器的复制偏移量 offset
其他
【6】通过命令连接向服务器的 _sentinel:hello 频道发送一条消息,包括自己的ip端口、run_id、配置(后续投票的时候会用到)等
【7】通过订阅连接对服务器的 _sentinel:hello 频道做监听,所以所有的向该频道发送的哨兵消息都能被接收到
【8】解析监听到的消息,进行分析提取,就可以知道还有哪些别的哨兵服务节点也在监听这些主从节点了,更新结构体将这些哨兵节点记录下来
【9】向观察到的其他的哨兵节点建立命令连接-----没有订阅连接
4.主观下线
哨兵节点会每秒一次的频率向建立了命令节点的实例发送ping命令,如果在 down-after-milliseconds 毫秒内没有做出有效响应包括(pong/loading/masterdown)以外的响应,哨兵就会将该实例在本结构体中的状态标记为 sri_s_down 主观下线
5.客观下线
当一个哨兵节点发现主节点处于主观下线状态时,就会向其他的哨兵节点发出询问,该节点是否已经主观下线。如果超过配置参数 quorum 个节点认为是主观下线时,该哨兵节点就会将自己维护的结构体中该主节点标记为 sri_o_down 客观下线
6.master 选举
在认为主节点客观下线的情况下,哨兵节点间会发起一次选举,命令为: SENTINEL is-master-down-by-addr,只是 run_id 这次会将自己的 run_id 带进去,希望接受者将自己设置为主节点。如果超过半数以上的节点返回将该节点标记为 leader 的情况下,会有该 leader 对故障进行迁移
7.故障迁移
【1】在从节点中挑选出新的从节点
通讯正常
优先级排序
优先级相同时选择offset最大的
【2】将该节点设置成新的主节点 slaveof no one ,并确保在后续的 INGO 命令时,该节点返回状态为 master
【3】将其他的从节点设置成从新的主节点服务, slaveof 命令
【4】将旧的主节点变成新的主节点的从节点
8.优点与缺点
【优点】:高可用,哨兵模式是基于主从模式的,所有主从模式的优点,哨兵模式都有;主从可以自动切换,系统更健壮,可用性更高
【缺点】:redis 比较难支持在线扩容,在群集容量达到上限时在线扩容会变得很复杂
四、Cluster群集
1.Cluster集群概念
redis的哨兵模式基本已经可以实现高可用、读写分离,但是在这种模式,每台redis服务器都存储相同的数据,很浪费内存资源,所以加入了 Cluster 群集模式,实现了redis的分布式存储,也就是说,每台redis节点存储着不同的内容
群集部署建议至少3台以上的master节点,建议使用3主3从六个节点的模式
Cluster 群集由多个redis服务器组成的分布式网络服务群集,群集中有多个master主节点,每个主节点都可读可写,节点之间会互相通信,两两相连,redis群集无中心节点
【1】在 redis-Cluster 群集中,可以给每个主节点添加从节点,主节点和从节点直接遵循主从模型的特性,当用户需要处理更多读请求的时候,添加从节点可以扩展系统的读性能
【2】redis-Cluster 的故障转移:redis群集的主节点内置了类似 redis sentinel 的节点故障检测和自动故障转移功能,当群集中的某个主节点下线时,群集中的其他在线主节点会注意到这点,并且对已经下线的主节点进行故障转移
【3】群集进行故障转移的方法和 redis sentinel 进行故障转移的方法基本一样,不同的是,在集群里面,故障转移是由集群中其他在线的主节点复制进行的,所以群集不必另外使用 redis sentinel
五、redis主从复制
主机 | IP地址 | 软件 / 安装包 / 工具 |
---|---|---|
Master | 192.168.22.100 | redis-5.0.7.tar.gz |
Slave1 | 192.168.22.21 | redis-5.0.7.tar.gz |
Slave2 | 192.168.22.22 | redis-5.0.7.tar.gz |
1.修改各服务器redis配置文件
#关闭防火墙和核心防护
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
进行redis的安装(所有主机都需要安装)
yum install -y gcc gcc-c++ make
cd /opt
tar zxvf redis-5.0.7.tar.gz
cd /opt/redis-5.0.7/
make -j 2 && make PREFIX=/usr/local/redis install
cd /opt/redis-5.0.7/utils
./install_server.sh
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/
//Master节点(192.168.22.100):
vim /etc/redis/6379.conf
bind 0.0.0.0 #70行,修改bind 项,0.0.0.0监听所有网段
daemonize yes #137行,开启守护进程
logfile /var/log/redis_6379.log #172行,指定日志文件目录
dir /var/lib/redis/6379 #264行,指定工作目录
appendonly yes #700行,开启AOF持久化功能
/etc/init.d/redis_6379 restart #重启redis服务
//slaves节点(192.168.22.21、192.168.22.22):
vim /etc/redis/6379.conf
bind 0.0.0.0 #70行,修改bind 项,0.0.0.0监听所有网卡
daemonize yes #137行,开启守护进程
logfile /var/log/redis_6379.log #172行,指定日志文件目录
dir /var/lib/redis/6379 #264行,指定工作目录
replicaof 192.168.22.100 6379 #288行,指定要同步的Master节点IP和端口
appendonly yes #700行,开启AOF持久化功能
/etc/init.d/redis_6379 restart
//进行主从复制验证
tail -f /var/log/redis_6379.log #查看master节点日志
redis-cli info replication #master上验证从节点
Master配置(192.168.22.100)
Slave1和Slave2配置(192.168.22.21 192.168.22.22)
主从复制验证
master上设键值
Slave1查看
Slave2查看
六、哨兵模式的搭建
1.环境配置: 主从复制已搭建完成
主机 | 操作系统 | IP地址 | 软件 / 安装包 / 工具 |
---|---|---|---|
Master | CentOS7 | 192.168.22.100 | redis-5.0.7.tar.gz |
Slave1 | CentOS7 | 192.168.22.21 | redis-5.0.7.tar.gz |
Slave2 | CentOS7 | 192.168.22.22 | redis-5.0.7.tar.gz |
2.修改 Redis 配置文件(所有节点操作)
systemctl stop firewalld
setenforce 0
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.22.100 6379 2 #84行,修改 指定该哨兵节点监控192.168.22.100:6379这个主节点,该主节点的名称是mymaster,最后的2的含义与主节点的故障判定有关:至少需要2个哨兵节点同意,才能判定主节点故障并进行故障转移
sentinel down-after-milliseconds mymaster 30000 #113行,判定服务器down掉的时间周期,默认30000毫秒(30秒)
sentinel failover-timeout mymaster 180000 #146行,故障节点的最大超时时间为18000秒
3.启动哨兵模式
先启master,再启slave
cd /opt/redis-5.0.7/
redis-sentinel sentinel.conf &
注意!先启动主服务器,再启动从服务器
4.查看哨兵模式
redis-cli -p 26379 info Sentinel
5.故障模拟
查看redis-server进程号
ps -ef | grep redis
杀死 Master 节点上redis-server的进程号
kill -9 8676 #Master节点上redis-server的进程号
6.验证结果
tail -f /var/log/sentinel.log #查看日志信息
redis-cli -p 26379 INFO Sentinel #查看哨兵信息
七、搭建Redis 群集模式
redis的集群一般需要6个节点,3主3从。方便起见,这里所有节点在同一台服务器
都要安装redis数据库,建议不要在哨兵模式的基础上进行实验
主机 | 操作系统 | IP:端口 | 软件/安装包/工具 |
---|---|---|---|
Master1 | CentOS7 | 192.168.22.100:7001 | redis-5.0.7.tar.gz |
Master2 | CentOS7 | 192.168.22.100:7002 | redis-5.0.7.tar.gz |
Master3 | CentOS7 | 192.168.22.100:7003 | redis-5.0.7.tar.gz |
Slave1 | CentOS7 | 192.168.22.100:7004 | redis-5.0.7.tar.gz |
Slave3 | CentOS7 | 192.168.22.100:7005 | redis-5.0.7.tar.gz |
Slave3 | CentOS7 | 192.168.22.100:7006 | redis-5.0.7.tar.gz |
1、配置安装redis
#关闭防火墙和核心防护
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
进行redis的安装(所有主机都需要安装)
yum install -y gcc gcc-c++ make
cd /opt
tar zxvf redis-5.0.7.tar.gz
cd /opt/redis-5.0.7/
make -j 2 && make PREFIX=/usr/local/redis install
cd /opt/redis-5.0.7/utils
./install_server.sh
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/
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/redic-server /etc/redis/redis-cluster/redis600$i
done
2、开启群集功能:
#其他5个文件夹的配置文件以此类推修改,注意6个端口都要不一样。
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-timeout 15000
#846行,取消注释群集超时时间设置
配置其他5台
cp redis.conf ../redis6002/
cp redis.conf ../redis6003/
cp redis.conf ../redis6004/
cp redis.conf ../redis6005/
cp redis.conf ../redis6006/
修改port
vim /etc/redis/redis-cluster/redis6002/redis.conf
vim /etc/redis/redis-cluster/redis6003/redis.conf
vim /etc/redis/redis-cluster/redis6004/redis.conf
vim /etc/redis/redis-cluster/redis6005/redis.conf
vim /etc/redis/redis-cluster/redis6006/redis.conf
/etc/init.d/redis_6379 stop
3、启动redis节点
分别进入那六个文件夹,执行命令:redis-server redis.conf ,来启动redis节点cd /etc/ redis/redis-cluster/redis6001
redis-server redis.conf
for d in {1..6}
do
cd /etc/redis/redis-cluster/ redis600$d
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表示每个主节点有1个从节点。
5、测试集群
#测试群集
redis-cli -p 6001-c
#力加-c参数,节点之间就可以互相跳转
127.0.0.1:6001>cluster slots
#查看节点的哈希槽编号范围
1)1)(integer)5461
2)(integer) 10922
#哈希槽编号范围
3)1)"127.0.0.1"
2)(integer) 6003
#主节点IP和端口号
3)"fdca661922216dd69a63a7c9d3c4540cd6baef44"
4) 1)"127.0.0.1"
2)(integer)6004
#从节点IP和端口号
3) "a2c0c32aff0f38980accd2b63d6d952812e44740"
2)1)(integer)o
2)(integer)54603)1)"127.0.0.1"2)(integer)6001
3) "Oe5873747a2e26bdc935bc76c2bafb19d0a54b11"4) 1)"127.0.0.1"
2)(integer)6006
3) "8842ef5584a85005e135fd0ee59e5a0d67b0cf8e"
3)1)(integer) 10923
2)(integer) 163833)1)"127.0.0.1"
2)(integer)6002
?)"Q16ddaa?d1 46Q5A∩h>ffhcaafQaa只676A6RA6h?∩"
127.0.0.1:6001> set ky20 zz
127.0.0.1:6001> keys *
127.0.0.1:6001> exit
[root@zz redis6006]# redis-cli -p 6002 -c
127.0.0.1:6002> keys *
127.0.0.1:6002> exit
[root@zz redis6006]# redis-cli -p 6005 -c
127.0.0.1:6005> keys *