• Redis的集群方案


    Redis的集群方案总共有3种:

    1.主从同步

    2.哨兵模式

    3.分片集群

    一.Redis的主从同步

    单节点Redis的并发能力是有限的,要进一步提高Redis的并发能力,就需要搭建主从集群,实现读写分离,一般都是一主多从,主节点负责写数据,从节点负责读数据

    主从同步的方式:

    1.全量同步:

    第一步从节点执行replicaof命令建立,请求主节点数据同步,然后主节点判断是否是第一次同步,如果是第一次,则返回master的数据版本信息,然后从节点保存版本信息,然后主节点执行bgsava,生成RDB,然后发送RDB文件,从节点清空本地数据,加载RDB文件,然后从节点清空本地数据,加载RDB文件,这时候是不是就完成了主从同步呢?其实这里还是有问题的,如果主节点再进行主从同步的时候又有数据进行了修改,那这部分数据并没有同步到从节点,为了解决这个问题,引入了repl_baklog它会记录RDB期间的所有命令,然后发送repl_backlog中的命令,然后从节点执行接收到的命令。

    这里还有两个问题:

    (1)如何判断数据是否是第一次同步

    主节点有一个replid,从节点有一个replid,当进行数据同步的时候,如果这两个节点的replid不同,那么就是第一次数据同步,第一次数据同步完后,主节点会把自己的replid发送给一份给从节点,

    当进行第二次同步数据的时候,两个replid值就一样了,然后再进行数据同步的时候,就不会执行bgsave,生成RDB文件了,而是直接通过repl_baklog

    (2)当进行第二次数据或者更多次数据同步的时候,如何判断应该同步那一部分新修改的数据?

    我们先来介绍一个概念:offset  偏移量,随着记录在repl_baklog中的数据增多而逐渐增大,slave完成同步时也会记录在当前同步的offset,如果slave的offset小于master的offset,说明slave的数据落后于master,需要更新

    举个例子再进行第一次数据同步的时候,假设主节点的offset为50,在数据同步的时候,主节点又有新的数据修改,第一次数据同步结束,从节点offset为50,但主节点offset为80.那么就会把多余的30数据进行同步

    2.增量同步:

    二.哨兵模式:

    1.含义:

    哨兵模式专注于对 Redis 实例(主节点、从节点)运行状态的监控,并能够在主节点发生故障时通过一系列的机制实现选主及主从切换,实现故障自动转移和恢复,确保整个 Redis 系统的可用性

     

    Sentinel基于心跳的机制监测服务状态,每隔1秒向集群中的每个实例发送ping命令

    (1)主观下线:如果某sentinel节点发现某实例未在规定时间内响应,则认为改实例主观下线

    (2)客观下线:若超过指定数量的sentinel都认为该实例主观下线,则改实例客观下线

    2.哨兵选主规则:

    (1)首先判断主从节点断开时间长短,如超过指定时间则排除改节点

    (2)然后判断从节点的slave_priority值,越小优先级越高

    (3)如果slave_prority一样,则判断slave节点的offset值,越大优先级越高

    (4)最后判断slave节点的运行id大小,越小优先级越高

    3.Redis集群脑裂是什么?该如何实现

    集群脑裂是由于主节点和sentinel处于不同的网络分区,使得sentinel没有能够心跳感知到主节点,所以又选出了一个从节点为主节点

    集群脑裂带来的问题:

    客户端 写入数据还是会写到老的主节点,新节点无法同步数据,当网络恢复后,sentinel会将老的主节点将为从节点,这时再从新的主节点同步数据,就会导致数据丢失

    解决:我们可以修改redis的配置,可以设置最少的从节点数量以及缩短主从数据同步的延迟时间,达不到要求就拒绝请求,可以避免大量的数据丢失

    三.分片集群架构:

    1.主从和哨兵可以解决高可用,高并发读的问题,但是没有解决海量数据存储问题和高并发写问题

    集群里有多个master,每个master保存不同数据,相较于单个master,集群能存储更多的数据

    每个主节点有多个从节点

    主节点之间通过ping监测彼此健康状态

    客户端请求可以访问集群里任意节点,最终都会转发到正确节点

    2.Redis分片集群中数据是怎么存储和读取的

    (1)Redis分片集群里引入了哈希槽的概念,Redis集群里有16384个哈希槽

    (2)  将16384插槽到不同的实例

    (3)读写数据:根据key的有效部分计算哈希值,对16384取余(有效部分,如果key前面有大括号,大括号的内容就是有效部分,如果没有,则以key本身作为有效部分)余数作为插槽,寻找插槽所在的实例。

    四.Redis快的原因

    1.内存访问

      2.单线程,避免了线程的上下文切换

    3.IO多路复用

    下面我们来重点讲解一下IO多路复用

    Redis是纯内存操作,执行速度非常快,它的性能瓶颈是网络延迟而不是执行速度,I/O多路复用模型主要就是实现了高效的网络请求

    用户空间和内存空间

    用户空间和内核空间:

    linux系统中一个进程使用的内存情况划分为两部分:内核空间、用户空间

    用户空间:只能执行受限的命令,而且不能直接调用系统资源,必须通过内核提供的接口 

    内核空间:可以执行特权命令,调用一切系统资源

    Linux系统会在用户空间和内核空间都加入缓冲区

    写数据时,把用户缓冲数据拷贝到内核缓冲区,然后写入设备

    读数据时,要从设备读取数据到内核缓冲区,然后拷贝到用户缓冲区

     这里举个例子:当我们发送一条消息给对方的时候,我们发送的消息在用户缓冲区,然后到了内核缓冲区,然后再到硬件设备(网卡),通过网卡发给对方,然后对方回的消息会通过网卡放入内核缓冲区,然后到

    阻塞IO:

    阶段一:(1)用户进程尝试读取数据(比如网卡数据)

                 (2)此时数据尚未到达,内核需要等待数据

                 (3)此时用户进程处于阻塞状态

    阶段二:(1)数据到达并拷贝到内核缓冲区,代表已就绪

                (2)将内核数据拷贝到用户缓冲区

                (3)拷贝过程中,用户进程依然阻塞等待

                 (4)拷贝完成,用户进程阻塞解除,处理数据

    非阻塞IO:

    阶段一:

    (1)用户进程尝试读取数据(比如网卡数据)

    (2)此时数据尚未到达,内核需要等待数据

    (3)返回异常给用户进程

    (4)用户进程拿到error后,再次尝试去读

    (5)循环往复,直到数据就绪

    阶段二:

    (1)将内核数据拷贝到用户缓冲区

    (2)拷贝过程中,用户进程仍然阻塞等待

    (3)拷贝完成,用户进程解除阻塞,处理数据

      可以看到非阻塞IO模型中,用户进程在第一个阶段是非阻塞,第二个阶段是阻塞状态。虽然是非阻塞,但性能并没有得到提高,而且忙等机制会导致CPU空转,CPU使用率暴增。

    IO多路复用:

    是利用单个线程来同时监听多个socket,并在某个Socket可读,可写时得到通知,从而避免无效的等待,充分利用CPU资源

    阶段一:

    (1)  用户进程调用select,指定要监听的Socket集合

    (2)内核监听对应的多个socket

    (3)任意一个或多个socket数据就绪则返回readable

    (4)此过程中用户进程阻塞

    阶段二:

    (1)用户进程找到就绪的socket

    (2)依次调用recvform读取数据

    (3)内核将数据拷贝到用户空间

    (4)用户进程处理数据

    select和poll只会通知用户进程有Socket就绪,但不确定具体是那个socket,需要用户进程逐个遍历Socket来确认

    epoll则会通知用户进程Socket就绪的同时,把已就绪的Socket写入用户空间。

    Redis网络模型

    使用I/O多路复用结合事件的处理器来应对多个Socket请求

    (1)连接应答处理器

    (2)命令回复处理器,在Redis6.0之后,为了提升更好的性能,使用了多线程来处理回复事件

    (3)命令请求处理器,在Redis6.0之后,将命令的转换使用了多线程,增加命令转换速度,在命令执行的时候,依然是单线程

            

  • 相关阅读:
    Redis_第二章_实战篇_第一节_ 短信登录
    Jenkins设置root权限(13)
    痞子衡嵌入式:浅谈i.MXRT1xxx系列MCU时钟相关功能引脚的作用
    python与pycharm如何设置文件夹为源代码根目录
    java 工程管理系统源码+项目说明+功能描述+前后端分离 + 二次开发
    GPT实战系列-P-Tuning本地化训练ChatGLM2等LLM模型,到底做了什么?(二)
    嵌入式分享合集53
    Ubuntu Seata开机自启动服务
    Java Field.getType()方法具有什么功能呢?
    大数据开发和软件开发哪个前景好?
  • 原文地址:https://blog.csdn.net/m0_70386582/article/details/133249471