Redis高级

目录

一、Redis主从

1. 主从集群结构

2. 主从同步原理

2.1 全量同步

2.2 增量同步

3. 主从同步优化

4. 总结

二、Redis哨兵

1. 哨兵工作原理

1.1 哨兵作用

1.2 状态监控

1.3 选举新的master节点

2. 总结

三、Redis分片集群

1. 散列插槽

2. 故障转移

四、Redis数据结构

1. RedisObject

2. SkipList

3. SortedSet

五、Redis内存回收

1. 内存过期处理

2. 内存淘汰策略

3. 总结


一、Redis主从

单节点Redis的并发能力是有上限的,要进一步提高Redis的并发能力,就需要搭建主从集群,实现读写分离。

1. 主从集群结构

下图是一个简单的Redis主从集群结构:

集群中有一个master节点(主),两个slave节点(从)。当我们通过Redis的Java客户端访问主从集群时,应该做好路由:

  • 如果是写操作,应该访问master节点,master会自动将数据同步给两个slave节点

  • 如果是读操作,建议访问各个slave节点,从而分担并发压力

2. 主从同步原理

我们向master节点写入数据之后,在两个slave节点上也可以看到对应的数据,这说明主从之间完成了数据的同步。那么这个同步是如何完成的呢?

2.1 全量同步

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

但是主节点如何知道是不是第一次同步呢?

每一个节点在创建出来的时候,都会认为自己是master节点,因此每一个节点就会有一个唯一的ID,即replid。当该节点成为其他节点的从节点时,它就会继承master节点的ID。因此,如果请求数据同步的节点ID与master节点ID不同,就可以判断是不是第一次进行同步。

2.2 增量同步

全量同步需要先生成RDB文件,然后将RDB文件通过网络传输个slave,成本太高了。因此除了第一次做全量同步,其它大多数时候slave与master都是做增量同步,流程如下

做增量同步之前,需要知道一个重要的概念:偏移量(offset),随着记录在repl_baklog中的数据增多而逐渐增大。slave完成同步时也会记录当前同步的offset。如果slaveoffset小于masteroffset,说明slave数据落后于master,需要更新。

repl_baklog文件:是一个固定大小的环形数组,也就是说角标到达数组末尾后,会再次从0开始读写,这样数组头部的数据就会被覆盖。

repl_baklog文件中会记录Redis处理过的命令及offset,包括master当前的offset,和slave已经拷贝到的offset,slave与naster的offset之间的差异,就是slave需要增量拷贝的数据。

红色部分是需要进行同步的数据。

但是会有一种特殊情况,slave出现了网络阻塞,导致master的offset远远超过slave的offset,最终导致还没有进行数据同步,master就将slave的offset覆盖了。此时就只能进行全量同步。

3. 主从同步优化

主从同步可以保证主从数据的一致性,非常重要。

可以从下面几个方面来优化Redis主从集群:

  • 在master中配置repl-diskless-sync yes启用无磁盘复制(即主节点直接通过网络向从节点同步数据,不会先保存到磁盘中,再从磁盘取),避免全量同步时的磁盘IO。

  • Redis单节点的内存占用不要太大,减少RDB导致过多的磁盘IO

  • 适当提高repl_baklog的大小,发现slave宕机时尽快实现故障恢复,尽可能的避免全量同步

  • 限制一个master节点上的salve节点数量。

4. 总结

二、Redis哨兵

主从结构中master节点的作用非常重要,一旦故障就会导致集群不可用。Redis提供了哨兵Sentinel)机制来监控主从集群监控状态,确保集群的高可用性。

1. 哨兵工作原理

1.1 哨兵作用

哨兵集群作用原理图:

哨兵的作用如下:

  • 状态监控Sentinel 会不断检查masterslave是否按预期工作

  • 故障恢复(failover):如果master故障,Sentinel会将一个slave提升为master。当故障实例恢复后会成为slave

  • 状态通知Sentinel充当Redis客户端的服务发现来源,当集群发生failover时,会将最新集群信息推送给Redis的客户端,客户端就会知道有了一个新的master,就不会向旧的master中写数据了。

1.2 状态监控

sentinel基于心跳机制监测服务状态,每隔1秒向集群的每个节点发送ping命令,并通过实例的响应结果来做出判断:

  • 主观下线(sdown):如果某sentinel节点发现某Redis节点未在规定时间响应,则认为该节点主观下线。

  • 客观下线(odown):若超过指定数量(通过quorum设置)的sentinel都认为该节点主观下线,则该节点客观下线。quorum值最好超过Sentinel节点数量的一半,Sentinel节点数量至少3台。

一旦发现故障,sentinel需要在slave中选择一个作为新的master,选择依据如下:

  • 首先会判断slave节点与master节点断开时间长短,如果超过一定时间则会排除该slave节点

  • 然后判断slave节点的slave-priority值,越小优先级越高,如果是0则永不参与选举(默认都是1)。

  • 如果slave-prority一样,则判断slave节点的offset值,越大说明数据越新,优先级越高

1.3 选举新的master节点

首先sentinel集群会先选择出一个执行failover的节点,第一个确认master客观下线的人会立刻发起投票,一定会成为leader(执行failover的节点)

执行failover的流程如下:

假设我们有一个集群,初始状态下7001为master,7002和7003为slave

此时master发生故障,sentinel会给备选的slave1节点发送slaveof no one命令,让该节点成为master:

然后sentinel给所有其它slave发送slaveof 192.168.150.101 7002 命令,让这些节点成为新master,也就是7002slave节点,开始从新的master上同步数据。

等故障节点恢复之后会接收到哨兵信号,执行slaveof 192.168.150.101 7002命令,成为slave

2. 总结

三、Redis分片集群

主从模式可以解决高可用、高并发读的问题。但依然有两个问题没有解决:

  • 海量数据存储

  • 高并发写

要解决这两个问题就需要用到分片集群了。分片的意思,就是把数据拆分存储到不同节点,这样整个集群的存储数据量就更大了。

可以将分片集群理解为多个主从集群集群到一起了。

结构如图:

分片集群特征:

  • 集群中有多个master,每个master保存不同分片数据 ,解决海量数据存储问题

  • 每个master都可以有多个slave节点 ,确保高可用

  • master之间通过ping监测彼此健康状态 ,类似哨兵作用

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

1. 散列插槽

当使用分片集群时,数据要分片存储到不同的Redis节点,肯定需要有分片的依据,这样下次查询的时候才能知道去哪个节点查询。redis是利用散列插槽(hash slot)的方式实现数据分片的。

在Redis集群中,共有16384个hash slots,集群中的每一个master节点都会分配一定数量的hash slots。具体的分配在集群创建时就已经指定了:

redis中一共有16384个插槽,在分片集群中,会将这些插槽分配给不同的示例。例如上图,三个主从集群,每一个会被分配5461个插槽。然后根据key计算哈希值,对16384取余,余数作为插槽,寻找插槽所在的实例即可。

不过hash slot的计算也分两种情况:

  • key中包含{}时,根据{}之间的字符串计算hash slot

  • key中不包含{}时,则根据整个key字符串计算hash slot

例如:

  • key是user,则根据user来计算hash slot

  • key是user:{age},则根据age来计算hash slot

2. 故障转移

分片集群的节点之间会互相通过ping的方式做心跳检测,超时未回应的节点会被标记为下线状态。当发现master下线时,会将这个master的某个slave提升为master。

例如某个分片集群master节点为7002,有个从节点7006。如果7002发生故障,那么7006就会变成主节点,7002恢复后就会变成7006的slave节点。

四、Redis数据结构

1. RedisObject

不管是任何一种数据类型,最终都会封装为RedisObject格式,它是一种结构体。

结构如下图所示:

属性中的encoding就是当前对象底层采用的数据结构或者编码方式

下面要说的SkipList(跳表)就是一种encoding。

2. SkipList

SkipList(跳表)首先是链表,但与传统链表相比有几点差异:

  • 元素按照升序排列存储

  • 节点可能包含多个指针,指针跨度不同。

传统链表只有指向前后元素的指针,因此只能顺序依次访问。如果查找的元素在链表中间,查询的效率会比较低。而SkipList则不同,它内部包含跨度不同的多级指针,可以让我们跳跃查找链表中间的元素,效率非常高。

结构如图所示:

我们可以看到1号元素就有指向3、5、10的多个指针,查询时就可以跳跃查找。例如我们要找大小为14的元素,查找的流程是这样的:

3. SortedSet

SortedSet就是有序集合Zset。

SortedSet的结构体如下所示:

typedef struct zset {dict *dict; // dict,底层就是HashTablezskiplist *zsl; // 跳表
} zset;

Redis的SortedSet底层数据结构是怎么样的?

SortedSet是有序集合,底层的存储的每个数据都包含element和score两个值。score是得分,element则是字符串值。SortedSet会根据每个element的score值排序,形成有序集合。

它支持的操作很多,比如:

  • 根据element查询score值

  • 按照score值升序或降序查询element

要实现根据element查询对应的score值,就必须实现element与score之间的键值映射。SortedSet底层是基于HashTable来实现的。

要实现对score值排序,并且查询效率还高,就需要有一种高效的有序数据结构,SortedSet是基于跳表实现的。

五、Redis内存回收

1. 内存过期处理

过期处理指的就是存入Redis中的数据可以配置过期时间,到期后再次访问会发现这些数据都不存在了,也就是被过期清理了。

Redis是如何判断一个KEY是否过期呢?

在Redis中会有两个Dict,也就是HashTable,其中一个记录KEY-VALUE键值对,另一个记录KEY和过期时间。要判断一个KEY是否过期,只需要到记录过期时间的Dict中根据KEY查询即可。

Redis是何时删除过期KEY的呢?

Redis的过期KEY删除策略有两种:惰性删除、周期删除。

惰性删除顾名思义Redis不会定期去看内存中的KEY是否过期,而是在访问某个KEY的时候判断当前KEY是否过期,如果过期就直接删除。

周期删除就是通过一个定时任务,周期性的抽样部分过期的key,然后执行删除。

2. 内存淘汰策略

对于某些特别依赖于Redis的项目而言,仅仅依靠过期KEY清理是不够的,内存可能很快就达到上限。因此Redis允许设置内存告警阈值,当内存使用达到阈值时就会主动挑选部分KEY删除以释放更多内存。这叫做内存淘汰机制。

Redis支持多种内存淘汰策略,:

  • noeviction: 不淘汰任何key,但是内存满时不允许写入新数据,默认就是这种策略。

  • volatile-ttl: 对设置了TTL的key,比较key的剩余TTL值,TTL越小越先被淘汰

  • allkeys-random:对全体key ,随机进行淘汰。也就是直接从db->dict中随机挑选

  • volatile-random:对设置了TTL的key ,随机进行淘汰。也就是从db->expires中随机挑选。

  • allkeys-lru: 对全体key,基于LRU算法进行淘汰

  • volatile-lru: 对设置了TTL的key,基于LRU算法进行淘汰

  • allkeys-lfu: 对全体key,基于LFU算法进行淘汰

  • volatile-lfu: 对设置了TTL的key,基于LFI算法进行淘汰

其中volatile-lru和volatile-lfu是比较常用的两种策略。

  • LRULeast Recently Used),最近最久未使用。用当前时间减去最后一次访问时间,这个值越大则淘汰优先级越高。

  • LFULeast Frequently Used),最少频率使用。会统计每个key的访问频率,值越小淘汰优先级越高。

在RedisObject结构当中,其中的lru就是记录最近一次访问时间和访问频率的。

当然,选择LRULFU时的记录方式不同:

  • LRU:以秒为单位记录最近一次访问时间,长度24bit

  • LFU:高16位以分钟为单位记录最近一次访问时间,低8位记录逻辑访问次数

3. 总结

当Redis内存不足时会怎么做

这取决于配置的内存淘汰策略,Redis支持很多种内存淘汰策略,例如LRU、LFU、Random. 但默认的策略是直接拒绝新的写入请求。而如果设置了其它策略,则会在每次执行命令后判断占用内存是否达到阈值。如果达到阈值则会基于配置的淘汰策略尝试进行内存淘汰,直到占用内存小于阈值为止。

逻辑访问次数是如何计算的

由于记录访问次数的只有8bit,即便是无符号数,最大值只有255,不可能记录真实的访问次数。因此Redis统计的其实是逻辑访问次数。这其中有一个计算公式,会根据当前的访问次数做计算,结果要么是次数+1,要么是次数不变。但随着当前访问次数越大,+1的概率也会越低,并且最大值不超过255.

除此以外,逻辑访问次数还有一个衰减周期,默认为1分钟,即每隔1分钟逻辑访问次数会-1。这样逻辑访问次数就能基本反映出一个key的访问热度了。

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

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

相关文章

正点原子esp32s3探测土壤湿度

开发板使用&#xff1a;正点原子ATK_DNESP32S3 V1.3 IDE: VSCODE PLATFORMIO 土壤湿度检测传感器模块如下图&#xff1a; 引脚&#xff1a; 传感器VCC --> ESP32[3.3V] 传感器GND --> ESP32[GND] 传感器A0 --> ESP32[GPIO20] 代码如下&#xff1a; #include <…

一篇文章解决 Win10 同时部署多个版本的Tomcat

文章目录所用到的文件夹Tomcat服务端口修改Tomcat参数修改环境变量配置验证环境是否配置成功可能遇到的问题问题一&#xff1a;startup.bat闪退问题二&#xff1a;startup.bat成功启动&#xff0c;但仍打不开服务器总结最近在学习JavaWeb的时候&#xff0c;想安装新版本的Tomca…

CentOS7安装和使用Workbench

文章目录CentOS7安装和使用Workbench一、前言1.简介2.环境二、正文1.更换镜像源2.安装依赖包3.下载4.安装5.打开workbench6.使用记录1&#xff09;连接数据库2&#xff09;创建数据库3&#xff09;导入数据3&#xff09;导出数据4&#xff09;运行SQL脚本5&#xff09;打开SQL脚…

SpringBoot查询方式全解析

文章目录一、简介二、常用注解分类1、请求映射类&#xff08;处理 URL 与 HTTP 方法的绑定&#xff09;2、参数绑定类&#xff08;从请求中获取数据并绑定到方法参数&#xff09;3、控制器与增强类&#xff08;标识控制器及全局增强&#xff09;4、异常与响应处理类&#xff08…

Linux操作系统从入门到实战(十五)详细讲解Linux调试器 gdb/cgdb使用

Linux操作系统从入门到实战&#xff08;十五&#xff09;详细讲解Linux调试器 gdb/cgdb使用前言一、gdb/cgdb是什么&#xff1f;1. 程序的两种发布模式&#xff08;debug 和 release&#xff09;二、gdb/cgdb如何启动&#xff1f;1. 准备工作2. 启动 gdb/cgdb 调试器2.1 启动 g…

基于UDP的代理协议的Tuic怎么样?

Tuic&#xff08;全称“TUIClient”&#xff09;是一款基于UDP协议的轻量代理工具&#xff0c;主打低延迟与高实时性&#xff0c;专为解决传统TCP代理在实时场景中的性能瓶颈而生。其核心设计围绕“UDP优先”展开&#xff0c;通过简化握手流程、优化加密效率&#xff0c;在保持…

缓存投毒进阶 -- justctf 2025 Busy Traffic

题目核心逻辑如下 let browser; // 全局浏览器实例// 访问指定 URL 的异步函数 const visit async (url) > {try {// 如果已有浏览器实例&#xff0c;先关闭并等待 2 秒if (browser) {await browser.close();await sleep(2000);console.log("Terminated ongoing job.&…

复刻苏宁易购(移动端)

html代码<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><link rel"s…

Scrapy返回200但无数据?可能是Cookies或Session问题

引言 在使用Scrapy框架进行网页爬取时&#xff0c;开发者可能会遇到一个常见但令人困惑的问题&#xff1a;HTTP请求返回状态码200&#xff08;表示成功&#xff09;&#xff0c;但实际获取的数据却是空的。这种情况通常意味着目标服务器接受了请求&#xff0c;但由于某些原因没…

【gateway nc adapter虚拟网卡 win11 联想】问题的解决

前言&#xff1a;由于需要登录公司内网&#xff0c;于是启用奇安信VPN。但启动后报出网关未连接的问题&#xff0c;于是我检查了我的网络适配器&#xff0c;并尝试解决&#xff0c;以下给出几种我实践过程中的行动&#xff0c;并附带最后成功的解决方法 【gateway nc adapter虚…

基于开源AI智能名片链动2+1模式S2B2C商城小程序的运营策略创新研究

摘要&#xff1a;在数字化商业生态快速演进的背景下&#xff0c;传统运营模式面临用户增长乏力、转化效率低下等挑战。本文以开源AI智能名片链动21模式与S2B2C商城小程序的深度融合为研究对象&#xff0c;提出通过周期化运营规划、关键节点策略设计、跨部门协同创新、数据驱动决…

smart-water表设计方案

-- -- 2. SOP 管理模块 -- -- 2.1 SOP主表 (存储SOP元数据&#xff0c;与版本分离) CREATE TABLE sops (id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),name VARCHAR(255) NOT NULL,description TEXT,latest_published_version_id UUID, -- 外键约束在版本表创建后添加crea…

A4.0:继C5.2的BJT理论引申的开关作用的应用示例

在C5里知道了BJT的静态工作点Q的计算方式&#xff08;IC和VCE的负载线&#xff09;&#xff0c;以及偏置电阻RB&#xff0c;得到了电流IB&#xff0c;进而通过电流增益hFE得到了IC(IC β*IB)&#xff0c;然后VCE VCC - IC*RC&#xff0c;即集电极和发射极之间的电压等于集电极…

平板探测器的主要技术指标

平板探测器(Flat-panel-detector,FPD)是一种广泛应用于医学影像学(如X射线、CT扫描等)、工业无损检测和科学研究中的成像设备。其主要技术指标包括以下几个方面: 1.空间分辨率(SpatialResolution) 定义:空间分辨率是指平板探测器能清晰分辨图像中细节的能力。一般以…

从苏州姑苏区人工智能大模型基础设施招标|学习参数5:单颗 AI 处理器的内存带宽如何达到 1600GB/s

招标参数5:配置≥8 个AI 处理器,支持OAM式集成服务器形式。单个 AI 处理器支持≥370TFLOPS@FP16或 80TFLOPS@FP32 算力,支持≥64GB HBM高带宽内存,单个AI处理器内存带宽≥1600GBps 单张卡算力及内存带宽参考如下NVIDIA算力表 H3C R4900 G5:支持多达 32 个 DDR4 内存,速率…

【机器学习深度学习】Embedding 模型详解:从基础原理到实际应用场景

目录 前言 一、Embedding 模型基础&#xff1a;文本到向量的“魔术师” 1.1 什么是 Embedding&#xff1f; 1.2 为什么需要 Embedding&#xff1f; 二、核心作用与优势&#xff1a;语义分析的“利刃” 三、工作原理拆解&#xff1a;从训练到应用的完整链条 3.1 训练阶段…

防御保护10

双机热备组网配置主备备份组网1、配置ip地址2、配置安全区域3、ospf配置4、配置双机热备5、安全策略hrp adjust ospf-cost enable --- 配置根据VGMP状态调整OSPF Cost值如果防火墙下行设备为三层设备&#xff0c;通过路由来引导流量&#xff0c;则需要配置上述命令&#xff1b;…

Python爬虫实战:研究meshio库,构建网格文件数据采集系统

一、引言 (一)研究背景 在有限元分析、计算流体力学(CFD)、计算机辅助设计(CAD)等领域,网格文件是描述几何模型离散化信息的基础数据载体,包含节点坐标、单元连接关系、物理属性等关键信息。目前,网格文件格式多达数十种(如 VTK、STL、OBJ、ANSYS CDB 等),且分散…