Redis集群介绍——主从、哨兵、集群
Redis集群介绍
集群里有三大模式:
Redis主从模式:一主一从或一主多从,自带读写分离,负载均衡;
Redis哨兵模式:高可用,主服务器宕机,从服务器变为主服务器;
Redis集群模式(分片):将数据拆分存储到多个Redis主从集群中。访问任何一台服务器都可以查到所有数据。
Redis主从模式
原理:第一次同步时,使用RDB(快照),在同步时,主服务器产生的数据,会记录偏移量,在同步完成后,进行偏移量的同步。
之后的同步的数据是通过AOF日志方式同步的。
工作机制(了解)
- 当slave启动后,主动向master发送SYNC命令;
- master接受到SYNC命令后在后台保存快照(RDB持久化)和缓存保存快照这段时间的命令;
- 然后将保存的快照文件和缓存的命令发送给slave;
- slave收到快照文件和命令后加载快照文件和缓存的执行命令;
- 复制初始化后,master每次收到的写命令都会同步发送给slave,保证主从数据一致性。
缺点:只有主服务器能写入数据,从服务器只能读,主服务器一旦宕机,导致无法写入数据。
哨兵模式
功能:
- 监控所有Redis服务器,重点监控主服务器,1秒ping一次主,10秒ping一次从;
- 主服务器宕机主观下线,10秒后未恢复,客观下线,选举新的主服务器,根据条件(数据完整性、服务器性能);
- 通知其他从服务器,主从变更,让其他从服务器链接新的主服务器。
多哨兵模式:
·哨兵监控主从的同时,也监控其他哨兵。
·当主宕机,哨兵中选出一个哨兵,这个哨兵再从其他从服务器中选出新的主。
工作机制(了解)
- 每个sentinel以每秒钟一次的频率向它所知的master,slave以及其他sentinel实例发送一个 PING 命令
- 如果一个实例距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被sentinel标记为主观下线。
- 如果一个master被标记为主观下线,则正在监视这个master的所有sentinel要以每秒一次的频率确认master的确进入了主观下线状态
- 当有足够数量的sentinel(大于等于配置文件指定的值)在指定的时间范围内确认master的确进入了主观下线状态, 则master会被标记为客观下线
- 在一般情况下, 每个sentinel会以每 10 秒一次的频率向它已知的所有master,slave发送 INFO 命令
- 当master被sentinel标记为客观下线时,sentinel向下线的master的所有slave发送 INFO 命令的频率会从 10 秒一次改为 1 秒一次
- 若没有足够数量的sentinel同意master已经下线,master的客观下线状态就会被移除;
- 若master重新向sentinel的 PING 命令返回有效回复,master的主观下线状态就会被移除
Redis集群模式
集群=哨兵+主从+分片,实现高扩展性
集群模式特点
多个redis节点网络互联,数据共享
支持在线增加、删除节点
客户端可以连接任何一个主节点进行读写
优点:
- 多个redis节点网络互联,数据共享;
- 所有的节点都是一主一从(也可以是一主多从),其中从不提供服务,仅作为备用;
- 支持在线增加、删除节点;
- 客户端可以连接任何一个主节点进行读写;
缺点:
- 不支持同时处理多个key(如MSET/MGET),因为redis需要把key均匀分布在各个节点上;
- 并发量很高的情况下同时创建key-value会降低性能并导致不可预测的行为。
集群工作方式
哈希槽:默认Redis官方在Redis集群模式中内置了16384个槽
插槽的取值范围是:0-16383。cluster,可以理解为是一个集群管理的插件。
当我们的存取 Key的时候,Redis 会根据算法得出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作。
1 % 16384 = 1
Redis重定向:在Redis集群任意节点查询或存储修改数据时,通过哈希槽运算,未命中节点,则会重新计算查找节点。
集群模式的搭建⭐⭐⭐(单机多实例)
- 第一步:创建一个文件夹redis-cluster,然后在其下面分别创建6个文件夹如下:
[root@localhost ~]# cd /usr/local/redis
[root@localhost redis]# ls
bin data etc logs redis.pid
[root@localhost redis]# mkdir redis-cluster
[root@localhost redis]# cd redis-cluster/
[root@localhost redis-cluster]# mkdir 700{1..6}
[root@localhost redis-cluster]# ls
7001 7002 7003 7004 7005 7006
- 第二步:把之前的redis.conf配置文件分别copy到700*下
# 返回redis目录里
cd ../
[root@localhost redis]# cp ./etc/redis.conf ./redis-cluster/7001/redis.conf
[root@localhost redis]# cp ./etc/redis.conf ./redis-cluster/7002/redis.conf
[root@localhost redis]# cp ./etc/redis.conf ./redis-cluster/7003/redis.conf
[root@localhost redis]# cp ./etc/redis.conf ./redis-cluster/7004/redis.conf
[root@localhost redis]# cp ./etc/redis.conf ./redis-cluster/7005/redis.conf
[root@localhost redis-cluster]# cp ../etc/redis.conf 7006
[root@localhost redis-cluster]# tree
- 第三步:修改集群配置
[root@zuolaoshi redis]# vim ./redis-cluster/7001/redis.conf
以下是全部修改内容:
bind 192.168.221.129
port 7001
pidfile /usr/local/redis/redis-cluster/7001/redis.pid
logfile "/usr/local/redis/logs/redis-7001.log"
dir /usr/local/redis/redis-cluster/7001/
appendonly yes
cluster-enabled yes
cluster-config-file nodes7001.conf
cluster-node-timeout 5000
# 切换到cluster比较方便
[root@localhost redis]# cd redis-cluster/
# 刷新一下7001的配置文件
[root@localhost redis-cluster]# redis-server 7001/redis.conf
# 查看是否开启
[root@localhost redis-cluster]# netstat -lnutp | grep 7001
#会出现
tcp 0 0 192.168.221.129:17001 0.0.0.0:* LISTEN 66164/redis-server
tcp 0 0 192.168.221.129:7001 0.0.0.0:* LISTEN 66164/redis-server
tcp6 0 0 ::1:17001 :::* LISTEN 66164/redis-server
tcp6 0 0 ::1:7001 :::* LISTEN 66164/redis-server
# 把修改好的配置文件覆盖到7002到7006的配置文件上
[root@localhost redis-cluster]# cp 7001/redis.conf 7002/redis.conf
cp:是否覆盖"7002/redis.conf"? y
# 修改每一个配置文件(五个文件都重复这个步骤)
[root@localhost redis-cluster]# vim 7002/redis.conf
:%s/7001/7002/g
[root@localhost redis-cluster]# redis-server 7002/redis.conf
[root@localhost redis-cluster]# netstat -lnutp | grep 7002
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
中途换成Ubuntu,安装了Redis,互传了redis-cluster目录,改了IP,别的都没有变,建议下次直接使用Ubuntu:
scp -r root@192.168.221.10:/usr/local/redis/redis-cluster /usr/local/redis/
先进入/usr/local/redis目录里
cd /usr/local/redis/
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# 安装ruby
apt install ruby Y
gem install redis
# 创建集群
root@cqh-virtual-machine:/usr/local/redis# ./bin/redis-cli --cluster create 192.168.221.129:7001 192.168.221.129:7002 192.168.221.129:7003 192.168.221.129:7004 192.168.221.129:7005 192.168.221.129:7006 --cluster-replicas 1
出现
最后出现绿色OK就成功了
# 查看Redis服务状态
ps -ef | grep redis
# 进入7001端口
root@cqh-virtual-machine:/usr/local/redis# ./bin/redis-cli -c -h 192.168.221.129 -p 7001
192.168.221.129:7001> info cluster
# Cluster
cluster_enabled:1 #节点是否为cluster模式,1是0否
# 测试操作
192.168.221.129:7001> exit
root@cqh-virtual-machine:/usr/local/redis# ./bin/redis-cli -c -h 192.168.221.129 -p 7005
192.168.221.129:7005> set b fdfsfsd
-> Redirected to slot [3300] located at 192.168.221.129:7001
OK
192.168.221.129:7001> get b
"fdfsfsd"
192.168.221.129:7001> set c fdsfdfdsfds
-> Redirected to slot [7365] located at 192.168.221.129:7002
OK
192.168.221.129:7002> get c
"fdsfdfdsfds"
192.168.221.129:7002> set x fdsfdsfsdf
-> Redirected to slot [16287] located at 192.168.221.129:7003
OK
192.168.221.129:7003> keys *
1) "x"
192.168.221.129:7003> get b
-> Redirected to slot [3300] located at 192.168.221.129:7001
"fdfsfsd"
192.168.221.129:7001> keys *
1) "b"
192.168.221.129:7001> set d fdsfdsfsd
-> Redirected to slot [11298] located at 192.168.221.129:7003
OK
192.168.221.129:7003> get d
"fdsfdsfsd"
192.168.221.129:7003> set x zhangsan
OK
192.168.221.129:7003> get x
"zhangsan"
192.168.221.129:7003> exit
实验:一主两从三哨兵⭐⭐⭐
一、安装好Redis
192.168.221.20 Redis(主)
192.168.221.30 Redis(从)
192.168.221.40 Redis(从)
安装Redis
二、多机主从配置一主二从
2.1、准备工作
开启三台虚拟主机20、30、40,分别安装redis
检查防火墙、挂载光盘
systemctl status firewalld
mount /dev/cdrom /media
2.2、配置主机和从机
# 修改配置文件redis.conf
vim /usr/local/redis/etc/redis.conf
主机配置
bind 0.0.0.0 #将bind127.0.0.1注释掉 或者改成 bind 0.0.0.0
port 6379 #改变其服务端口为6379
daemonize yes #修改服务为后台运行
#指定不同的pid文件,注意三份配置文件不同。
pidfile /usr/local/redis/redis.pid
#指定log日志路径,自己配,要求不同。
logfile "/usr/local/redis/logs/redis.log"
#这个指定rdb文件和aof文件的路径配置,要求改成不同。
dir /usr/local/redis/data
# 密码设置
masterauth 123 #从服务到主服务的认证密码(三台都配置)
requirepass 123 #客户端访问需要密码验证(三台都配置)
从机配置
#主服务这句话注释,从服务配置的两台需要开启。配置主服务的ip的port。
replicaof 192.168.221.20 6379
2.3、启动服务
分别启动三台主机的redis服务器端服务
./bin/redis-server ./etc/redis.conf
ps -ef|grep redis
分别启动三台主机客户端服务
./bin/redis-cli
# 查看主从的从属信息
127.0.0.1:6379> info replication
# 如果从服务器没有变成从服务,就手动设置从属
127.0.0.1:6379> slaveof 192.168.221.20 6379
# 关闭从属功能
127.0.0.1:6379> slaveof no one
# 转而对新服务器进行同步
127.0.0.1:6379> slaveof host port(比如:slaveof 192.168.221.30 6379)
三、设置单哨兵(在主服务器上)
# 备份配置文件
[root@localhost /]#cp /usr/local/src/redis-6.2.14/sentinel.conf /usr/local/redis/etc/sentinel.conf
# 进入etc目录
[root@localhost /]#cd /usr/local/redis/etc/
# 排除哨兵配置文件里的注释信息(如果没注释大约在第84行)
[root@localhost etc]#grep -Ev "^$|^#" /usr/local/src/redis-6.2.14/sentinel.conf > /etc/redis/sentinel.conf
# 编辑哨兵配置文件
[root@localhost etc#vim sentinel.conf
++++++++++++++++++++++++++++++++
pidfile "/var/run/redis-sentinel.pid"
logfile "/usr/local/redis/logs/sentinel.log"
dir "/usr/local/redis/data"
sentinel monitor mymaster 192.168.221.20 6379 1 # mymaster是监控主数据的名称,命名时可以使用大小写字母和“.-_”符号;后面是主机IP、端口号和哨兵的数量,少数服从多数的命令
sentinel down-after-milliseconds mymaster 10000
sentinel failover-timeout mymaster 15000
++++++++++++++++++++++++++++++++
# 返回到redis目录里
[root@localhost etc]# cd ../
# 启动哨兵实时查看情况
[root@localhost redis]# ./bin/redis-sentinel ./etc/sentinel.conf 或者 ./bin/redis-server ./etc/sentinel.conf --sentinel
从机宕机
[[root@localhost bin]# cd
[root@localhost ~]# /etc/init.d/redis stop
Stopping Redis...
Redis stopped.
# 哨兵认为主观宕机
[root@localhost ~]# /etc/init.d/redis start
Starting Redis...
Redis started.
# 哨兵取消主观宕机,检测到192.168.221.30重启/恢复上线
# 192.168.221.30重新同步为从节点
主机宕机
[root@localhost redis]# cd
[root@localhost ~]# /etc/init.d/redis stop
Stopping Redis...
Redis stopped.
# 哨兵主观+客观宕机
(达到法定票数,这里quorum 1/1表示1个哨兵同意即可)
# 进入新的 “纪元”(类似选举轮次),保障故障转移流程有序
# 尝试执行故障转移,选主从节点重新挂载
# 哨兵集群选举出“主导哨兵”,由它主导后续故障转移操作
# 把一个从节点选为新的主节点
# 其他从节点重新挂载新的主节点
# 测试哨兵连接
redis-cli -p 26379 sentinel masters
# 通过哨兵获取当前主节点的IP和端口
redis-cli -p 26379 sentinel get-master-addr-by-name mymaster
四、多哨兵连接(一主两从都配置)
# 接单哨兵结尾40变为主节点开始:
# 修改主节点配置文件:
vim /etc/redis/redis.conf
++++++++++++++++++++++++++++++++++++++++++++++++++
bind 0.0.0.0
protected no # 关闭加密保护 否则从节点无法连接
daemonize yes # 开启后台模式将no改为yes
timeout 300 # 连接超时时间
port 6379 # 端口号
logfile "/usr/local/redis/logs/redis.log" # 存放日志
pidfile /usr/local/redis/redis.pid # 定义pid文件
dbfilename dump.rdb
dir /usr/local/redis/data # 用于存放数据(目录需提前创建)
save 3600 1
save 300 100
save 60 10000 # snapshot触发的时机
stop-writes-on-bgsave-error yes # 当snapshot时出现错误无法继续时,阻塞客户端“变更操作”,“错误”可能因为磁盘已满/磁盘故障/OS级别异常等
rdbcompression yes # 启用rdb文件压缩,默认为“yes”,压缩往往意味着“额外的cpu消耗”,同时也意味这较小的文件尺寸以及较短的网络传输时间
appendonly yes # 开启aof功能,只有在“yes”下,aof重写/文件同步等特性才会生效
++++++++++++++++++++++++++++++++++++++++++++++++++
# 修改从节点配置文件:
vim /etc/redis/redis.conf
+++++++++++++++++++++++++++++++++
replicaof 192.168.221.40 6379 ##添加 master IP和端口(注意:老版本的redis是搜索 slaveof 有些许区别)
+++++++++++++++++++++++++++++++++
启动测试
测试
##-->master节点操作
/etc/init.d/redis restart
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> set name jack
OK
127.0.0.1:6379> get name
"jack"
##查看连接状态
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2 ##两个从节点
slave0:ip=192.168.8.12,port=6379,state=online,offset=6535,lag=0
slave1:ip=192.168.8.13,port=6379,state=online,offset=6535,lag=0
##-->从节点操作
/etc/init.d/redis restart
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> get name
"jack"
##查看连接状态
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:192.168.221.40
master_port:6379
master_link_status:up
# 排除哨兵配置文件里的注释信息并把它生成一个新文件(如果不注释,大约在第84行,需要提前备份一个新的配置文件cp /usr/local/src/redis-6.2.14/sentinel.conf /usr/local/redis/sentinel.conf)
[root@localhost ~]#grep -Ev "^$|^#" /usr/local/src/redis-6.2.14/sentinel.conf > /usr/local/redis/sentinel.conf
# 编辑哨兵配置文件
[root@localhost ~]#vim /usr/local/redis/sentinel.conf
++++++++++++++++++++++++++++++++++++++++++++++++++
port 26379
protected-mode no
daemonize yes
pidfile /var/run/redis-sentinel.pid
logfile "/usr/local/redis/logs/sentinel.log"
dir /tmp
sentinel monitor mymaster 192.168.221.40 6379 2
sentinel down-after-milliseconds mymaster 30000
acllog-max-len 128
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes
SENTINEL resolve-hostnames no
SENTINEL announce-hostnames no
++++++++++++++++++++++++++++++++++++++++++++++++++
保存退出
# 将配置文件发送到另外两台服务器
scp /usr/local/redis/sentinel.conf 192.168.221.20:/usr/local/redis/
yes
输入20的密码
scp /usr/local/redis/sentinel.conf 192.168.221.30:/usr/local/redis/
yes
输入30的密码
# 如需查看是否一致,可以在另外两台输入
cat /usr/local/redis/sentinel.conf 一致则说明发送成功
# 启动测试(三台机器均启动)
## 启动哨兵
cd /usr/local/redis/
redis-sentinel sentinel.conf
## 动态查看
tail -f /usr/local/redis/logs/sentinel.log
Ctrl+C退出
##主节点
[root@localhost redis]# redis-cli
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.221.20,port=6379,state=online,offset=547559,lag=0
slave1:ip=192.168.221.30,port=6379,state=online,offset=547559,lag=0
## 停止主节点redis(后面要有耐心,多等待一会儿)
127.0.0.1:6379> exit
[root@redis-master redis]# netstat -tnlp
# 会出现
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:26379 0.0.0.0:* LISTEN 15630/redis-sentine
tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN 14351/redis-server
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 743/rpcbind
tcp 0 0 0.0.0.0:6032 0.0.0.0:* LISTEN 1562/proxysql
tcp 0 0 0.0.0.0:6033 0.0.0.0:* LISTEN 1562/proxysql
tcp 0 0 192.168.122.1:53 0.0.0.0:* LISTEN 1698/dnsmasq
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1116/sshd
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN 1119/cupsd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1622/master
tcp 0 0 127.0.0.1:6010 0.0.0.0:* LISTEN 13696/sshd: root@pt
tcp 0 0 127.0.0.1:6011 0.0.0.0:* LISTEN 15015/sshd: root@pt
tcp6 0 0 :::26379 :::* LISTEN 15630/redis-sentine
tcp6 0 0 ::1:6379 :::* LISTEN 14351/redis-server
tcp6 0 0 :::111 :::* LISTEN 743/rpcbind
tcp6 0 0 :::22 :::* LISTEN 1116/sshd
tcp6 0 0 ::1:631 :::* LISTEN 1119/cupsd
tcp6 0 0 ::1:25 :::* LISTEN 1622/master
tcp6 0 0 ::1:6010 :::* LISTEN 13696/sshd: root@pt
tcp6 0 0 ::1:6011 :::* LISTEN 15015/sshd: root@pt
tcp6 0 0 :::33060 :::* LISTEN 1595/mysqld
tcp6 0 0 :::3306 :::* LISTEN 1595/mysqld
[root@localhost redis]# kill 14351
##--新的主节点机器192.168.221.30(到时候两台都登陆)
127.0.0.1:6379> redis-cli
127.0.0.1:6379> info replication
# 出现下面这个说明正在转换身份
Error: Server closed the connection
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.221.20,port=6379,state=online,offset=738791,lag=1
##已实现故障转移
##--启动故障机器192.168.221.40
[root@localhost redis]# /etc/init.d/redis start
[root@localhost redis]# redis-cli
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:192.168.221.30
master_port:6379
master_link_status:up #恢复的机器会自动加入集群降为从节点