Redis数据库集群部署
Redis集群
1、简介
Redis集群是一个提供在多个Redis间节点间共享数据的程序集
Redis集群并不支持处理多个keys的命令,因为这需要在不同的节点间移动数据,从而达不到像Redis那样的性能,在高负载的情况下可能会导致不可预料的错误
Redis集群通过分区来提供一定程度的可用性,在实际环境中当某个节点宕机或者不可达的情况下可继续处理命令
2、Redis集群的优势
自动分割数据到不同的节点上
整个集群的部分节点失败戟者不可达的情况下能够继续处理命令
3、Redis集群的实现方法
有客户端分片
代理分片
服务器端分片
Redis三种模式原理介绍
Redis群集有三种模式:
主从同步/复制
哨兵模式
Cluster
主从模式
通过持久化功能,redis保证了即使在服务器重启的情况下也不会丢失(或少量丢失)数据,因为持久化会把内存中的数据保存到硬盘上,重启会从硬盘上加载数据,但是由于数据是存储在一台服务器上的,如果这台服务器出现硬盘故障等问题,也会导致数据丢失。为了避免单点故障,通常的做法是将数据库复制多个副本以部署在不同的服务器上,这样即使有一台服务器出现故障,其他服务器依然可以继续提供服务,为此,redis提供了复制(replication)功能,可以实现当一台数据库中的数据更新后,自动将更新的数据同步到其他数据库上。
在复制的概念中,数据库分为两类,一类是主数据库(master),另一类是从数据(slave)。主数据可以进行读写操作,当写操做导致数据变化时自动把数据同步给从数据库,而从数据库一般是只读的,并接收主数据同步过来的数据。一个主数据库可以拥有多个从数据库,而一个从数据库只能拥有一个主数据库
主从复制流程
redis-主
1、缓存写入操作的命令
2、主redis派生一个子进程,触发RDB持久化,生成RDB快照文件
在触发RDB持久化到完成的过程中,客户端在持续写入,这段数据是保存在内存、缓存,这类的数据,靠AOF进行持久化
3、在ADB持久化完成,生成.rdb文件后,主会将.rdb文件和aof持久化的缓存命令,全部交给redis-从服务
4、在持续的主从同步过程中,客户端会持续进行写入命令操作,命令操作也会由主安按照一定的规则来同步给从服务器
redis-从
rdb文件和缓存的命令
基于以上部分进行加载以达到与master趋于一致的状态
哨兵模式(Sentinel)
哨兵模式集群架构
哨兵是Redis集群架构中非常重要的一个组件,哨兵的出现主要是解决了主从复制出现故障时需要人为干预的问题
哨兵模式主要功能
①:集群监控:负责监控Redis的master和slave进程是否正常工作
②:消息通知:如果某个Redis实例有故障,那么哨兵负责发送消息作为告警通知给管理员
③:故障转移:如果master node(master角色)挂掉了,会自动转移到slave node上
④:配置中心:如果故障转移发生了,通知client客户端新的master地址
使用一个或者多个哨兵(Sentinel)实例组成的系统,对redis节点进行监控在主节点出现故障的情况下,能将从节点中的一个从节点角色升级为主节点,进行故障转义,保证系统的可用性
哨兵们监控整个系统节点的过程
①:哨兵之间相互进行命令连接目的为了在同一频道进行信息共享和监控
②:哨兵们向master发送命令连接和订阅连接(周期性)
③:哨兵10/s向master发送info,iR-M会回应哨兵本节点的信息状态+从节点的位置
④:哨兵收到回复之后,知晓R-S01 R-S02的位置
⑤:然后再向slaves发送命令连接和订阅连接(周期性) ,以达到监控整个集群的目的
哨兵模式下的故障迁移
①:主观下线
哨兵(Sentinel)节点会每秒一次的频率向建立了命令连接的实例发送PING命令,如果在down-after-milliseconds毫秒内没有做出有效响应包括(PONG/ LOADING/MASTERDOWN)以外的响应,哨兵就会将该实例在本结构体中的状态标记为SRI_s_DOWN主观下线
②:客观下线
当一个哨兵节点发现主节点处于主观下线状态是,会向其他的哨兵节点发出询问,该节点是不是已经主观下线了。如果超过配置参数quorum个节点认为是主观下线时,该哨兵节点就会将自己维护的结构体中该主节点标记为SRIO DOWN客观下线询问命令SENTINEL is-master-down-by-addr
③:master选举
在认为主节点客观下线的情况下,哨兵节点节点间会发起一.次选举,命令为:SENTINEL is-master-down-by-addr只是runid这次会将自己的runid带进去, 希望接受者将自己设置为主节点。如果超过半数以.上的节点返回将该节点标记为leacer的情况下,会有该leader对故障进行迁移
⑥:故障转移
在从节点中挑选出新的主节点
通讯正常
优先级排序
优先级相同时选择offset最大的( 最接近master的)
将该节点设置成新的主节点SLAVEOFnoone,并确保在后续的INGO命令时该节点返回状态为master
将其他的从节点设置成从新的主节点的从节点,SLAVEQF命令
将旧的主节点变成新的主节点的从节点
Cluster集群模式
主节点负责读写请求和集群信息的维护,从节点只进行主节点数据和状态信息的复制
作用
数据分区
数据分区( 或称数据分片)是集群最核心的功能( 分布式)
集群将数据分散到多个节点,一方面突破了Redis
单机内存大小的限制,存储容量大大增加,另一方面每个主节点都可以对外提供读服务和写服务,大大提高了集群的响应能力
Redis单机内存大小受限问题,在介绍持久化和主从复制时都有提及
例如,如果单机内存太大,bgsave 和bgrewriteaof的fork操作可能导致主进程阻塞,主从环境下主机切换时可能导致从节点长时间无法提供服务,全量复制阶段主节点的复制缓冲区可能溢出
高可用
集群支持主从复制(模式)和主节点的自动故障转移(与哨兵类似),当任意节点发送故障时,集群仍然可以对外提供服务
数据分片
Redis 集群引入了哈希槽的概念,有16384 个哈希槽(编号0~16383)
集群的每个节点负责一部分哈希槽,每个Key通过CRC16校验后对16384取余来决定放置哪个哈希槽,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存
取操作
以3个节点组成的集群为例:
节点A包含0~5469号的哈希槽
节点B包含5461~10922号的哈希槽
节点C包含10923~16383 号的哈希槽
Redis主从复制部署
设备准备:三台Redis服务器,master(192.168.8.150)、slave1(192.168.8.151)、slave2(192.168.8.152)
三台服务器同步操作
yum install -y gcc gcc-c++ make
ntpdate ntp1.aliyun.com
cd /opt/redis-5.0.7/
make
make prefix=/usr/local/redis install
cd utils/
./install_server.sh
master
[root@master utils]# vim /etc/redis/6379.conf
[root@master utils]# /etc/init.d/redis_6379 restart #重启服务
Stopping ...
Waiting for Redis to shutdown ...
Redis stopped
Starting Redis server...
两台slave同步操作
[root@slave1 utils]# vim /etc/redis/6379.conf #修改配置文件
[root@slave1 ~]# /etc/init.d/redis_6379 restart #重启服务
Stopping ...
Waiting for Redis to shutdown ...
Redis stopped
Starting Redis server...
在master上查看日志文件
[root@master ~]# cat /var/log/redis_6379.log
………………………………
81072:M 08 Aug 2021 23:00:47.259 * Background saving terminated with success
81072:M 08 Aug 2021 23:00:47.259 * Synchronization with replica 192.168.118.50:6379 succeeded
81072:M 08 Aug 2021 23:00:47.259 * Synchronization with replica 192.168.118.200:6379 succeeded
[root@master ~]# redis-cli info replication #验证主从复制效果
#Replication
role:master
connected_slaves:2
##master启动时生成40位16进制的随机字符串,用来标识master节点
slave0:ip=192.168.118.50,port=6379,state=online,offset=546,lag=0
slave1:ip=192.168.118.200,port=6379,state=online,offset=546,lag=1
master_replid:4e5fe691b45ddcbc614fae909211ffa2538dcb54
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:546
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:546
[root@master ~]# redis-cli #进入主节点,设置一个key,然后在从节点查看
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> set lisi www
OK
[root@slave1 ~]# redis-cli
127.0.0.1:6379> keys *
1) "lisi"
Redis哨兵模式部署
三台服务器同时配置
vim /opt/redis-5.0.7/sentinel.conf #修改哨兵配置文件
启动哨兵节点,先启动主节点,再启动两个从节点
[root@master ~]# cd /opt/redis-5.0.7/
[root@master redis-5.0.7]# redis-sentinel sentinel.conf &
[root@master redis-5.0.7]# redis-cli -p 26379 info sentinel #查看哨兵信息
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.118.100:6379,slaves=2,sentinels=3
cluster集群搭建
设备三主三从,这里为了方便我们用一台设备做实验,三主节点:112/113/114 、三从节点:115/116/117
[root@cluster ~]# cd /etc/redis
[root@cluster redis]# mkdir -p redis-cluster/redis11{2..7} #创建redis六个端口的工作目录
[root@cluster redis]# vim /opt/redis.sh #设置启动脚本
#!/bin/bash
for i in {2..7}
do
cp /opt/redis-5.0.7/redis.conf /etc/redis/redis-cluster/redis11$i
cp /opt/redis-5.0.7/src/redis-cli /opt/redis-5.0.7/src/redis-server /etc/redis/redis-cluster/redis11$i
done
[root@cluster redis]# sh -x /opt/redis.sh #执行脚本
修改配置文件
[root@cluster redis]# cd /etc/redis/redis-cluster/redis112 #首先修改节点111的
[root@cluster redis112]# vim redis.conf
将修改的111节点配置文件分别复制到各个节点,然后修改其端口和名称
[root@cluster redis112]# cp redis.conf ../redis117/
cp: overwrite ‘../redis112/redis.conf’? y
[root@cluster redis112]# cp redis.conf ../redis113/
cp: overwrite ‘../redis113/redis.conf’? y
[root@cluster redis112]# cp redis.conf ../redis114/
cp: overwrite ‘../redis114/redis.conf’? y
[root@cluster redis112]# cp redis.conf ../redis115/
cp: overwrite ‘../redis115/redis.conf’? y
[root@cluster redis112]# cp redis.conf ../redis116/
cp: overwrite ‘../redis116/redis.conf’? y
更改端口和文件名称,后面依次类推,保存退出设置启动脚本
[root@cluster redis116]# vim /opt/redis-start.sh
#!/bin/bash
for i in {2..7}
do
cd /etc/redis/redis-cluster/redis11$i
redis-server redis.conf
done
ps -ef | grep redis
[root@cluster redis116]# sh -x /opt/redis-start.sh
root 24540 1 0 21:18 ? 00:00:00 /usr/local/bin/redis-server 127.0.0.1:6379
root 24711 20063 0 21:27 pts/1 00:00:00 sh -x /opt/redis-start.sh
root 24713 1 0 21:27 ? 00:00:00 redis-server 127.0.0.1:112 [cluster]
root 24715 1 0 21:27 ? 00:00:00 redis-server 127.0.0.1:113 [cluster]
root 24720 1 0 21:27 ? 00:00:00 redis-server 127.0.0.1:114 [cluster]
root 24725 1 0 21:27 ? 00:00:00 redis-server 127.0.0.1:115 [cluster]
root 24727 1 0 21:27 ? 00:00:00 redis-server 127.0.0.1:116 [cluster]
root 24738 1 0 21:27 ? 00:00:00 redis-server 127.0.0.1:117 [cluster]
root 24740 24711 0 21:27 pts/1 00:00:00 grep redis
加入集群然后测试
[root@localhost redis117]# redis-cli --cluster create 127.0.0.1:112 127.0.0.1:113 127.0.0.1:114 127.0.0.1:115 127.0.0.1:116 127.0.0.1:117 --cluster-replicas 1
##六个节点,三主三从,每个主对应一个从节点,后面的交互输入yes即可
>>> Performing Cluster Check (using node 127.0.0.1:112)
M: 397888ebf5109561da23e32d00b54d7d1ef2127f 127.0.0.1:112
slots:[0-5460] (5461 slots) master
1 additional replica(s)
M: c9aeec32e6fefd7a6e0465cd81eab676f4eb5709 127.0.0.1:113
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: f1b9dac943f8d003e063cb1b2c56d60b701ac537 127.0.0.1:117
slots: (0 slots) slave
replicates c9aeec32e6fefd7a6e0465cd81eab676f4eb5709
M: 1b9411e364e5273846d9857c08ed867e946b9e37 127.0.0.1:114
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: cf2f2204207bf37ad8b94b7ea18cd562fe6bfa15 127.0.0.1:116
slots: (0 slots) slave
replicates 397888ebf5109561da23e32d00b54d7d1ef2127f
S: 8d7916590a49bd2b2e534e2e543830b51997921d 127.0.0.1:115
slots: (0 slots) slave
replicates 1b9411e364e5273846d9857c08ed867e946b9e37
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
查看各节点对应的哈希槽
[root@localhost redis117]# redis-cli -p 112 -c #进入第一个节点,-c表示节点之间可以切换
127.0.0.1:112> cluster slots #查看各节点对应的哈希槽
1) 1) (integer) 5461
2) (integer) 10922
3) 1) "127.0.0.1"
2) (integer) 113
3) "c9aeec32e6fefd7a6e0465cd81eab676f4eb5709"
4) 1) "127.0.0.1"
2) (integer) 117
3) "f1b9dac943f8d003e063cb1b2c56d60b701ac537"
2) 1) (integer) 0
2) (integer) 5460
3) 1) "127.0.0.1"
2) (integer) 112
3) "397888ebf5109561da23e32d00b54d7d1ef2127f"
4) 1) "127.0.0.1"
2) (integer) 116
3) "cf2f2204207bf37ad8b94b7ea18cd562fe6bfa15"
3) 1) (integer) 10923
2) (integer) 16383
3) 1) "127.0.0.1"
2) (integer) 114
3) "1b9411e364e5273846d9857c08ed867e946b9e37"
4) 1) "127.0.0.1"
2) (integer) 115
3) "8d7916590a49bd2b2e534e2e543830b51997921d"
测试集群
127.0.0.1:112> set name whd #创建一个key键whd,发现他对应哈希槽位5798
-> Redirected to slot [5798] located at 127.0.0.1:113
OK
127.0.0.1:113> cluster keyslot name #查看键的哈希槽,对应发现在113节点中
(integer) 5798