Redis集群(分布式缓存):详解持久化、主从同步原理、哨兵机制、Cluster分片集群,实现高并发高可用

news2024/12/25 9:33:59

0、引言

        单机式Redis存在以下问题,因此需要Redis集群化来解决这些问题


1、持久化

1.1 RDB(Redis Database Backup file )持久化

       Redis数据快照,简单来说就是把内存中的所有数据都记录到磁盘中。当Redis实例故障重启后,从磁盘读取快照文件,恢复数据。快照文件称为RDB文件,默认是保存在当前运行目录。   

 (1)执行方法:

 (2)原理

        着重比较一下save命令与bgsave:
        save会阻塞所有命令,因为备份的过程不允许更改。
        而bgsave不会阻塞其他命令、是通过fork一个子线程共享数据,然后读取内存数据并写入 RDB 文件,如果主线程此时进行写操作,则会拷贝一份数据出来执行写操作。

        个人理解,这个Redis的RDB文件类似于Mysql里的Redo日志,存的是数据。

1.2 AOF(Append Only File )持久化 

(1)AOF持久化原理

        与RDB相对的,AOF并不是直接将数据存入磁盘进行持久化保存,
        而是通过将每一个写命令记录在AOF文件中实现持久化。个人理解,就很类似于Mysql的Binlog日志,记录的是具体的语句操作。

        例如,set num 123这一步操作,AOF就会记录相应的操作语句。

        其刷盘频率的规定如下: 通过redis.conf文件进行配置:

# 表示每执行一次写命令,立即记录到AOF文件
appendfsync always 
# 写命令执行完先放入AOF缓冲区,然后表示每隔1秒将缓冲区数据写到AOF文件,是默认方案
appendfsync everysec 
# 写命令执行完先放入AOF缓冲区,由操作系统决定何时将缓冲区内容写回磁盘
appendfsync no

(2)AOF的文件重写

        既然记录的是写操作,如果对一个数据多次重复写,那么有很多次写操作都是无用操作,因此AOF能够执行如图所示重写功能:

        

 1.3 RDB与AOF对比总结


2、Redis主从架构

2.1 简单搭建

        类似于MySQL,单节点Redis并发能力有限,需要搭建主从结构:即,主Redis进行写操作,从Redis执行读操作,并且主从之间要保持数据同步。

搭建流程:

连接到从redis:

redis-cli -p 端口号

建立其master:

SLAVEOF 主IP地址 主端口号(SLAVEOF也可以换成REPLICAOF)

 2.2 全量同步

(1)基本流程

        主从第一次建立连接时,会执行全量同步,将master节点的所有数据都拷贝给slave节点。

        在同步的过程中,需要用到上文提到的RDB文件。
        还会用到repl_baklog文件:通过bgsave生成RDB时,是子进程复制出的数据进行存盘,但如果此时主线程趁此时进行写数据,那这些新的数据不就没有同步进slave里了吗??
        因此,redis会在此时通过repl_baklog记录bgsave期间的所有命令,再发给slave进行补充,保证数据的完整。

        具体流程如下:

 (2)问题:slave向master请求数据同步,master如何知道这是第一次来连接?

通过以下两个概念作为判断依据:

  • Replication Id:简称replid,是数据集的标记,id一致则说明是同一数据集。每一个master都有唯一的replid,slave则会继承master节点的replid
    此为关键:这个id如果不同,说明是第一次!

  • offset:偏移量,随着记录在repl_baklog中的数据增多而逐渐增大。slave完成同步时也会记录当前同步的offset。如果slave的offset小于master的offset,说明slave数据落后于master,需要更新。

         因为slave原本也是一个master,有自己的replid和offset,当第一次变成slave,与master建立连接时,发送的replid和offset是自己的replid和offset。master判断发现slave发送来的replid与自己的不一致,说明这是一个全新的slave,就知道要做全量同步了。

        master会将自己的replid和offset都发送给这个slave,slave保存这些信息。以后slave的replid就与master一致了。

  2.3 增量同步

        在2.2节的基础上,当主从的Replication Id相同时,我们可以理解为,此时slave数据集至少是master的子集了。
        主从数据剩余部分具体相差多少呢?可以通过offset偏移量来进行记录。
        repl_baklog中会记录Redis处理过的命令日志及offset,包括master当前的offset,和slave已经拷贝到的offset。每次在第二阶段,master就去发送:从 已经拷贝过的offset开始 到 当前offset的数据,如图所示:

   ---->             ---->   

         repl_baklog这个文件是一个固定大小的数组,只不过数组是环形,也就是说角标到达数组末尾后,会再次从0开始读写,这样数组头部的数据就会被覆盖,但因为slave(绿色部分已经同步了,因此master可以直接覆盖也无妨)

        但是如果slave宕机过久,导致master把尚未同步的红色部分覆盖了(即,红色超过了一整圈):例如下图,此时只能全量同步了。 

 2.4 知识总结

简述全量同步和增量同步区别?

  • 全量同步:master将完整内存数据生成RDB,发送RDB到slave。后续命令则记录在repl_baklog,逐个发送给slave。

  • 增量同步:slave提交自己的offset到master,master获取repl_baklog中从offset之后的命令给slave

什么时候执行全量同步?

  • slave节点第一次连接master节点时

  • slave节点断开时间太久,repl_baklog中的offset已经被覆盖时

什么时候执行增量同步?

  • slave节点断开又恢复,并且在repl_baklog中能找到offset时

3、 Redis哨兵

        在第2节中,我们讲述了从机宕机后,通过repl_baklog的offset来进行恢复从机的数据。
        但如果,宕机是主机而不是从机,该怎么办?显然这时候需要指定新的主机了!而redis哨兵机制能够自动监控主机的健康状态、以及在主机挂掉后指定从机。

3.1 原理     

  • 监控:Sentinel 会不断检查您的master和slave是否按预期工作
            这里sentinel会反复向主机发送ping,如果在规定时间内收到pong,说明主机还是好的,反之反之。如果有超过半数的哨兵认为主机挂了,那说明主机挂了。

  • 自动故障恢复:如果master故障,Sentinel会将一个slave提升为master。当故障实例恢复后也以新的master为主
           具体怎么选新的主机呢?
           首先会判断slave节点与master节点断开时间长短,如果超过指定值(down-after-milliseconds * 10)则会排除该slave节点
           然后判断slave节点的slave-priority值,越小优先级越高,如果是0则永不参与选举
           如果slave-prority一样,则判断slave节点的offset值,越大说明数据越新,优先级越高
           最后是判断slave节点的运行id大小,越小优先级越高

  • 通知:Sentinel充当Redis客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给Redis的客户端

3.2 故障转移步骤

故障转移步骤有哪些?

  • 首先选定一个slave作为新的master,执行slaveof no one

  • 然后让所有节点都执行slaveof 新master

  • 修改故障节点配置,添加slaveof 新master

 4、 Cluster分片集群

        对于第3节中的哨兵模式,其每个节点存储的数据是一样的,浪费内存,并且不好在线扩容。当有海量数据需要存储、高并发的写问题出现时候,就要采取分片集群的方式来解决问题了。

4.1 分片集群的特征

  • 集群中有多个master,每个master保存不同数据

  • 每个master都可以有多个slave节点

  • master之间通过ping监测彼此健康状态(代替哨兵),如果挂掉了会故障转移。

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

 4.2 散列插槽

        插槽算法把整个数据库被分为16384个slot(槽),每个进入Redis的键值对,根据key进行散列,分配到这16384插槽中的一个。使用的哈希映射也比较简单,用CRC16算法计算出一个16 位的值,再对16384取模。数据库中的每个键都属于这16384个槽的其中一个,集群中的每个节点都可以处理这16384个槽。

        集群中的每个节点负责一部分的hash槽,比如当前集群有A、B、C个节点,每个节点上的哈希槽数 =16384/3,那么就有:

节点A负责0~5460号哈希槽
节点B负责5461~10922号哈希槽
节点C负责10923~16383号哈希槽

即: 数据key不是与节点绑定,而是与插槽绑定。 这样,三个节点分别处理不同的槽位置的数据,在存、取数据时,会根据运算得到的槽,自动切换节点。

  4.3 动态扩容、缩容

        在4.2节的基础上,我们知道,实际上数据不是存储在节点上的,而是插槽上的。因此,如果想增加新的节点时,给新的节点分配插槽即可。如果想删掉旧的节点时,先把插槽转移给别的节点,再把没有插槽的空节点删了即可

(1)动态扩容举例     

        使用redis-cli的add-node命令新增一个主节点8007(master),前面的ip:port为新增节点,后面的ip:port为集群中已存在的节点。        

src/redis-cli --cluster add-node 192.168.100.100:8007 192.168.100.100:8001

         当添加节点成功以后,新增的节点不会有任何数据,因为它还没有分配任何的slot(hash槽),我们需要为新节点手工分配hash槽
        使用redis-cli的rehash命令为8007分配hash槽,找到集群中的任意一个主节点,对其进行重新分片工作。

src/redis-cli --cluster reshard 192.168.100.100:8001
How many slots do you want to move (from 1 to 16384)? 600
(ps:需要多少个槽移动到新的节点上,自己设置,比如600个hash槽)
What is the receiving node ID? 2728a594a0498e98e4b83a537e19f9a0a3790f38
(ps:把这600个hash槽移动到哪个节点上去,需要指定节点id)
Please enter all the source node IDs.
  Type 'all' to use all the nodes as source nodes for the hash slots.
  Type 'done' once you entered all the source nodes IDs.
Source node 1:all
(ps:输入all为从所有主节点(8001,8002,8003)中分别抽取相应的槽数指定到新节点中,抽取的总槽数为600个)
 ... ...
Do you want to proceed with the proposed reshard plan (yes/no)? yes
(ps:输入yes确认开始执行分片任务)

        槽位迁移后,对应槽位中的数据也会迁移! 

(2)动态缩容举例    

         例如,我们将(1)中的8007节点删除:
        因为主节点8007的里面是有分配了hash槽的,所以我们这里必须先把8007里的hash槽放入到其他的可用主节点中去,然后再进行移除节点操作,不然会出现数据丢失问题。

src/redis-cli  --cluster reshard 192.168.100.100:8007

 ... ...
How many slots do you want to move (from 1 to 16384)? 600
What is the receiving node ID? baf0c2f3afde2410e34351a8261a703f1394cee9
(ps:这里是需要把数据移动到哪?8001的主节点id)
Please enter all the source node IDs.
  Type 'all' to use all the nodes as source nodes for the hash slots.
  Type 'done' once you entered all the source nodes IDs.
Source node 1:4b339ad25b4884c2ff6de8a8ec2bc8766f8faf0b
(ps:这里是需要数据源,也就是我们的8007节点id)
Source node 2:done
(ps:这里直接输入done 开始生成迁移计划)
 ... ...
Do you want to proceed with the proposed reshard plan (yes/no)? Yes
(ps:这里输入yes开始迁移)

        至此,我们已经成功的把8007主节点的数据迁移到8001上去了,我们可以看一下现在的集群状态如下图,你会发现8007下面已经没有任何hash槽了,证明迁移成功!   
      

        最后我们直接使用del-node命令删除8007主节点即可

 src/redis-cli  --cluster del-node 192.168.100.100:8007 4b339ad25b4884c2ff6de8a8ec2bc8766f8faf0b

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/630752.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CSS 布局备忘录

CSS 布局 元素布局display:blockdisplay:inlinedisplay:inline-blockdisplay:inheritdisplay:none Position 布局Flex 布局父元素属性flex-directionflex-wrapflex-flowjustify-contentalign-itemsalign-content 子元素属性orderflex-growflex-shrinkflex-basisfelxalign-self …

电商--抢购总结

文章目录 业务流程业务难点技术难点技术方案技术方向具体落地客户端流控网关流控容器流控后端接口流控数据库流控 流控总结优化读取加速异步化流程处理系统扩容 压测监控 总结参考文献 业务流程 客户端抢购流程中会涉及到商品数据的读取用于商品展示,运营活动数据的…

MM32F3273G8P火龙果开发板MindSDK开发教程8 - MutilButton的移植

MM32F3273G8P火龙果开发板MindSDK开发教程8 - MutilButton的移植 1、MutilButton简介 MultiButton 是一个小巧简单易用的事件驱动型按键驱动模块,可无限量扩展按键,按键事件的回调异步处理方式可以简化你的程序结构,去除冗余的按键处理硬编…

NodeJS SessionToken验证⑧

文章目录 ✨文章有误请指正,如果觉得对你有用,请点三连一波,蟹蟹支持😘前言登录鉴权Cookie&Session ExpressSession中间件 MVC演示登录鉴权JSON Web Token (JWT) Jsonwebtoken参数sign 方法verify 方法 封装JsonWebToke…

北邮22信通:第六章查找:BST树表(代码超详细逐步图解)

北邮22信通一枚~ 跟随课程进度每周更新数据结构与算法的代码和文章 持续关注作者 解锁更多邮苑信通专属代码~ 获取更多文章 请访问专栏: 北邮22信通_青山如墨雨如画的博客-CSDN博客 目录 讲解 1.构造函数 2.析构函数 3.查询函数 4.删除操作 &#xf…

全新出品!阿里 P5 工程师~P8 架构师晋升路线揭秘

阿里巴巴终于公开了从初级程序员到架构师的学习路线图,这里相对应的基本上就是从P5到P8的晋升体系!今天老师将会带着大家从初级程序员开始一点点分享整个晋升体系! 职级:初级程序员 薪资:6-12K 开发年限:0-…

PureComponent和Component的区别和底层处理机制

PureComponent和Component都是React中的组件类,但它们在实现细节和使用上有些差别。 Component是React中定义组件的基类,它的shouldComponentUpdate方法默认返回true,也就是说,每次调用setState或forceUpdate方法都会引发组件重新…

代码随想录第55天

1.判断子序列: 动态规划五部曲分析如下: 确定dp数组(dp table)以及下标的含义 dp[i][j] 表示以下标i-1为结尾的字符串s,和以下标j-1为结尾的字符串t,相同子序列的长度为dp[i][j]。 注意这里是判断s是否…

百度新闻源调整:自媒体权重降低,官方媒体优势突显

我是卢松松,点点上面的头像,欢迎关注我哦! 根据黑猫发稿的消息,自6月1日起,百度新闻源取消了大部分自媒体新闻源的收录,包括搜狐自媒体、企鹅号、网易号,甚至百度自己的百家号也受到了影响。 …

X2000 Linux 低功耗

一、进入休眠 当系统启动后,在命令终端输入: echo mem> /sys/power/state 即可立即进入休眠,功耗也随之降低。 二、配置中断唤醒GPIO 1、确认kernel默认配置文件 进入到/tools/iconfigtool/IConfigToolApp/路径下,执行./…

【Pm4py第四讲】关于Conversion

本节用于介绍pm4py中的转换函数,包括日志、事件流、数据块的转换、Petei网、流程树、BPMN的转换、可达图、面向对象日志等。 1.函数概述 本次主要介绍Pm4py中一些常见的转换函数,总览如下表: 函数名说明convert_log_to_networkx(…

Java(30天拿下---第一天)

Java开发(30天拿下---第一天) 一 hello world以及JDK,JRE,JVM二 转义字符三 注释四 代码规范五 DOS命令(了解)六 变量1.加号的使用2.数据类型整型浮点型字符类型布尔类型自动类型转换强制类型转换String类型 七 API文档 一 hello …

React | Redux的使用详解

✨ 个人主页:CoderHing 🖥️ React.js专栏:React.js Redux的使用详解 🙋‍♂️ 个人简介:一个不甘平庸的平凡人🍬 💫 系列专栏:吊打面试官系列 16天学会Vue 7天学会微信小程序 N…

亚马逊云科技Serverless数据分析,助力猎豹移动构建更高性价比数据仓库

也许你也听过这样一句话:“21世纪什么最贵?人才!”当数字经济全面席卷而来,这个问题的答案不可置否地变为了“数据”。通过数据分析获取近乎实时的洞察,以驱动业务的全流程,是企业数字化转型的必经之路。借…

【文末送书】微服务拆分规范

目录 一. 🦁 什么是微服务?二. 🦁 拆分模型Ⅰ. 压力模型拆分1. 垂直拆分(Vertical Decomposition)2. 水平拆分(Horizontal Decomposition)3. 动态拆分(Dynamic Decomposition&#x…

初识网络之http协议

目录 一、http协议含义 二、 认识URL 三、urlencode与urldecode 1. urlencode 2. urldecode 四、http协议响应与请求格式 1. http协议请求格式 2.http协议响应格式 3. http请求实际形式 3.1 程序准备 3.2 浏览器发起请求 3.3 请求行内容 3.4 请求报头内容 4. htt…

2022年国赛高教杯数学建模E题小批量物料的生产安排解题全过程文档及程序

2022年国赛高教杯数学建模 E题 小批量物料的生产安排 原题再现 某电子产品制造企业面临以下问题:在多品种小批量的物料生产中,事先无法知道物料的实际需求量。企业希望运用数学方法,分析已有的历史数据,建立数学模型&#xff0c…

mysql联合索引详解

比较简单的是单列索引(btree)。遇到多条件查询时,不可避免会使用到多列索引。联合索引又叫复合索引。 btree结构如下: 每一个磁盘块在mysql中是一个页,页大小是固定的,mysql innodb的默认的页大小是16k&a…

【工作中遇到的性能优化问题】

项目场景: 页面左侧有一列表数据,点击列表项会查对应的表格数据和表单信息(表单是根据数据配置生成的),并在右侧展示。如果数据量大,则非常卡。 需要对此页面进行优化。 问题描述 问题一、加载左侧数据时…

systemV的工作原理+原理代码

概念 我们知道进程间的通信有管道的方式进程通信管道制作_云的小站的博客-CSDN博客 但是我们的管道通信其实属于一种取巧的方式,利用了打开的文件可读写的特性上,两个进程对此分别进行读写操作就会产生所谓的通信现象,但是外面的管道依旧得…