深入了解redis集群方案(主从模式、哨兵模式、Redis Cluster模式)
本篇文章给大家带来了关于redis的相关知识,其中主要介绍了主从模式、哨兵模式以及redis cluster模式的相关问题,希望对大家有帮助。

推荐学习:Redis教程
redis 集群方案的介绍(主从模式、哨兵模式、Redis Cluster模式)
一、主从模式
将数据完全存储在单个redis中主要存在两个问题:
数据备份和数据体量较大造成的性能降低。
Redis的主从模式为这两个问题提供了一个较好的解决方案。主从模式指的是使用一个redis实例作为主机,其余的实例作为备份机。
主机和从机的数据完全一致,主机支持数据的写入和读取等各项操作,而从机则只支持与主机数据的同步和读取,也就是说,客户端可以将数据写入到主机,由主机自动将数据的写入操作同步到从机。
主从模式很好的解决了数据备份问题,并且由于主从服务数据几乎是一致的,因而可以将写入数据的命令发送给主机执行,而读取数据的命令发送给不同的从机执行,从而达到读写分离的目的。
实现主从复制(Master-Sl*e Replication)的工作原理:
Sl*e从节点服务启动并连接到Master之后,它将主动发送一个SYNC命令。Master服务主节点收到同步命令后将启动后台存盘进程,同时收集所有接收到的用于修改数据集的命令,在后台进程执行完毕后,Master将传送整个数据库文件到Sl*e,以完成一次完全同步。而Sl*e从节点服务在接收到数据库文件数据之后将其存盘并加载到内存中。此后,Master主节点继续将所有已经收集到的修改命令,和新的修改命令依次传送给Sl*es,Sl*e将在本次执行这些数据修改命令,从而达到最终的数据同步。
如果Master和Sl*e之间的链接出现断连现象,Sl*e可以自动重连Master,在连接成功之后,一次完全同步将被自动执行。
部署:
redis version:6.0.9
1.分别复制4份Redis配置文件
命名为 master.conf sl*e1.conf sl*e2.conf sl*e3.conf
2.对4份配置文件进行简单配置
Master节点的配置文件一般不需要特殊设置 port默认为6379
Sl*e1 节点 port设置 6380 再配置一行 replicaof 127.0.0.1 6379
Sl*e2 节点 port设置 6381 再配置一行 replicaof 127.0.0.1 6379
Sl*e3 节点 port设置 6382 再配置一行 replicaof 127.0.0.1 6379
3.分别开启 Master节点和3个Sl*e节点
redis-server master.conf
redis-server sl*e1.conf
redis-server sl*e2.conf
redis-server sl*e3.conf
4.验证集群主从状态


主从模式的优缺点:
1、优点:
同一个Master可以同步多个Sl*es。
master能自动将数据同步到sl*e,可以进行读写分离,分担master的读压力
master、sl*e之间的同步是以非阻塞的方式进行的,同步期间,客户端仍然可以提交查询或更新请求
2、缺点:
不具备自动容错与恢复功能,master或sl*e的宕机都可能导致客户端请求失败,需要等待机器重启或手动切换客户端IP才能恢复
master宕机,如果宕机前数据没有同步完,则切换IP后会存在数据不一致的问题
难以支持在线扩容,Redis的容量受限于单机配置
其实redis的主从模式很简单,在实际的生产环境中很少使用,不建议在实际的生产环境中使用主从模式来提供系统的高可用性,之所以不建议使用都是由它的缺点造成的,在数据量非常大的情况,或者对系统的高可用性要求很高的情况下,主从模式也是不稳定的。虽然这个模式很简单,但是这个模式是其他模式的基础,所以理解了这个模式,对其他模式的学习会很有帮助。
二、哨兵模式(Sentinel)
哨兵顾名思义,就是来为Redis集群站哨的,一旦发现问题能做出相应的应对处理。其功能包括
监控master、sl*e是否正常运行
当master出现故障时,能自动将一个sl*e转换为master(大哥挂了,选一个小弟上位)
多个哨兵可以监控同一个Redis,哨兵之间也会自动监控
当自动发现sl*e和其他哨兵节点后,哨兵就可以通过定期发送PING命令定时监控这些数据库和节点有没有停止服务。
如果被PING的数据库或者节点超时(通过 sentinel down-after-milliseconds master-name milliseconds 配置)未回复,哨兵认为其主观下线(sdown,s就是Subjectively —— 主观地)。如果下线的是master,哨兵会向其它哨兵发送命令询问它们是否也认为该master主观下线,如果达到一定数目(即配置文件中的quorum)投票,哨兵会认为该master已经客观下线(odown,o就是Objectively —— 客观地),并选举领头的哨兵节点对主从系统发起故障恢复。若没有足够的sentinel进程同意master下线,master的客观下线状态会被移除,若master重新向sentinel进程发送的PING命令返回有效回复,master的主观下线状态就会被移除。
哨兵认为master客观下线后,故障恢复的操作需要由选举的领头哨兵来执行,
选出领头哨兵后,领头者开始对系统进行故障恢复,从出现故障的master的从数据库中挑选一个来当选新的master,
挑选出需要继任的sl*e后,领头哨兵向该数据库发送命令使其升格为master,然后再向其他sl*e发送命令接受新的master,最后更新数据。将已经停止的旧的master更新为新的master的从数据库,使其恢复服务后以sl*e的身份继续运行。
哨兵模式基于前面的主从复制模式。哨兵的配置文件为sentinel.conf,在相应目录中添加以下配置,注意端口不要冲突:
port 26379 protected-mode no daemonize yes pidfile "/var/run/redis-sentinel-26379.pid" logfile "/data/redis/logs/sentinel_26379.log" dir "/data/redis/6379" sentinel monitor mymaster 127.0.0.1 6379 2 ##指定主机IP地址和端口,并且指定当有2台哨兵认为主机挂了,则对主机进行容灾切换 #sentinel auth-pass mymaster pwdtest@2019 ##当在Redis实例中开启了requirepass,这里就需要提供密码 sentinel down-after-milliseconds mymaster 3000 ##这里设置了主机多少秒无响应,则认为挂了 sentinel failover-timeout mymaster 180000 ##故障转移的超时时间,这里设置为三分钟
格式如下:

查看哨兵状态:
三、redis 集群模式(Cluster)

Cluster采用无中心结构,它的特点如下:
客户端与redis节点直连,客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可
Cluster模式的具体工作机制:
在Redis的每个节点上,都有一个插槽(slot),取值范围为0-16383 ,一共16384个槽
当我们存取key的时候,Redis会根据CRC16的算法得出一个结果,然后把结果对16384求余数,这样每个key都会对应一个编号在0-16383之间的哈希槽,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作。
为了保证高可用,Cluster模式也引入主从复制模式,一个主节点对应一个或者多个从节点,当主节点宕机的时候,就会启用从节点。
当其它主节点ping一个主节点A时,如果半数以上的主节点与A通信超时,那么认为主节点A宕机了。如果主节点A和它的从节点都宕机了,那么该集群就无法再提供服务了。
Redis集群,要保证16384个槽对应的node都正常工作,如果某个node发生故障,那它负责的slots也就失效,整个集群将不能工作。
为了增加集群的可访问性,官方推荐的方案是将node配置成主从结构,即一个master主节点,挂n个sl*e从节点。这时,如果主节点失效,Redis Cluster会根据选举算法从sl*e节点中选择一个上升为主节点,整个集群继续对外提供服务,Redis Cluster本身提供了故障转移容错的能力。
Cluster模式集群节点最小配置6个节点(根据cluster的选举机制和主从备份的实现,redis要求至少三主三从共6个节点才能组成redis集群,因为至少需要半数以上才能确定某个节点是否宕机且需要主从备份),其中主节点提供读写操作,从节点作为备用节点,不提供请求,只作为故障转移使用。
cluster集群部署
根据cluster的选举机制和主从备份的实现,redis要求至少三主三从共6个节点才能组成redis集群,测试环境可一台物理机器上启动6个redis节点,但生产环境至少要准备2~3台物理机。(这里使用三台虚拟机)
Cluster模式是建立在Sentinel模式的基础上的,当数据多到需要动态扩容的时候,前面两种就不行了,需要对数据进行分片,根据一定的规则把redis数据分配到多台机器。
该模式就支持动态扩容,可以在线增加或删除节点,而且客户端可以连接任何一个主节点进行读写,不过此时的从节点仅仅只是备份的作用。至于为何能做到动态扩容,主要是因为Redis集群没有使用一致性hash,而是使用的哈希槽。Redis集群会有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽,而集群的每个节点负责一部分hash槽。
那么这样就很容易添加或者删除节点, 比如如果我想新添加个新节点, 我只需要从已有的节点中的部分槽到过来;如果我想移除某个节点,就只需要将该节点的槽移到其它节点上,然后将没有任何槽的A节点从集群中移除即可。由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态。
需要注意的是,该模式下不支持同时处理多个key(如MSET/MGET),因为redis需要把key均匀分布在各个节点上,并发量很高的情况下同时创建key-value会降低性能并导致不可预测的行为。
搭建集群
这里就直接搭建较为复杂的Cluster模式集群,也是企业级开发过程中使用最多的。
1.建redis各节点目录
最终目录结构如下
2.逐个修改redis配置
以 9001 的为例子,其余五个类似。
Quicktools Background Remover
Picsart推出的图片背景移除工具
31
查看详情
编辑 /data/redis-cluster/9001/redis.conf
redis.conf修改如下:
port 9001(每个节点的端口号) daemonize yes appendonly yes //开启aof bind 0.0.0.0(绑定当前机器 IP) dir "/data/redis-cluster/9001"(数据文件存放位置,,自己加到最后一行 快捷键 shift+g) pidfile /var/run/redis_9001.pid(pid 9001和port要对应) logfile "/data/redis-cluster/logs/9001.log" cluster-enabled yes(启动集群模式) cluster-config-file nodes9001.conf(9001和port要对应) cluster-node-timeout 15000
3.逐个启动redis节点
/data/redis-cluster/bin/redis-server /data/redis-cluster/9001/redis.conf
/data/redis-cluster/bin/redis-server /data/redis-cluster/9002/redis.conf
/data/redis-cluster/bin/redis-server /data/redis-cluster/9003/redis.conf
/data/redis-cluster/bin/redis-server /data/redis-cluster/9004/redis.conf
/data/redis-cluster/bin/redis-server /data/redis-cluster/9005/redis.conf
/data/redis-cluster/bin/redis-server /data/redis-cluster/9006/redis.conf
现在检查一下是否成功开启,如下图所示,都开启成功。
ps -el | grep redis

4.集群配置
此时的节点虽然都启动成功了,但他们还不在一个集群里面,不能互相发现,测试会报错:(error) CLUSTERDOWN Hash slot not served。
如下图所示

redis-cli --cluster create 10.32.176.80:9001 10.32.176.80:9002 10.32.176.80:9003 10.32.176.80:9004 10.32.176.80:9005 10.32.176.80:9006 --cluster-replicas 1
–cluster-replicas 1 这个指的是从机的数量,表示我们希望为集群中的每个主节点创建一个从节点。
红色选框是给三个主节点分配的共16384个槽点。
黄色选框是主从节点的分配情况。
蓝色选框是各个节点的详情。

5.测试
现在通过客户端命令连接上,通过集群命令看一下状态和节点信息等
/data/redis-cluster/bin/redis-cli -c -h 10.32.176.80 -p 9001 cluster info cluster nodes
效果图如下,集群搭建成功。

现在往9001这个主节点写入一条信息,我们可以在9002这个主节点取到信息,集群间各个节点可以通信。
6.故障转移
故障转移机制详解
集群中的节点会向其它节点发送PING消息(该PING消息会带着当前集群和节点的信息),如果在规定时间内,没有收到对应的PONG消息,就把此节点标记为疑似下线。当被分配了slot槽位的主节点中有超过一半的节点都认为此节点疑似下线(就是其它节点以更高的频次,更频繁的与该节点PING-PONG),那么该节点就真的下线。其它节点收到某节点已经下线的广播后,把自己内部的集群维护信息也修改为该节点已事实下线。
节点资格审查:然后对从节点进行资格审查,每个从节点检查最后与主节点的断线时间,如果该值超过配置文件的设置,那么取消该从节点的资格。准备选举时间:这里使用了延迟触发机制,主要是给那些延迟低的更高的优先级,延迟低的让它提前参与被选举,延迟高的让它靠后参与被选举。(延迟的高低是依据之前与主节点的最后断线时间确定的)
选举投票:当从节点获取选举资格后,会向其他带有slot槽位的主节点发起选举请求,由它们进行投票,优先级越高的从节点就越有可能成为主节点,当从节点获取的票数到达一定数值时(如集群内有N个主节点,那么只要有一个从节点获得了N/2+1的选票即认为胜出),就会替换成为主节点。
替换主节点:被选举出来的从节点会执行sl*eof no one把自己的状态从sl*e变成master,然后执行clusterDelSlot操作撤销故障主节点负责的槽,并执行 clusterAddSlot把这些槽分配给自己,之后向集群广播自己的pong消息,通知集群内所有的节点,当前从节点已变为主节点。
接管相关操作:新的主节点接管了之前故障的主节点的槽信息,接收和处理与自己槽位相关的命令请求。
故障转移测试
这是之前集群中具体节点的情况,我简化成如下,可以向上回看图片中的集群信息。

这里关闭该9001端口的进程,即模拟该主节点挂掉。
登录挂掉的redis节点,会被拒绝服务,通过还在正常运行的某个主节点进入,然后再次查看集群中的信息

简而言之,就是之前的集群信息变成了如下所示


现在,我重启刚才挂掉的主节点,重新查看集群内部的节点情况,具体情况如下图所示

简而言之,现在集群内的节点情况如下

推荐学习:Redis教程
以上就是深入了解redis集群方案(主从模式、哨兵模式、Redis Cluster模式)的详细内容,更多请关注其它相关文章!
