news 2026/6/30 4:19:26

redis缓存高并发、高性能?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
redis缓存高并发、高性能?

我们都知道系统中使用缓存,其实就两个主要的用途:高并发和高性能。
那么用了缓存后会有哪些弊端呢?

1. redis为什么是单线程模型?效率为什么高?

Redis 内部使用文件事件处理器file event handler,这个文件事件处理器是单线程的,所以 Redis 才叫做单线程的模型。
文件事件处理器的结构包含4 个部分
1、多个 socket
2、IO 多路复用程序
3、文件事件分派器
4、事件处理器
效率高:
1、纯内存操作
2、核心是基于非阻塞的 IO 多路复用机制
3、单线程反而避免了多线程的频繁上下文切换问题

2. 有哪些数据类型?

Redis 主要有以下几种数据类型:
Strings:字符串,最简单的数据类型,用于存储键值对。
Hashes:哈希表类似于map,用于存储键值对
Lists:有序列表,可以存储排行榜、文章评论列表之类的东西
Sets:无序集合,不能存储重复元素
Sorted Sets:排序的set,去重且排序

3. redis的过期策略有哪些?淘汰机制呢?LRU了解吗?

过期策略就是:定期删除+惰性删除
1、定期删除就是redis默认每隔100ms随机抽取一些过期时间的key,删除过期的key(redis不是查找所有的key进行检查)
2、 惰性删除就是当访问一个key时,如果发现key过期了,就删除这个key

这样总会有漏网之鱼,怎么办?内存淘汰机制!
淘汰机制有以下几个:
1、allkeys-lru:全局最近最少使用
2、allkeys-ttl:全局过期时间最短的
3、allkeys-random:全局随机选择
4、volatile-ttl:过期时间最短的
5、volatile-random:随机选择
6、volatile-lru:最近最少使用

手写LRU算法:
第一种:使用哈希表+双向链表实现LRU缓存(复杂)
第二种:JDk底层自己实现的LRU缓存(简单)
实例:

/** * 继承 LinkedHashMap 快速实现 LRU Cache * @param <K> key * @param <V> value */publicclassLRUCacheLinkedHashMap<K,V>extendsLinkedHashMap<K,V>{// 缓存最大容量privatefinalintmaxCapacity;/** * 构造器开启访问顺序排序 * @param capacity 缓存容量 */publicLRUCacheLinkedHashMap(intcapacity){// initialCapacity: 初始容量,loadFactor: 负载因子,accessOrder=true 开启LRU访问排序super(capacity,0.75f,true);this.maxCapacity=capacity;}/** * 钩子方法:put 执行完毕后回调 * 返回 true → 删除最久未使用的元素(链表头部) */@OverrideprotectedbooleanremoveEldestEntry(Map.Entry<K,V>eldest){// 当前元素个数超过最大容量则淘汰returnsize()>maxCapacity;}// 测试入口publicstaticvoidmain(String[]args){// 缓存容量为3LRUCacheLinkedHashMap<Integer,String>lru=newLRUCacheLinkedHashMap<>(3);lru.put(1,"一号数据");lru.put(2,"二号数据");lru.put(3,"三号数据");System.out.println("存入1,2,3:"+lru);// 新增第4个,超出容量,淘汰最久未使用的1lru.put(4,"四号数据");System.out.println("存入4,淘汰1:"+lru);// 访问key=2,2变为最新元素,移到末尾lru.get(2);System.out.println("访问2之后:"+lru);// 新增5,此时最久未使用是3,淘汰3lru.put(5,"五号数据");System.out.println("存入5,淘汰3:"+lru);// 更新key=4的值,4变为最新lru.put(4,"四号更新");System.out.println("更新4之后:"+lru);}}

4. 什么是 Redis 的雪崩、穿透和击穿问题?

**雪崩:**大量key同时过期失效或者redis服务挂了,大量请求直接打到数据库,导致数据库压力很大,甚至崩溃

解决:
事前:主从复制➕哨兵模式
事中:本地缓存➕服务层限流、降级
事后:持久化数据,避免数据丢失

**穿透:**查询数据库中根本不存在的数据,绕过缓存,直接查询数据库,比如传-1或者空值

解决:
1、缓存空值,数据库查询为空时,让redis写入key:null,设置过期时间为5分钟
2、使用布隆过滤器

**击穿:**缓存中有超高并发热点key刚刚好过期

解决:
1、使用互斥锁,确保只有一个线程查询数据库
2、使用缓存预热,提前查询数据库,将数据缓存起来,避免直接查询数据库
3、设置永不过期

5. Redis 的持久化有哪几种方式?

**RDB:**快照持久化,按照时间点快照,把当前内存中全部数据一次性保存到磁盘二进制文件中。
1、自动触发:

#900秒至少1次修改、300秒至少10次、60秒至少10000次修改,自动bgsave save9001save30010save6010000

2、手动触发:fork子进程,子进程写RDB,父进程继续处理请求。

**AOF:**记录每一条修改命令(set/hset/del等),追加写入.aof 文本文件,重启时重放命令恢复数据。
默认关闭,开启配置:

appendonly yes appendfilename"append.aof"

AOF 重写机制:
AOF 持续追加会文件越来越大,重写:
fork 子进程,读取当前内存数据,生成精简命令替换旧 AOF,删除冗余操作。
触发条件配置:

文件比上次重写后增大100%且超过64MB自动重写。 auto-aof-rewrite-percentage100auto-aof-rewrite-min-size64mb

6. 如何保证redis的高可用和高并发呢?

高并发:
1、主从复制
一主多从,主负责写,并且将数据复制到其它的 slave 节点,所有的读请求全部走从节点。

原理及流程:全量复制➕增量复制
(1)从节点发起连接,握手认证,发送replconf配置
(2)发送PSYNC命令(核心):PSYNC
runid:主节点唯一运行ID,每次重启变更
offset:复制偏移量,记录从节点上次复制到的偏移量,用于断线重连
2种情况:
1、首次链接/runid不匹配:主节点执行全量复制
2、断线重连/runid一致、offset在主节点复制积压缓冲区:增量复制
(3)主节点执行全量复制:生成一份RDB持久化文件,同时写入所有命令,存入复制积压缓冲区,生成完毕,通过socket发送给从节点
(4)从节点接收RDB文件,加载数据,同时从主节点订阅写命令,持续增量同步

无磁盘复制:
主节点在内存中直接创建RDB ,然后发送给从节点,不会在自己本地落地磁盘了。只需要在配置文件中开启 repl-diskless-sync yes 即可。

过期key处理:
slave 不会过期key,只会等待 master 过期key。如果 master 过期了一个key,或者通过 LRU 淘汰了一个key,那么会模拟一条 del 命令发送给 slave。

高可用:
1、使用哨兵模式
哨兵:sentinel是 Redis 集群架构中非常重要的一个组件,主要有以下功能:
集群监控:负责监控 Redis master 和 slave 进程是否正常工作。
消息通知:如果某个 Redis 实例有故障,那么哨兵负责发送消息作为报警通知给管理员。
故障转移:如果 master node 挂掉了,会自动转移到 slave node 上。
配置中心:如果故障转移发生了,通知 client 客户端新的 master 地址。

此模式导致数据丢失的情况:
**1、异步复制导致:**主从复制是异步的,有部分数据还没复制到从节点,主节点就宕机了
**2、脑裂导致:**主节点突然脱离了正常的网络,和其他从节点不连接,但是自己还运行着,此时哨兵认为你已经挂了,会选举新的主节点,集群里就会有两个主节点,这就是脑裂。
此时某个从节点被选择为了主节点,但是client还没来及切换,还在往旧的主节点写数据。因此就主节点再次恢复的时候,会被认为是新的从节点从主节点同步数据,但是新的主节点
并没有client写入的数据,所以就丢失了。
解决方法:

至少有1个 slave,数据复制和同步的延迟不能超过10秒 min-slaves-to-write1min-slaves-max-lag10

如何保证缓存与数据库的双写一致性?

场景1:读多写少、允许短暂不一致(90% 普通业务)
标准实现:延迟双删 + 过期兜底
更新数据库;
删除缓存;
异步延迟 N ms 再次删除缓存;
缓存统一设置过期时间,兜底最终一致。

// 1. 更新数据库updateDb(entity);// 2. 立即删缓存redis.del(key);// 3. 异步延迟删除threadPool.execute(()->{Thread.sleep(500);redis.del(key);});

场景2:强一致性要求(金融、订单、库存,不允许脏数据)
分布式锁(串行化读写)
写流程:加锁 → 更新 DB → 删除缓存 → 释放锁
读流程:加锁 → 查询缓存,无则查 DB 写入缓存 → 释放锁

11. 写在最后

喜欢的点赞、收藏、转发呀!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/30 4:18:47

2026 DApp 开发新趋势:去中心化应用如何重构实体商业新模式

引言移动互联网时代&#xff0c;微信、电商、短视频等中心化 App 掌控流量、数据、收益分配权&#xff0c;平台抽取高额佣金、随意调整规则、用户数据被集中存储&#xff0c;创作者、中小商家、普通消费者长期处于被动地位。而 DApp 去中心化应用&#xff0c;依托区块链智能合约…

作者头像 李华
网站建设 2026/6/30 4:17:55

PVE 重装系统后:硬盘挂载与存储分配完全指南

在 Proxmox VE (PVE) 9.2.2重新安装系统后&#xff0c;原有的数据盘&#xff08;机械硬盘&#xff09;通常不会被自动挂载&#xff0c;且存储池的“内容分配”需要重新规划。本文将以最简明的步骤&#xff0c;带你完成硬盘挂载与存储内容分配。第一步&#xff1a;确认硬盘状态 …

作者头像 李华
网站建设 2026/6/30 4:16:52

PLC移位与循环指令:从基础原理到高效编程实践

1. 移位与循环指令的本质&#xff1a;数据流动的艺术 第一次接触PLC移位指令时&#xff0c;我盯着那个闪烁的流水线指示灯发了半小时呆——为什么简单的"移动数据"就能实现如此复杂的控制逻辑&#xff1f;后来才明白&#xff0c;移位操作本质上是对数据流动路径的精确…

作者头像 李华
网站建设 2026/6/30 4:15:29

Anthropic语义压缩层消失:大模型中间态可控性终结

1. 项目概述&#xff1a;这不是一次普通更新&#xff0c;而是一次架构级“蒸发” “Anthropic Just Shipped the Layer That’s Already Going to Zero”——这个标题一出现&#xff0c;我在 Slack 群里就看到三位同行同时发了同一个表情&#xff1a;一个倒计时归零的数字“0”…

作者头像 李华
网站建设 2026/6/30 4:13:21

DNA折纸纳米结构包载脂质体的实验与优化方向

名称&#xff1a;DNA折纸纳米结构包载脂质体 一、研究背景与思路概述 近年来&#xff0c;纳米尺度的结构设计在生物材料与递送体系领域中受到广泛关注。DNA折纸技术作为一种可编程的自组装方法&#xff0c;能够通过碱基互补配对原理&#xff0c;将单链DNA折叠成预设的二维或三维…

作者头像 李华