0Redis主从架构的问题
1哨兵服务介绍
2架构图
3主从服务搭建
4配置哨兵服务
5启动哨兵服务
6验证哨兵服务
对于Redis的主从架构而言,无法实现 master 和 slave 角色的自动切换, 即当 master 出现 redis 服务异常、主机断电、磁盘损坏等问题导致 master 无法使用,而 redis 高可用无法实现自故障转移(将 slave 提升为 master),需要手动改环境配置才能切换到 slave redis 服务器。另外无法横向扩展 Redis 服务的并行写入性能, 当单台 Redis 服务器性能无法满足业务写入需求的时候就必须需要一种方式解决此问题。
1master和slave角色的无缝切换,让业务无感知从而不影响业务使用
2可以横向动态扩展Redis服务器, 从而实现多台服务器并行写入以实现更高并发的目的。
Sentinel进程是用于监控redis集群中Master主服务器工作的状态,在Master主服务器发生故障的时候,可以实现Master和Slave服务器的切换,保证系统的高可用,其已经被集成在 redis26+的版本中,Redis的哨兵模式到了28版本之后就稳定了下来。一般在生产环境也建议使用Redis28以后版本。哨兵(Sentinel)是一个分布式系统,你可以在一个架构中运行多个哨兵(sentinel) 进程,这些进程使用流言协议(gossipprotocols)来接收关于Master主服务器是否下线的信息,并使用投票协议(Agreement Protocols)来决定是否执行自动故障迁移,以及选择哪个 Slave 作为新的 Master。每个哨兵(Sentinel)进程会向其它哨兵(Sentinel)、Master、Slave定时发送消息,以确认对方是否”活”着,如果发现对方在指定配置时间(可配置的)内未得到回应,则暂时认为对方已掉线,也就是所谓的”主观认为宕机” ,英文名称:Subjective Down,简称SDOWN。有主观宕机,肯定就有客观宕机。当“哨兵群”中的多数 Sentinel 进程在对 Master 主服务器做出 SDOWN 的判断,并且通过SENTINEL is-master-down-by-addr 命令互相交流之后,得出的Master Server下线判断,这种方式就是“客观宕机”,英文名称是: Objectively Down, 简称 ODOWN。通过一定的 vote 算法,从剩下的 slave 从服务器节点中,选一台提升为 Master 服务器节点,然后自动修改相关配置,并开启故障转移(failover)。Sentinel 机制可以解决 master 和 slave 角色的切换问题。
安装
修改配置文件
启动服务
192168177139
192168177140
其他地方配置和主服务器一致
启动服务
查看主从状态
MASTER
SLAVE1
SLAVE2
MASTER
SLAVE1
SLAVE2
主服务器
SLAVE1:升级为主服务器
SLAVE2:主服务器变为node10
主服务器
从服务器
在redis主从架构中,Master节点负责处理写请求,Slave节点只处理读请求。对于写请求少,读请求多的场景,例如电商详情页,通过这种读写分离的 *** 作可以大幅提高并发量,通过增加redis从节点的数量可以使得redis的QPS达到10W+。Master节点接收到写请求并处理后,需要告知Slave节点数据发生了改变,保持主从节点数据一致的行为称为主从同步,所有的Slave都和Master通信去同步数据也会加大Master节点的负担,实际上,除了主从同步,redis也可以从从同步,我们在这里统一描述为主从同步。
redis 同步的是指令流,主节点会将那些对自己的状态产生修改性影响的指令记录在本地的内存 buffer 中,然后异步将 buffer 中的指令同步到从节点,从节点一边执行同步的指令流来达到和主节点一样的状态,一边向主节点反馈自己同步到哪里了 (偏移量,这是redis-28之后才有的特性)。从节点同步数据的时候不会影响主节点的正常工作,也不会影响自己对外提供读服务的功能,从节点会用旧的数据来提供服务,当同步完成后,需要删除旧数据集,加载新数据,这个时候才会暂停对外服务。
因为内存的 buffer 是有限的,所以 redis 主节点不能将所有的指令都记录在内存 buffer 中。redis 的复制内存 buffer 是一个定长的环形数组,如果数组内容满
了,就会从头开始覆盖前面的内容。
如果节点间网络通信不好,那么当从节点同步的速度不如主节点接收新写请求的速度时,buffer 中会丢失一部分指令,从节点中的数据将与主节点中的数据不一致,此时将会触发快照同步。
快照同步是一个非常耗费资源的 *** 作,它首先需要在主节点上进行一次 bgsave 将当前内存的数据全部快照到RDB文件中,然后再将快照文件的内容全部传送到从节点。从节点将RDB文件接受完毕后,立即执行一次全量加载,加载之前先要将当前内存的数据清空。加载完毕后通知主节点继续进行增量同步。
在整个快照同步进行的过程中,主节点的复制 buffer 还在不停的往前移动,如果快照同步的时间过长或者复制 buffer 太小,都会导致同步期间的增量指令在复制 buffer 中被覆盖,这样就会导致快照同步完成后无法进行增量复制,然后会再次发起快照同步,如此极有可能会陷入快照同步的死循环。所以需要配置一个合适的复制 buffer 大小参数,避免快照复制的死循环。
主节点在进行快照同步时,会进行大量的文件 IO *** 作,特别是对于非 SSD 磁盘存储时,快照会对系统的负载产生较大影响。特别是当系统正在进行 AOF 的 fsync *** 作时如果发生快照复制,fsync 将会被推迟执行,这就会严重影响主节点的服务效率。
从 Redis 2818 版开始支持无盘复制。所谓无盘复制是主节点会一边遍历内存,一遍将序列化的内容发送到从节点,而不是生成完整的 RDB 文件后才进行 IO 传输从节点还是跟之前一样,先将接收到的内容存储到磁盘文件中,再进行一次性加载。
(1) 在从节点的配置文件中的 slaveof 配置项中配置了主节点的IP和port后,从节点就知道自己要和那个主节点进行连接了。
(2) 从节点内部有个定时任务,会每秒检查自己要连接的主节点是否上线,如果发现了主节点上线,就跟主节点进行网络连接。注意,此时仅仅是取得连接,还没有进行主从数据同步。
(3) 从节点发送ping命令给主节点进行连接,如果设置了口令认证(主节点设置了requirepass),那么从节点必须发送正确的口令(masterauth)进行认证。
(4) 主从节点连接成功后,主从节点进行一次快照同步。事实上,是否进行快照同步需要判断主节点的 run id ,当从节点发现已经连接过某个 run id 的主节点,那么视此次连接为重新连接,就不会进行快照同步。相同IP和port的主节点每次重启服务都会生成一个新的 run id ,所以每次主节点重启服务都会进行一次快照同步,如果想重启主节点服务而不改变 run id ,使用 redis-cli debug reload 命令。
(5) 当开始进行快照同步后,主节点在本地生成一份rdb快照文件,并将这个rdb文件发送给从节点,如果复制时间超过60秒(配置项:repl-timeout),那么就会认为复制失败,如果数据量比较大,要适当调大这个参数的值。主从节点进行快照同步的时候,主节点会把接收到的新请求命令写在缓存 buffer 中,当快照同步完成后,再把 buffer 中的指令增量同步到从节点。如果在快照同步期间,内存缓冲区大小超过256MB,或者超过64MB的状态持续时间超过60s(配置项: client-output-buffer-limit slave 256MB 64MB 60 ),那么也会认为快照同步失败。
(6) 从节点接收到RDB文件之后,清空自己的旧数据,然后重新加载RDB到自己的内存中,在这个过程中基于旧的数据对外提供服务。如果主节点开启了AOF,那么在快照同步结束后会立即执行BGREWRITEAOF,重写AOF文件。
(7) 主节点维护了一个backlog文件,默认是1MB大小,主节点向从节点发送全量数据(RDB文件)时,也会同步往backlog中写,这样当发送全量数据这个过程意外中断后,从backlog文件中可以得知数据有哪些是发送成功了,哪些还没有发送,然后当主从节点再次连接后,从失败的地方开始增量同步。这里需要注意的是,当快照同步连接中断后,主从节点再次连接并非是第一次连接,所以进行增量同步,而不是继续进行快照同步。
(8) 快照同步完成后,主节点后续接收到写请求导致数据变化后,将和从节点进行增量同步,遇到 buffer 溢出则再触发快照同步。
(9) 主从节点都会维护一个offset,随着主节点的数据变化以及主从同步的进行,主从节点会不断累加自己维护的offset,从节点每秒都会上报自己的offset给主节点,主节点也会保存每个从节点的offset,这样主从节点就能知道互相之间的数据一致性情况。从节点发送 psync runid offset 命令给主节点从而开始主从同步,主节点会根据自身的情况返回响应信息,可能是FULLRESYNC runid offset触发全量复制,也可能是CONTINUE触发增量复制。
(10) 主从节点因为网络原因导致断开,当网络接通后,不需要手工干预,可以自动重新连接。
(11) 主节点如果发现有多个从节点连接,在快照同步过程中仅仅会生成一个RDB文件,用一份数据服务所有从节点进行快照同步。
(12) 从节点不会处理过期key,当主节点处理了一个过期key,会模拟一条del命令发送给从节点。
(13) 主从节点会保持心跳来检测对方是否在线,主节点默认每隔10秒发送一次heartbeat,从节点默认每隔1秒发送一个heartbeat。
(14) 建议在主节点使用AOF+RDB的持久化方式,并且在主节点定期备份RDB文件,而从节点不要开启AOF机制,原因有两个,一是从节点AOF会降低性能,二是如果主节点数据丢失,主节点数据同步给从节点后,从节点收到了空的数据,如果开启了AOF,会生成空的AOF文件,基于AOF恢复数据后,全部数据就都丢失了,而如果不开启AOF机制,从节点启动后,基于自身的RDB文件恢复数据,这样不至于丢失全部数据。RDB和AOF机制可以参考 详解 redis-4x 持久化机制
使用3个虚拟机搭建一主二从的redis主从架构集群。首先参考 redis-4012单节点安装 在每台机器上安装redis,然后修改redis配置文件,其中一个master节点的配置如下(未列出的保持默认即可):
两个slave节点的配置如下:
启动3个redis服务:
查看master日志:
看日志发现一个问题,我们在原理中介绍说:
主节点如果发现有多个从节点连接,在快照同步过程中仅仅会生成一个RDB文件,用一份数据服务所有从节点进行快照同步。
然而这里master的日志显示写了两次RDB文件,这里我查一些资料再来更新。(!!!待完善)
查看slave日志(这里只列出一个slave的日志):
测试主从架构:
(1) 使用 redis-cli 访问3个redis服务
(2) 在 master 节点上 set 一个数据
(3) 从节点上获取数据
(4) 尝试在slave上写入数据
redis主从架构搭建成功!
wait 提供两个参数,第一个参数是从节点的数量 m,第二个参数是时间 t,以毫秒
为单位。它表示等待 wait 指令之前的所有写 *** 作同步到 n 个子节点 (也就是确保
m 个子节点的同步没有滞后),最多等待时间 t。如果时间 t=0,表示无限等待直到
N 个从库同步完成达成一致。
假设此时某个子节点与主节点网络断开,wait 指令第二个参数时间 t = 0,主从同步无法继续
进行,wait 指令会永远阻塞,redis 服务器将丧失可用性。redis在 60 版本之后更新了一些重要的新特性
60之前的redis 基本上 是一个单线程的,但并不是指只有一个线程,比如说执行 unlink *** 作删除大key的时候( unlink 和 del 命令一样都是用来删除key,但是 unlink 是异步的,适合删除大的key),会有单独的线程完成,不然会阻塞主线程,还有慢的IO *** 作的时候,也会使用单独的线程完成,还有比如持久化的时候,也是会有单独的线程来实现
60之后增加了多线程的实现,多线程使用在io的 *** 作上,工作线程还是只有一个单线程,还是串行实现的,多的io线程用于 读read 或者 写write ,
多线程不会同时执行读写 *** 作。所有多出的线程要不是全部用于 读 ,要不全部都是用于 写 。
多线程的配置默认情况下是关闭的,需要通过配置开启
如果本地没有实现 JVM 缓存,那么在大并发的情况下对redis服务器也是一种考验,所以redis提出一种客户端缓存方案
主要实现过程如下图
可以根据命令和key来控制访问连接
在redis6之前,只能通过密码来控制,还有通过 rename 来调整高危命令 flushdb , keys , shutdown 等命令的权限。
redis6之后,提供了更细粒度的权限控制
通过增加设置,在传输的时候使用 SSL 协议,确保传输过程的安全性
当 SSL 模块开启的时候,不能使用多线程
增加 RESP3 同行协议,优化服务端和客户端之间的通信
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)