点击上方蓝色字体,选择“设为星标”
回复”资源“获取更多资源![18867d5f7f5e29cb083a6e8ba9340f2d.png](https://i-blog.csdnimg.cn/blog_migrate/17323468989657dabbdbadcf2cf1dee4.jpeg)
![78aeecfd9d9e39d11929eb0690c63f67.png](https://i-blog.csdnimg.cn/blog_migrate/272dd242225a9537d36b943896725e8f.png)
由于单机Redis存储能力受单机限制,以及无法实现读写操作的负载均衡和读写分离,无法保证高可用。本篇就来介绍 Redis 集群搭建方案及实现原理,实现Redis对数据的冗余备份,从而保证数据和服务的高可用。主从复制是哨兵和集群的基石,因此我们循序渐进,由浅入深一层层的将Redis高可用方案抽丝剥茧展示在大家面前。
主从复制
介绍
主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器,主从是哨兵和集群模式能够实施的基础。前者称为主节点(master),后者称为从节点(slave),数据的复制是单向的,只能由主节点到从节点。
默认情况下,每台Redis服务器都是主节点;且一个主节点可以有零个或多个从节点(0+个从节点),但一个从节点只能有一个主节点。一般主节点负责接收写请求,从节点负责接收读请求,从而实现读写分离。
主从一般部署在不同机器上,复制时存在网络延时问题,使用参数repl-disable-tcp-nodelay选择是否关闭TCP_NODELAY,默认为关闭:
关闭:无论数据大小都会及时同步到从节点,占带宽,适用于主从网络好的场景;
开启:主节点每隔指定时间合并数据为TCP包节省带宽,默认为40毫秒同步一次,适用于网络环境复杂或带宽紧张,如跨机房;
数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务,分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
读写分离:主库写、从库读,读写分离不仅可以提高服务器的负载能力,同时可根据需求的变化,改变从库的数量;
高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础。
#在从服务器执行下面的命令成为或取消成为某节点的从节点
#slaveof 主服务器的IP 端口号
slaveof host port
#取消成为任何服务器的从服务器
slaveof no one
#从服务器只读(推荐配置)
config set slave-read-only yes
#查看主从信息
info replication
#配置主节点ACL账号密码(Redis6开启ACL的情况)
config set masteruser username
config set masterauth password
slaveof
命令是异步的,不会阻塞。
同时,从服务器现有的数据会先被清空,然后才会同步主服务器的数据。
配置文件
在从服务器配置文件中添加下面的配置然后重启从服务器即可:#在从节点配置文件中新增下面两个配置即可指定成为某个主节点的从节点
#slaveof 主节点地址 主节点端口
slaveof host port
#从服务器只读(推荐配置)
slave-read-only yes
使用ACL用户同步
上一篇文章中介绍了 Redis6的新特性ACL访问控制列表,基于该特性我们可以为Redis设置不同的用户和权限,在主从复制中我们也可以配置该同步用户的 账号密码:#命令行模式
#在从节点配置主节点ACL账号密码(Redis6开启ACL的情况)
config set masteruser default
config set masterauth wyk123456
#在从节点查看主节点的ACL用户密码
config get master*
#配置文件模式 redis.conf
#在从节点配置主节点ACL账号密码(Redis6开启ACL的情况)
masteruser default
masterauth wyk123456
![ce4042586c173f8c882b670eb27774a3.png](https://i-blog.csdnimg.cn/blog_migrate/d6456ef273a411f196ddb175ec753321.png)
一主一从
最基础的主从复制模型,主节点负责处理写请求,从节点负责处理读请求,主节点使用RDB持久化模式,从节点使用AOF持久化模式:![51e7b581b8d3cc1192182b1f6efe585b.png](https://i-blog.csdnimg.cn/blog_migrate/5e9de6a00133f68d3f51cf3548d4eef1.png)
一主多从
一个主节点可以有多个从节点,但每个从节点只能有一个主节点。一主多从适用于写少读多的场景,多个从节点可以分担读请求负载,提升并发:![c06f54c2b30588cc5507f3124298583d.png](https://i-blog.csdnimg.cn/blog_migrate/f6f83326d86a50f9618f8f6196c68765.png)
树状主从
上面的一主多从可以实现读请求的负载均衡,但当从节点数量多的时候,主节点的同步压力也是线性提升的,因此可以使用树状主从来分担主节点的同步压力:![b628d8cd89893498469539578853c8c3.png](https://i-blog.csdnimg.cn/blog_migrate/b4cfc169068d879d1c7ba898fb05267a.png)
保存主节点信息:配置slaveof之后会在从节点保存主节点的信息。
主从建立socket连接:定时发现主节点以及尝试建立连接。
发送ping命令:从节点定时发送ping给主节点,主节点返回PONG。若主节点没有返回PONG或因阻塞无法响应导致超时,则主从断开,在下次定时任务时会从新ping主节点。
权限验证:若主节点开启了ACL或配置了requirepass参数,则从节点需要配置masteruser和masterauth参数才能保证主从正常连接。
同步数据集:首次连接,全量同步。
命令持续复制:全量同步完成后,保持增量同步。
监控:监控主从节点运行情况。
通知:当监控节点出现故障,哨兵之间进行通讯。
自动故障转移:当监控到主节点宕机后,断开与宕机主节点连接的所有从节点,然后在从节点中选取一个作为主节点,将其他的从节点连接到这个最新的主节点。最后通知客户端最新的服务器地址。
配置文件
在redis源码中找到 sentinel.conf 配置文件,我们把它移动到redis安装目录下然后修改配置,共有下面几个配置: vim /opt/app/redis6/bin/sentinel.conf#端口
port 26379
#后台启动
daemonize yes
#运行时PID文件
pidfile /var/run/redis-sentinel.pid
#日志文件(绝对路径)
logfile "/opt/app/redis6/sentinel.log"
#数据目录
dir /tmp/sentinel_26379
#监控的节点名字可以自定义,后边的2代表的:如果有俩个哨兵判断这个主节点挂了那这个主节点就挂了,通常设置为哨兵个数一半加一
sentinel monitor mymaster 127.0.0.1 6379 2
#哨兵连接主节点多长时间没有响应就代表主节点挂了,单位毫秒。默认30000毫秒,30秒。
sentinel down-after-milliseconds mymaster 30000
#在故障转移时,最多有多少从节点对新的主节点进行同步。这个值越小完成故障转移的时间就越长,这个值越大就意味着越多的从节点因为同步数据而暂时阻塞不可用
sentinel parallel-syncs mymaster 1
#在进行同步的过程中,多长时间完成算有效,单位是毫秒,默认值是180000毫秒,3分钟。
sentinel failover-timeout mymaster 180000
#禁止使用SENTINEL SET设置notification-script和client-reconfig-script
sentinel deny-scripts-reconfig yes
哨兵启动及验证
我这里演示在一台机器上启动3个Redis服务以及3个哨兵服务,其中3个redis服务作一主两从,哨兵监控主节点,然后测试主节点挂了之后哨兵自动选举新的master节点。[实际应用中建议分别部署在不同的机器上]:Redis服务:localhost:6381,localhost:6382,localhost:6383
sentinel服务:localhost:26381,localhost:26382,localhost:26383
6381为Redis初始主节点,6382,6383分别为6381的从节点。
26381,26382,26383作为三个哨兵服务监控上面的Redis主从架构。
配置启动三个Redis服务以及Sentinel 服务:
1.首先复制Redis目录出三个:
cp -r /opt/app/redis6 /opt/app/redis6A
cp -r /opt/app/redis6 /opt/app/redis6B
cp -r /opt/app/redis6 /opt/app/redis6C
2.分别修改A,B,C三个目录中的redis.conf和sentinel.conf文件,主要修改端口和文件路径,下面以A为演示,B,C略过:
vim redis.conf
--------------------------------------------
port 6381
daemonize yes
pidfile "/var/run/redisA_6381.pid"
logfile "/opt/app/redis6A/redis_6381.log" #需要手动touch文件
dir "/opt/app/redis6A/data" #需要手动先mkdir文件夹
--------------------------------------------
vim sentinel.conf
--------------------------------------------
port 26381
daemonize yes
pidfile /var/run/redis-sentinel_26381.pid
logfile "/opt/app/redis6A/sentinel_26381.log" #需要手动先touch文件
dir /tmp/sentinel_26381 #需要手动先mkdir文件夹
sentinel monitor mymaster 127.0.0.1 6381 2 #此参数在ABC三个服务中保持一致,都监听6381端口
--------------------------------------------
创建log文件和目录:
mkdir /opt/app/redis6A/data
mkdir /opt/app/redis6B/data
mkdir /opt/app/redis6C/data
touch /opt/app/redis6A/redis_6381.log
touch /opt/app/redis6B/redis_6382.log
touch /opt/app/redis6C/redis_6383.log
mkdir /tmp/sentinel_26381
mkdir /tmp/sentinel_26382
mkdir /tmp/sentinel_26383
touch /opt/app/redis6A/sentinel_26381.log
touch /opt/app/redis6B/sentinel_26382.log
touch /opt/app/redis6C/sentinel_26383.log
3.配置完成后,分别启动Redis三个服务以及Sentinel三个服务:
#启动Redis
/opt/app/redis6A/bin/redis-server /opt/app/redis6A/bin/redis.conf
/opt/app/redis6B/bin/redis-server /opt/app/redis6B/bin/redis.conf
/opt/app/redis6C/bin/redis-server /opt/app/redis6C/bin/redis.conf
#配置Redis主从,6381为主,6382和6383为从节点
#最后启动Sentinel
/opt/app/redis6A/bin/redis-sentinel /opt/app/redis6A/bin/sentinel.conf
/opt/app/redis6B/bin/redis-sentinel /opt/app/redis6B/bin/sentinel.conf
/opt/app/redis6C/bin/redis-sentinel /opt/app/redis6C/bin/sentinel.conf
使用redis-cli客户端命令行进入6381,6382,6383的Redis服务,然后配置6382和6383作为6381的从节点:
![cbea7f065f6b7dd3f4a4cc9599be70ae.png](https://i-blog.csdnimg.cn/blog_migrate/edfe912f73419ed0f1cc9e59afaffbd2.png)
![c60153368e3ec15c1e5cc9fe5b4d0b42.png](https://i-blog.csdnimg.cn/blog_migrate/c346a203803f55cb6733ddb2321c4c8e.png)
#命令执行一个非法的内存访问从而让 Redis 崩溃,仅在开发时用于 BUG 调试,执行后需要重启服务
debug segfault
然后我们查看哨兵的日志:
vim /opt/app/redis6A/sentinel_26381.log
![58baf2628a714e55e30cacccf51c5d91.png](https://i-blog.csdnimg.cn/blog_migrate/45970589d77255dfe567fbf3d21412a3.png)
![fc4e9babc5e816fcc8c9b8b530065665.png](https://i-blog.csdnimg.cn/blog_migrate/37f3f047d8153877435db3497b1a8be2.png)
![d2f47670aec6076371b2a39113ddeaf4.png](https://i-blog.csdnimg.cn/blog_migrate/3e10aec0cd0247337762f5f649724a04.png)
![17f6e97b7a3dd66a1633b9ba1318dcbd.png](https://i-blog.csdnimg.cn/blog_migrate/2290b63401d49d4e0fac4d1bfa3c10d4.png)
哨兵和哨兵之间以及哨兵和Redis主从节点之间每隔一秒发送ping监控它们的健康状态;
哨兵向Redis主从节点每隔10秒发送一次info保存节点信息;
哨兵向Redis主节点每隔2秒发送一次hello,直到哨兵报出sdown,代表主节点失联,然后通知其余哨兵尝试连接该主节点;
哨兵A发现Redis主节点失联;
哨兵A报出sdown,并通知其他哨兵,发送指令sentinel is-master-down-by-address-port给其余哨兵节点;
其余哨兵接收到哨兵A的指令后尝试连接Redis主节点,发现主节点确实失联;
哨兵返回信息给哨兵A,当超过半数的哨兵认为主节点下线后,状态会变成odown;
最先发现主节点下线的哨兵A会成为哨兵领导者负责这次的主从节点的切换工作;
![0b2c15f3e17849c3564d05f686a64278.png](https://i-blog.csdnimg.cn/blog_migrate/499ac67f0a4097dad65aa847ba303f3f.png)
哨兵Leader 根据一定规则从各个从节点中选择出一个节点升级为主节点;
其余从节点修改对应的主节点为新的主节点;
当原主节点恢复启动的时候,变为新的主节点的从节点
#Java
JedisSentinelPool
#Python
from redis.sentinel import SentinelConnectionPool
集群
介绍
Redis集群(Redis Cluster)是从 Redis 3.0 开始引入的分布式存储方案。集群由多个节点(Node)组成,Redis 的数据分布在这些节点中。
集群中的节点分为主节点和从节点,只有主节点负责读写请求和集群信息的维护,从节点只进行主节点数据和状态信息的复制。
作用
Redis集群的作用有下面几点:
数据分区:突破单机的存储限制,将数据分散到多个不同的节点存储;
负载均衡:每个主节点都可以处理读写请求,提高了并发能力;
高可用:集群有着和哨兵模式类似的故障转移能力,提升集群的稳定性;
![253f2922a06ebf97dcca22cd1f70af77.png](https://i-blog.csdnimg.cn/blog_migrate/8eddaedede260ea3f1ed6f23aaae72a8.png)
![2b2d874e47e8e468730c7c5c656be93b.png](https://i-blog.csdnimg.cn/blog_migrate/ed2acf81727371e0ea6091da2ea02e25.png)
普通端口:即客户端访问端口,如默认的6379;
集群端口:普通端口号加10000,如6379的集群端口为16379,用于集群节点之间的通讯;
MEET:在节点握手阶段,对新加入的节点发送meet消息,请求新节点加入当前集群,新节点收到消息会回复PONG消息;
PING:节点之间互相发送ping消息,收到消息的会回复pong消息。ping消息内容包含本节点和其他节点的状态信息,以此达到状态同步;
PONG:pong消息包含自身的状态数据,在接收到ping或meet消息时会回复pong消息,也会主动向集群广播pong消息;
FAIL:当一个主节点判断另一个主节点进入fail状态时,会向集群广播这个消息,接收到的节点会保存该消息并对该fail节点做状态判断;
PUBLISH:当节点收到publish命令时,会先执行命令,然后向集群广播publish消息,接收到消息的节点也会执行publish命令;
#使用-c进入集群命令行模式
redis-cli -c -p 6381
#使用命令查看key所在的槽
cluster keyslot key1
![4d14ea23d369a470bfcd144f4c62c939.png](https://i-blog.csdnimg.cn/blog_migrate/125ca640aa13513697a8a3da8f76c1ba.png)
![f1265d97a214e45f73073df7268a1193.png](https://i-blog.csdnimg.cn/blog_migrate/5e10bc46381f623a8bfdac9d59d5aa61.png)
cluster slots
![3f4f181fd1c37c05affc2da216a011f7.png](https://i-blog.csdnimg.cn/blog_migrate/f869956ac429c1d835e16039f8aa3860.png)
搭建集群
从Redis5之后我们就可以直接使用redis-cli --cluster命令自动部署Redis集群了,所以本篇也直接使用该方式搭建集群。 这里演示仍然是一台机器上使用三主三从的方式部署Redis集群:![0e516869089702237a10367b677419e1.png](https://i-blog.csdnimg.cn/blog_migrate/e86570e879e5dfa25c2b0fb83268e3c1.png)
1.首先复制Redis目录出三个:
cp -r /opt/app/redis6A /opt/app/redis6AA
cp -r /opt/app/redis6B /opt/app/redis6BB
cp -r /opt/app/redis6C /opt/app/redis6CC
2.分别修改6个目录中的redis.conf文件,主要开启集群以及修改端口和文件路径,下面以A为演示,其余略过:
vim /opt/app/redis6A/bin/redis.conf
--------------------------------------------
port 6381
daemonize yes
pidfile "/var/run/redisA_6381.pid"
logfile "/opt/app/redis6A/redis_6381.log" #需要手动touch文件
dir "/opt/app/redis6A/data" #需要手动先mkdir文件夹
cluster-enabled yes # 启用集群模式
cluster-node-timeout 15000 # 设置当前节点连接超时毫秒数
cluster-config-file node_6381.conf #设置当前节点集群配置文件路径
--------------------------------------------
3.在6个目录下分别创建log文件和目录:
mkdir /opt/app/redis6A/data
touch /opt/app/redis6A/redis_6381.log
cluster-config-file:每个节点在运行过程中,会维护一份集群配置文件。
当集群信息发生变化时(如增减节点),集群内所有节点会将最新信息更新到该配置文件。
节点重启后,会重新读取该配置文件,获取集群信息,可以方便的重新加入到集群中。
也就是说,当 Redis 节点以集群模式启动时,会首先寻找是否有集群配置文件。
如果有则使用文件中的配置启动;如果没有,则初始化配置并将配置保存到文件中。
集群配置文件由 Redis 节点维护,不需要人工修改。
启动部署:部署集群需要
先启动各个节点的服务,此时这些节点都没加到集群中,使用
redis-cli --cluster create xxx命令创建集群:
bin/redis-cli --cluster create 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6391 127.0.0.1:6392 127.0.0.1:6393 --cluster-replicas 1
#这里的--cluster-replicas表示每个主节点有几个副本节点
![d6770e12fce4c1d2369615256c854104.png](https://i-blog.csdnimg.cn/blog_migrate/a648e2ec15727e5ebfdd22cd5ce15943.png)
![6ff530008b6fe747d810b6105f0db9e0.png](https://i-blog.csdnimg.cn/blog_migrate/8ff84e7bda4bab0ac13603493e8594c4.png)
![435deea355ac2b5d7beeb6d083ccb9c5.png](https://i-blog.csdnimg.cn/blog_migrate/54a2540b73153aa6ca1ff659d09d2a3d.png)
文章不错?点个【在看】吧! ?