【Java】Redis(中间件)

一、对Redis的理解

        Reids是一种基于内存的数据库,对数据的读写操作都在内存中完成,因此读写速度非常快,常用于缓存、消息队列、分布式锁等场景。除此之外,Redis还支持事务、持久化、Lua脚本、多种集群方案(主从复制模式、哨兵模式、切片机群模式)、发布/订阅模式、内存淘汰机制、过期删除机制等等。


二、五大基本数据类型

1、String(字符串)

        String类型的底层数据结构实现主要是SDS(简单的动态字符串)。

  • SDS 不仅可以保存文本数据,还可以保存二进制数据。SDS的所有API都会以处理二进制的方式来处理SDS存放在buf[]数组中的数据。所以 SDS不仅可以保存文本数据,还可以保存图片、音频、视频等这些二进制数据。
  • SDS 获取字符串长度的实践复杂度为O(1)。因为SDS不是采用C语言的“\0”来判断字符串是否结束,而是采用len属性的值,所以时间复杂度为O(1);
  • Redis 的 SDS API 是安全的,拼接字符串不会造成缓冲区溢出。因为 SDS 在拼接之前对 SDS 的空间进行检查,不满足会进行扩容。

2、List(列表)

        List类型的底层数据结构是由双向链表或压缩指针实现:

  • 如果列表的元素个数小于 512 个(默认值,可由 list-max-ziplist-entries 配置),列表每个元素的值都小于 64 字节(默认值,可由 list-max-ziplist-value 配置),Redis 会使用压缩列表作为 List 类型的底层数据结构;
  • 如果列表的元素不满足上面的条件,Redis 会使用双向链表作为 List 类型的底层数据结构;
  • 但是在 Redis 3.2 版本之后,List 数据类型底层数据结构就只由 quicklist 实现了,替代了双向链表和压缩列表。

3、Hash(散列)

        Hash 类型的底层数据结构是由压缩列表或哈希表实现的

  • 如果哈希类型元素个数小于 512 个(默认值,可由 hash-max-ziplist-entries 配置),所有值小于 64 字节(默认值,可由 hash-max-ziplist-value 配置)的话,Redis 会使用压缩列表作为 Hash 类型的底层数据结构;
  • 如果哈希类型元素不满足上面条件,Redis 会使用哈希表作为 Hash 类型的底层数据结构。在
  • Redis 7.0 中,压缩列表数据结构已经废弃了,交由 listpack 数据结构来实现了。

4、Set(集合)

        Set 类型的底层数据结构是由整数集或哈希表合实现的:

  • 如果集合中的元素都是整数且元素个数小于 512(默认值,set-maxintset-entries 配置)个,Redis 会使用整数集合作为 Set 类型的底层数据结构;
  • 如果集合中的元素不满足上面条件,则 Redis 使用哈希表作为 Set 类型的底层数据结构。

5、sorted_set(有序集合)

        Set 类型的底层数据结构是由压缩列表或跳表合实现的:

  • 如果有序集合的元素个数小于 128 个,并且每个元素的值小于 64 字节时,Redis 会使用压缩列表作为 Zset 类型的底层数据结构;
  • 如果有序集合的元素不满足上面的条件,Redis 会使用跳表作为 Zset 类型的底层数据结构;
  • 在 Redis 7.0 中,压缩列表数据结构已经废弃了,交由 listpack 数据结构来实现了。

三、持久化

RDB(快照形式、保存当前数据状态)

        在进行保存时可能会阻塞当前redis服务器,直到当前rdb过程完成,所以如果数据量过大,可能造册长时间的阻塞,我们通常使用bgsave进行保存。RDB 触发条件:

  • 手动触发

    • save:执行该指令后,主线程执行 rdbSave 函数,服务器进程阻塞,即不能处理任何其他请求
    • bgsave(background save):本质上这个命令和 save 差不多,区别在于这个命令会 fork 了一个子进程,去执行 rdbSave 函数,因此主线程还是可以执行新请求的。
  • 自动触发: 配置文件中写入save m n,代表当m秒内发生n次变化时,会自动执行 bgsave

AOF(以日志的方式进行持久化)

        redis可以通过AOF文件,将文件中的数据修改命令全部执行一遍,以恢复数据。

AOF重写:

        实现方式:创建一个新的AOF文件,替换原来的AOF文件。

AOF恢复:

AOF 触发条件

  • 手动触发: bgrewriteaof
  • 自动触发:配置文件中设置 appendonly yes 开启
  • 自动触发的写入策略:
    • Always:即同步写回,在每个写命令执行完成后,直接将命令落入磁盘文件(数据基本保证可靠性,但是影响 Redis 的性能)
    • Everysec:即每秒写回,对于每个命令执行完成后,该命令被写入文件的内存缓存区,每过 1 秒,redis 会把该缓存区命令写到磁盘的 AOF 文件中(出了问题最多丢失一秒内数据,性能影响较小)
    • No:这个 No 不是不执行 AOF,而是将操作命令全部只写到 Redis 缓存区,至于在何时将缓存数据落盘,交给操作系统决定(出了问题,数据丢失情况不可控,性能影响最小)

四、删除策略

1、基于过期时间(数据创建时固定时间)(过期的数据并没有真正的删除)

Redis是一种内存级数据库,所有数据均存放在内存中,内存中的数据可以通过TTL指令获取其状态 XX :具有时效性的数据

-1 :永久有效的数据

-2 :已经过期的数据或被删除的数据或未定义的数据

过期删除策略:

定时删除

        创建定时器,当set数据设置的定时时间到达时,由定时器对该键值对执行删除任务,但是在执行期间会阻塞cpu,先进行删除,删除完成后才会释放cpu。(用cpu性能换区空间,那时间换空间)

惰性删除

        当数据过期时,不做处理,当下次访问该数据时再进行删除,并返回不存在该数据。虽然会节约cpu的性能,但当过期数据一直不被访问时,则会长期占用内存。(相当于用内存空间来换取时间,cpu的性能)

定期删除(定时删除+惰性删除)

        redis会主动执行定时删除策略,当不执行定期删除策略时,则执行惰性删除策略。

2、基于内存淘汰(内存满时)

LRU(最近最少使用)

        传统的LRU算法是基于【链表】实现,链表中的元素会按照操作顺序从前往后进行排序,最新的操作的键会被移动到表头,当需要淘汰元素时,直接从表尾进行淘汰。

        Redis并没有使用这样的方式进行实现LRU,因为会存在两个问题:

        1、需要使用链表管理所有的缓存数据,会带来额外的空间开销。

        2、当有数据被访问时,需要将链表中的元素移到表头,会很耗时,降低Redis缓存的性能。

    Rids如何实现LRU算法?

        它的实现方式是在Redis的对象结构体中添加一个额外的字段,用来保存该数据最后一次访问的时间。当Redis进行内存淘汰时,会使用随机采样的方式来进行淘汰数据,它会随机选取5个值,然后淘汰最久没有使用的那个。可以解决传承LRU存在的两个问题。但也会出现新的问题【缓存污染问题】:当软件一次读取大量数据,而这些数据只需要使用一次,那么这些数据就会在Redis缓存中存在很长的时间,造成数据污染。因此在Redis4.0后引入了 LFU 算法。

        

LFU(最近最不常用)

        LFU 算法是根据访问次数来决定淘汰数据,他的核心思想【如果数据被访问多次,那将来的访问的频率也会更高】,所以 LFU 算法会记录每个数据的访问次数,当数据被访问一次则会增加一次访问次数,这样就解决了 LRU 中数据污染的问题。

    Rids如何实现LFU算法?

        Redis对象头中的24bits的lru字段被分为,高16bit存储idt,低8bit用来存储logc。

  • ldt:是用来记录key被访问的时间戳。
  • logc:是用来记录key的访问频次【不是次数】,数值越小越容易被淘汰,key初始值为5

Redis在访问key时,对 logc 的变化:

  1. 先按照这次访问时间和上次访问时间的间隔,对 logc 进行衰减;
  2. 再按一定的概率增加 logc 的值;

五、企业级解决方案

缓存击穿

        当一个热点key突然失效时,那么这些请求就会击穿缓存(Redis)自己对数据库进行查找,从而导致性能下降。

解决方案:

        1、可以将key设置成永不过期的状态;

        2、可以加锁排队,当一个key突然失效,会有一个线程进入数据库进行查询,并将读取的数据重新放回 Reids 缓存中,该过程在加锁的状态下只允许一个线程对数据库进行请求,当第一个线程将数据写入缓存就可以正常进行查询。

缓存雪崩

        当大量key集中失效时,或者缓存服务宕机,会导致大量请求访问数据库,造成压力过大,甚至宕机。

解决方案:

        1、给不同的Key的TTL添加随机值

        2、利用Redis集群提高服务的可用性

        3、给缓存业务添加降级限流策略

        4、给业务添加多级缓存

缓存穿透

        当大量请求所查询的值缓存和数据库中都不存在时,会对数据库进行查询,会导致压力过大,甚至宕机。

解决方案:

        1、缓存空对象:单的解决方案就是哪怕这个数据在数据库中也不存在,我们也把这个数据存入到redis 中去,这样,下次用户过来访问这个不存在的数据,那么在redis中也能找到这个数据就不会进入到缓存 了

        2、布隆过滤


六、主从复制

        Redis 主从复制(Master-Slave Replication)是 Redis 实现高可用、数据备份和读写分离的核心机制。其核心思想是:一个主节点(Master)负责处理写操作和数据同步,多个从节点(Slave)通过复制主节点的数据,仅处理读操作,从而分担主节点压力、提高系统吞吐量,并实现数据冗余。

一、主从复制的核心作用

  1. 读写分离:Master 处理写请求(SET、DEL 等),Slaves 处理读请求(GET、ZRANGE 等),避免读写冲突,提升系统并发能力。
  2. 数据备份:Slave 是 Master 的实时备份,避免因 Master 单点故障导致数据丢失。
  3. 故障转移基础:当 Master 故障时,可通过哨兵(Sentinel)或集群机制将某个 Slave 升级为新 Master,实现高可用。

二、主从复制的核心原理(3 个阶段)

Redis 主从复制的过程分为「建立连接」「数据同步」「命令传播」三个阶段

建立连接:当主库从库上线后,不着急直接进行负责过程,首先需要握手进行信息验证。

数据同步:当捂手完成后,从库需向主库发送PSYN命令,即同步命令,开启数据同步过程,并发送主库ID,复制进度偏移量offset。

主库会根据从库发送的消息,进行逻辑判断,并告诉从库进行全量复制/断线后重复制。

       全量复制:初次复制后的同步

  • 主库执行BGSAVE,生成对应的RDB文件,同时开辟缓冲区,记录在RDB文件实行过程中,收到的新数据命令
  • RDB文件产生后,主库发给从库,从库通过RDB恢复数据

        断线后重复制:从库与主库断线重连后复制

  • 服务器运行 Id:唯一确定主库身份
  • 复制偏移量:代表主节点传输了的字节数
  • 复制积压缓冲区:复制积压缓冲区是一个先进先出队列,存储了最近主节点的数据修改命令。

命令传播:

        数据同步完成后,主从进入「稳定复制阶段」。此时 Master 每执行一条写命令,都会立即将命令发送给所有 Slave,Slave 执行后保持与 Master 数据实时一致。

七、哨兵系统

        哨兵系统:哨兵会对主库和从库进行监控,所有库每隔一段时间(10s)会向系统发送消息(心跳),如果一段时间没有收到消息,也就认为这个库挂掉了,如果挂的是主库,那么多个哨兵会选一个老大哨兵对所有从库的状态进行评估,选择一个最适合做主库的从库进行升级。当主库又成功上线会将主库降为从库。

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

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

相关文章

【题解】洛谷P1776 宝物筛选 [单调队列优化多重背包]

二进制优化还是不够快,如果我们想时间复杂度为 ,还得找新的方法。 (W 为背包最大可承载量,N 为物品种类数) 例题:P1776 宝物筛选 - 洛谷 原来的转移式很普通: 注意到对于每个 ,有…

数据结构_循环队列_牺牲一个存储空间_不牺牲额外的存储空间 Circular Queue(C语言实现_超详细)

目录循环队列的引出区别普通队列和循环队列两种循环队列的概念循环队列深入理解题目:此题,分为牺牲一个额外空间和不牺牲一个额外空间不牺牲一个额外空间完成第一步完成第二步完成第三步完成第四步牺牲一个额外空间完成第一步完成第二步完成第三步完成第…

Linux_网络基础

✨✨ 欢迎大家来到小伞的大讲堂✨✨ 🎈🎈养成好习惯,先赞后看哦~🎈🎈 所属专栏:LInux_st 小伞的主页:xiaosan_blog 制作不易!点个赞吧!!谢谢喵!&a…

Portainer:Docker可视化管理神器部署与使用攻略

Portainer是一款优秀的Docker可视化管理工具,它提供了简洁美观的Web界面,可以通过点击鼠标轻松管理Docker环境。 一、Portainer简介 Portainer是一个轻量级的Docker管理界面,具有以下特点: 可视化操作:通过Web界面管…

OVITO3.13.1_ Mac中文_材料科学、物理及化学领域设计的数据可视化和分析软件_安装教程

软件下载 【名称】:****OVITO3.13.1Mac中文 【大小】:****154M 【语言】:简体中文 【安装环境】:****mac 【网站下载链接】: https://a-xing.top/3008.html软件应用 软件应用 Ovito能做什么? Ovito的功能十…

MySQL 开发避坑:DROP TABLE 前你必须知道的几件事

MySQL 中删除表主要使用 DROP TABLE 语句。这是一个需要非常谨慎的操作,因为一旦执行,表结构和表中的所有数据都会被永久删除。1. 基本语法:删除单个表sqlDROP TABLE [IF EXISTS] table_name;* DROP TABLE: 核心命令,用于删除表…

浅谈人工智能之阿里云搭建coze平台

浅谈人工智能之阿里云搭建coze平台 一、部署环境准备 阿里云服务器配置要求 ○ 规格:最低2核CPU 4GB内存(推荐4核8GB保障流畅运行),作者原先想要利旧,使用了2核2GB的服务器,但是跑不起来,后来自…

ego(2)---初始轨迹生成后的关键点采样

在初始的多项式轨迹生成后,是要经过一个关键点采样,使用关键点来进行后续的 B 样条曲线拟合的。即:初始多项式拟合->关键点采样->B样条拟合关键点采样的思路关键点采样使用时间步长 ts 来在初始轨迹方程中取点。在上一步的初始轨迹生成…

专项智能练习(信息安全防护措施)

3.以下属于网络安全威胁的是(A )。 A.非授权访问、病毒感染、信息泄露、拒绝网络服务 B.信息泄露、非授权访问、病毒感染、硬盘损坏 C.信息篡改、非授权访问、病毒感染、硬盘损坏 D.网络异常、非授权访问、信息篡改、病毒感染 解析本题考查网络安全威胁。…

ubuntu编译webrtc库

一. 前言 本文介绍在 ubuntu 下如何通过 webrtc 源码编译出指定版本 webrtc.lib 库(以 m94 版本为例)。 二. 编译步骤 1. 下载depot_tools工具 depot_tools 是 Google 用来管理大型项目代码(例如 WebRTC)的工具集,它…

基于ZooKeeper实现分布式锁(Spring Boot接入)及与Kafka实现的对比分析

在分布式系统中,多节点对共享资源的并发访问往往会引发数据一致性问题,分布式锁正是解决这一问题的核心组件。本文将从原理出发,详细讲解基于ZooKeeper实现分布式锁的完整流程,提供Spring Boot接入的可运行代码,并深入对比其与Kafka实现分布式锁的异同点及优缺点,帮助开发…

Shell 三剑客之 awk 命令详解(理论+实战)

目录 一、前言 二、工作流程总览 三、最常用内置变量 四、命令格式 五、20 个高频实战案例 5.1 基础打印 awk {print "hello"} < /etc/passwd 所有行打印成hello awk {print} test6.txt 打印test6.txt文件 awk {print $1} test6.txt 默认以空格为分割&am…

一个真正跨平台可用的免费PDF解决方案

在整理资料时&#xff0c;常需将不同格式的文件统一转为PDF格式&#xff0c;确保排版不乱、便于长期保存和打印 它的功能全面&#xff0c;支持批量操作&#xff0c;使用非常方便&#xff1a;只需把PDF文件拖进界面&#xff0c;选择目标格式&#xff0c;无论PDF转换成Word、PDF…

强化微调:以Swift框架进行GRPO多模态模型强化微调为例

一、TL&#xff1b;DR 整体介绍&#xff1a;强化微调RFT的原因、步骤、作用以及常见的rft方式dmeo举例&#xff1a;以Swift给的Qwen2.5-Math-7B-Instruct为例介绍了整个RFT的流程和代码细节实际强化微调&#xff1a;以qwen/internVL为例完成一次指令微调并且使用强化学习进一步…

时序数据:使用关系数据库 vs 时序数据库存储的核心区别是什么?

一、时序数据使用关系数据库 vs 时序数据库存储的核心区别 时序数据&#xff08;Time Series Data&#xff09;是指随时间连续产生的数据&#xff08;如传感器读数、服务器指标、交易记录等&#xff09;&#xff0c;其核心特点是高频写入、时间有序、量大且查询模式集中于时间范…

ansible判断

ansible判断 一、判断运算符 “” “!” “>” “<” “>” “<” “and” “or” “not” is in 每次执行完一个任务&#xff0c;不管成功与失败&#xff0c;都会将执行的结果进行注册&#xff0c;可以使用这个注册的变量来判断 when&#…

接口设计标准化流程,结合RESTful最佳实践和实际开发经验,涵盖从需求分析到部署的全过程

目录一、接口设计流程二、需求分析阶段1. 功能需求2. 非功能性需求三、接口设计规范四、详细实现步骤1. 选择Web框架2. 接口路由设计3. 请求参数定义4. 请求参数验证5. 业务逻辑分层6. 错误处理机制7. 异步任务处理8. 安全策略9. 接口文档10. 测试策略11. 服务部署11.1 生产环境…

LeetCode 1023.驼峰式匹配

给你一个字符串数组 queries&#xff0c;和一个表示模式的字符串 pattern&#xff0c;请你返回一个布尔数组 answer 。只有在待查项 queries[i] 与模式串 pattern 匹配时&#xff0c; answer[i] 才为 true&#xff0c;否则为 false。 如果可以将 小写字母 插入模式串 pattern 得…

【IQA技术专题】 无参考自然图像IQA:NIQE

无参考自然图像IQA&#xff1a;NIQE&#xff1a;Making a “Completely Blind” Image Quality Analyzer&#xff08;2012 IEEE&#xff09;专题介绍一、研究背景二、NIQE方法2.1 NSS model2.2 Patch Selection2.3 Characterizing Image Patches2.4 Multivariate Gaussian Mode…

变位齿轮:分度圆、节圆与中心距的 “特殊关联”

接着上回的话题&#xff0c;在标准齿轮中&#xff0c;我们追求的是“节圆与分度圆重合”的理想状态。但当实际工程提出更苛刻的要求时&#xff0c;比如&#xff1a;需要避免齿轮根切&#xff08;齿数过少时&#xff09;。要配凑一个非标准的中心距。需要大幅提高小齿轮的强度和…