一、Redis与MySQL数据同步及一致性保障
(一)核心同步流程:数据库优先+消息队列解耦
- 更新优先级:所有数据更新优先写入MySQL,确保数据持久化(数据库为最终可信来源);
- 通知机制:MySQL更新成功后,通过RabbitMQ/Kafka发送缓存更新通知(携带数据ID、更新类型),替代Redis Pub/Sub(无持久化、重试机制,易丢消息);
- 缓存更新:Redis订阅节点收到通知后,从MySQL拉取最新完整数据更新缓存(避免通知数据篡改/不完整导致脏缓存);
- 降级兜底:消息队列不可用时,启动本地重试+定时补偿任务,确保缓存最终一致。
(二)一致性保障策略(分场景适配)
| 场景 |
核心方案 |
适用场景 |
优缺点 |
| 弱一致性 |
更新数据库→删除缓存;设置合理TTL(5-15分钟),依赖过期机制最终一致 |
非核心数据(商品浏览量) |
实现成本低、性能影响小,短时间可能不一致 |
| 强一致性 |
1. 核心流程:先删缓存→更新数据库→延迟双删(100-500ms); 2. 原子性:Seata TCC封装分布式事务; 3. 兜底:定时对账(ID分片对比)+ 并发控制(行锁/乐观锁) |
核心数据(订单、余额) |
实时一致,实现成本稍高 |
二、Go数组与切片核心区别
(一)底层本质
- 数组 :值类型,连续内存块,仅存储元素,声明时需指定固定长度(如
[5]int);
- 切片 :引用类型(
SliceHeader),包含3个字段:ptr(指向底层数组)、len(可用元素数)、cap(底层数组容量),仅为数组"视图"。
(二)核心特性对比
| 特性 |
数组 |
切片 |
| 长度特性 |
固定长度,长度是类型一部分([3]int与[5]int为不同类型) |
动态长度,len()随append/cut变化,长度非类型一部分 |
| 扩容机制 |
无扩容能力,需手动创建新数组并拷贝 |
自动扩容:<256倍扩容,≥256按1.25倍扩容,生成新底层数组 |
| 传参特性 |
值传递,拷贝整个数组,效率低 |
引用传递,仅拷贝3个元数据字段(24字节),函数内修改影响原切片 |
| 初始化方式 |
需指定长度([3]int{1,2,3}),支持[...]int{1,2}自动推导 |
无需指定长度(make([]int,3,5)),空切片/ nil切片均可调用len/cap |
三、Goroutine导致CPU占用过高排查(6步闭环)
- 定位进程/线程 :
top -P找高CPU Go进程PID;top -Hp PID判断单线程(死循环)/多线程(并发过载);
- 开启pprof :导入
_ "net/http/pprof",启动HTTP端口(如6060);
- 采集数据
go tool pprof -seconds 10 http://<IP>:6060/debug/pprof/profile(CPU采样);
curl http://<IP>:6060/debug/pprof/goroutine?debug=2 -o goroutine.log(协程栈);
- 定位高CPU函数 :pprof交互界面
top看flat%最高函数,list 函数名定位代码行;
- 验证根因
- 无退出条件循环→死循环;
- 高频编解码/计算→密集计算;
- 大量runnable协程→并发过载;
- 修复+验证
- 修复:死循环加超时、密集计算加缓存、协程池限流;
- 验证:
top看CPU回落,重新采集pprof确认。
四、RESTful API设计规范
(一)核心规范
| 维度 |
设计规则 |
| 资源命名 |
名词复数(/users),禁用动词;子资源嵌套(/users/123/orders) |
| HTTP方法 |
GET(查询,幂等)、POST(创建,非幂等)、PUT(全量更新,幂等)、PATCH(部分更新,幂等)、DELETE(删除,幂等) |
| 状态码 |
2xx(成功:200/201/204)、4xx(客户端错:400/401/403/404/409)、5xx(服务端错:500/503) |
| 版本控制 |
方案1:URL嵌入(/v1/users,推荐);方案2:请求头(Accept: application/vnd.xxx.v1+json) |
| 过滤分页排序 |
分页:/users?page=1&size=10;过滤:/users?role=admin;排序:/users?sort=createTime,desc |
(二)实操补充
- 返回格式统一(JSON:
code/message/data);
- 避免状态依赖,请求独立;
- 资源粒度适中,GET请求设置
Cache-Control缓存。
五、HTTPS原理
(一)核心设计思路:混合加密
| 加密方式 |
特点 |
用途 |
| 对称加密 |
速度快,密钥易泄露 |
加密传输HTTP数据 |
| 非对称加密 |
速度慢,公钥加密/私钥解密 |
安全传输对称加密的会话密钥 |
(二)关键阶段
- TLS握手(协商会话密钥)
- 客户端:发送加密套件+客户端随机数;
- 服务端:返回加密套件+服务端随机数+数字证书(含公钥);
- 客户端:验证证书合法性,生成预主密钥并通过服务端公钥加密发送;
- 双方:基于3个随机数生成会话密钥;
- 确认:用会话密钥加密"握手完成"通知,验证密钥有效性;
- 数据传输
- 加密:会话密钥对称加密HTTP数据;
- 验完整性:SHA-256生成消息摘要,校验数据是否篡改;
- 验身份:基于数字证书确认对方合法性。
六、数据库事务三大隔离性问题
(一)核心定义与场景
| 问题 |
核心定义 |
典型场景 |
触发隔离级别 |
| 脏读 |
事务A读取事务B未提交的修改,B回滚后A读的是脏数据 |
B更新余额至200(未提交)→A读200→B回滚→A基于200转账 |
仅读未提交 |
| 不可重复读 |
事务A同一事务内两次查同一行,B修改并提交,导致内容不一致 |
A第一次读余额100→B更新为200并提交→A第二次读200 |
读未提交、读已提交 |
| 幻读 |
事务A同一事务内两次查同一范围,B插入/删除数据,导致行数不一致 |
A查余额>100的用户(2条)→B插入1条→A再次查(3条) |
读未提交、读已提交、可重复读 |
(二)解决方式
| 隔离级别 |
脏读 |
不可重复读 |
幻读 |
并发性能 |
| 读未提交 |
允许 |
允许 |
允许 |
最高 |
| 读已提交 |
避免 |
允许 |
允许 |
较高 |
| 可重复读 |
避免 |
避免 |
缓解 |
中等 |
| 串行化 |
避免 |
避免 |
避免 |
最低 |
七、Redis ZSet选择跳表的原因
| 维度 |
跳表优势 |
红黑树劣势 |
| 实现复杂度 |
逻辑简单,仅需指针调整,维护成本低 |
需维护颜色/平衡因子,旋转逻辑复杂 |
| 查询性能 |
O(logN),与红黑树相当 |
O(logN),但实现复杂 |
| 范围查询 |
定位边界后沿底层链表遍历,高效适配ZRANGE/ZREVRANGE |
需中序遍历,效率低 |
| 并发友好性 |
更新仅涉及局部节点,锁粒度小 |
旋转调整涉及多节点,锁粒度大 |
八、跳表核心操作(插入/删除/修改)
(一)前置特性
跳表为多层有序链表:Level 0是完整链表,上层为稀疏索引;节点含"值/分数+数据+各层后继指针";层高随机生成(50%概率停止增长);操作核心是"从最高层向下遍历定位"。
(二)核心操作
| 操作 |
核心步骤 |
时间复杂度 |
关键注意点 |
| 插入 |
1. 定位各层前驱(update数组); 2. 校验重复; 3. 随机生成层高; 4. 插入节点并更新指针 |
O(logN) |
层高随机保证稀疏性,避免溢出 |
| 删除 |
1. 定位前驱; 2. 校验节点存在; 3. 跳过待删节点; 4. 清理空索引层 |
O(logN) |
清理空层提升后续查询效率 |
| 修改 |
1. 高效方式:直接定位修改(仅改数据,不改排序键); 2. 兼容方式:删除旧节点+插入新节点(改排序键) |
O(logN) |
排序键变更必须用删除重插 |
九、数据库事务原理
(一)核心特性(ACID)
- 原子性:事务内操作是整体,要么全成功,要么全回滚,无中间状态(如转账的扣款和收款)。
- 一致性:事务前后数据从合法状态切换到另一合法状态,业务约束不被破坏(如转账总金额不变)。
- 隔离性:多事务并发执行互不干扰,隔离级别决定干扰程度。
- 持久性:事务提交后修改永久生效,数据库崩溃重启后数据不丢失。
(二)ACID底层实现原理
- 原子性+持久性:redo log + undo log
- undo log(回滚日志)
- 生成时机:执行
INSERT/UPDATE/DELETE时,记录反向操作(如UPDATE存改前值)。
- 作用:事务失败时反向恢复数据;为MVCC提供多版本数据。
- 生命周期:提交后暂存用于MVCC,后续由后台线程清理。
- redo log(重做日志)
- 核心问题:解决"内存修改未刷盘"的崩溃丢失问题。
- 生成时机:先写数据页物理变化到redo log缓冲区,再修改内存数据。
- 刷盘机制:WAL策略,事务提交时强制刷盘;重启时重放恢复数据。
- 底层特点:物理日志、固定大小、循环写入。
- 隔离性:锁机制 + MVCC
- 锁机制(解决写冲突)
- 锁粒度:行锁(InnoDB默认)、表锁、页锁。
- 锁类型:共享锁(S锁,读)、排他锁(X锁,写);意向锁(IS/IX)快速判断表内行锁状态。
- MVCC(多版本并发控制,解决读冲突)
- 核心目标:读不阻塞写、写不阻塞读。
- 实现原理:每行含
trx_id(修改事务ID)、roll_ptr(指向undo log历史版本)。
- 工作逻辑:事务根据隔离级别,通过可见性规则选择历史版本(如RR级事务启动时生成快照)。
- 一致性:由原子性、隔离性、持久性共同支撑,辅以主键/外键约束、业务规则校验。
(三)高频追问
-
redo log vs binlog
| 对比维度 |
redo log |
binlog |
| 归属层 |
InnoDB存储引擎层 |
MySQL服务层 |
| 日志格式 |
物理日志(数据页变化) |
逻辑日志(SQL执行逻辑) |
| 写入方式 |
循环写 |
追加写 |
| 用途 |
崩溃恢复 |
主从复制、数据备份 |
| 一致性保障 |
两阶段提交(prepare写redo log,commit写binlog) |
- |
-
事务回滚流程
- 触发回滚(执行
ROLLBACK或事务出错);
- 读取undo log执行反向操作(如
UPDATE回滚原值);
- 释放事务持有的锁;
- 清理或标记undo log为可清理。
十、索引优化的使用场景
(一)核心原则
在"查询效率"与"写入性能"间平衡:索引加速读,但增加写开销,适合读多写少、查询耗时高的场景。
(二)核心优化场景
| 场景类型 |
业务场景 |
优化策略 |
核心逻辑 |
| 高频单表查询 |
高频过滤(WHERE user_id=?)、过滤+排序(WHERE status=1 ORDER BY create_time) |
单列索引(idx_user_id)、复合索引(idx_status_create_time) |
复合索引覆盖过滤+排序,避免回表+文件排序 |
| 多表JOIN |
订单JOIN用户(order.user_id = user.id) |
关联字段建索引;小表驱动大表 |
快速匹配关联行,减少笛卡尔积计算 |
| 大数据量分页/范围查询 |
百万级表分页(LIMIT 100000,10)、范围筛选(BETWEEN) |
范围字段建索引;用WHERE id>100000 LIMIT 10替代大OFFSET |
利用索引有序性跳过大量数据,减少IO |
| 覆盖索引 |
查询字段少(SELECT id FROM user WHERE phone=?) |
建包含查询字段的索引(idx_phone (phone)) |
无需回表,直接从二级索引返回结果 |
| 高/低基数字段 |
高基数(手机号)、低基数(status) |
高基数单独建索引;低基数建复合索引(status+create_time) |
高基数索引选择性高;低基数组合提升过滤性 |
| 排序/分组 |
ORDER BY/GROUP BY触发文件排序 |
建与排序/分组字段顺序一致的复合索引 |
利用索引有序性避免额外排序 |
(三)不适合建索引的场景
- 写多读少表(如日志表);
- 数据量极小表(如配置表);
- 低基数无复合场景字段(如gender);
- 频繁更新字段(如库存)。
十一、索引失效的场景
(一)核心逻辑
数据库优化器认为"用索引成本高于全表扫描",或无法利用索引的有序性/选择性。
(二)核心失效场景及解决方案
| 失效场景 |
示例 |
原因分析 |
解决方案 |
| 索引字段参与函数/运算 |
WHERE SUBSTR(phone,1,3)='138' |
函数/运算破坏索引有序性 |
函数移到条件右侧;MySQL 8.0+建函数索引 |
| %开头的模糊查询 |
WHERE name LIKE '%张三' |
无法确定索引起始位置 |
反转存储+前缀索引;使用全文索引 |
| 违反最左匹配原则 |
复合索引idx_a_b_c,查询WHERE b=1 AND c=2 |
跳过最左字段,破坏索引有序性 |
复合索引按查询频率排序字段;查询含最左字段 |
| OR连接非索引字段 |
WHERE phone='138' OR age=20(age无索引) |
OR需全表验证无索引字段 |
OR字段全建索引;用UNION替代OR |
| 隐式类型转换 |
WHERE phone=13800000000(phone为VARCHAR) |
隐式转换等价于函数操作 |
条件值类型与字段一致 |
| 否定操作(NOT IN/<>) |
WHERE id NOT IN (1,2,3) |
过滤性差,优化器选全表扫描 |
用LEFT JOIN + IS NULL替代;先筛主键再关联 |
| 优化器认为索引成本高 |
WHERE status=1(占表50%) |
回表成本高于全表扫描 |
增加过滤维度;建覆盖索引;谨慎使用强制索引 |
| 索引字段为NULL |
WHERE email IS NULL |
索引存储NULL效率低 |
字段设为NOT NULL(默认空字符串) |
(三)排查方法
EXPLAIN看type=ALL/key=NULL;
ANALYZE TABLE更新统计信息;
- 强制索引验证(
FORCE INDEX)。
十二、Go与Java的区别(深问)
| 对比维度 |
Go语言 |
Java语言 |
| 设计理念 |
极简实用(25个关键字),移除继承/异常,优先开发效率+性能 |
全面工程化,面向对象+丰富抽象层,支撑大规模企业应用 |
| 并发模型 |
Goroutine(初始栈2KB,用户态轻量级线程),GPM调度,Channel通信无锁竞争 |
线程池(系统线程,栈1MB),内核调度,共享内存+锁,锁竞争影响性能 |
| 内存管理 |
三色标记+混合写屏障GC,停顿ms级;TCMalloc分配,无手动管理/析构函数 |
分代收集GC(G1/ZGC),高并发需调优,易秒级停顿;TLAB分配,有finalize()(不推荐) |
| 编译与运行 |
静态编译,单二进制文件,启动毫秒级,支持交叉编译 |
编译为字节码,依赖JVM,启动秒级,需安装JRE |
| 生态场景 |
云原生(Docker/K8s)、高并发后端、边缘计算 |
企业应用、大数据、Android开发 |
十三、MySQL主从复制
(一)核心作用
- 读写分离:主库写,从库读,分流查询压力;
- 数据备份:从库为实时热备份,备份不影响主库;
- 高可用容灾:主库故障切换到从库,支持跨机房部署。
(二)底层原理(核心三步骤)
- 主库记录binlog:主库执行写入操作后,将操作逻辑记录到binlog(核心载体);
- 从库IO线程拉取binlog:从库IO线程连接主库,主库dump线程发送binlog,从库写入中继日志(relay log);
- 从库SQL线程重放日志:SQL线程读取中继日志,按顺序重放SQL,同步数据。
(三)复制模式
| 复制模式 |
核心逻辑 |
优点 |
缺点 |
适用场景 |
| 异步复制 |
主库写binlog后直接返回,无需等待从库 |
性能最好 |
主库宕机可能丢数据 |
非核心数据(日志收集) |
| 半同步复制 |
主库等待至少一个从库IO线程写入中继日志后返回 |
数据安全性高 |
主库有轻微延迟,性能略降 |
核心数据(金融、支付) |
| GTID复制 |
事务分配全局唯一ID,从库按GTID定位同步位置 |
部署维护简单,支持并行复制 |
不兼容MySQL 5.6以下版本 |
企业级分布式架构 |
(四)常见问题及解决方案
- 主从延迟
- 原因:大事务、从库SQL单线程、从库查询压力大;
- 解决:拆分大事务、开启并行复制、读写分离优先选低延迟从库、优化从库索引。
- 数据不一致
- 原因:复制中断、从库人为写入、主从配置不一致;
- 解决:pt-table-checksum校验、pt-table-sync修复、从库设为只读、主从配置统一。
十四、B+树(MySQL索引底层)
(一)结构特点
多路平衡树,核心特性如下:
- 非叶子节点:仅存索引键,用于导航;
- 叶子节点:存索引键+数据,双向链表连接;
- 所有叶子节点同层,查询时间复杂度O(logN)。
(二)B树vs B+树
| 特性 |
B树 |
B+树 |
| 节点内容 |
非叶子/叶子节点均存键+数据 |
非叶子存键,叶子存键+数据 |
| 范围查询 |
中序遍历,效率低 |
叶子链表遍历,效率高 |
| 磁盘IO |
节点体积大,IO次数多 |
节点体积小,IO次数少 |
| 排序支持 |
不天然支持 |
叶子有序,天然支持 |
(三)为何适合数据库
- 减少IO :非叶子节点存更多键,树高仅34层,查询最多34次IO;
- 高效范围查询 :叶子双向链表适配
BETWEEN、ORDER BY等场景。
十五、聚簇索引vs非聚簇索引
| 对比维度 |
聚簇索引 |
非聚簇索引(二级索引) |
| 存储结构 |
索引键+整行数据(叶子节点),索引即数据 |
索引键+聚簇索引键(叶子节点),索引与数据分离 |
| 数量限制 |
一张表仅1个 |
一张表可多个 |
| 默认规则 |
InnoDB中主键为聚簇索引;无主键选非空唯一索引;无则生成隐藏row_id |
手动创建(普通索引、联合索引等) |
| 查询效率 |
主键精准查询无需回表,效率极高 |
常规查询需回表;覆盖索引场景无需回表 |
| 数据存储关系 |
数据按聚簇索引顺序存储 |
索引独立于数据存储,不影响数据顺序 |
| 适用场景 |
主键精准查询、主键范围查询 |
非主键字段查询(手机号、创建时间) |
十六、Session建立机制
(一)核心设计思路
状态存服务端,标识传客户端,解决HTTP无状态问题:
- 状态存储:用户登录信息、购物车数据等存服务端(内存/Redis/数据库);
- 关联标识:服务端生成唯一Session ID,绑定会话状态;
- 标识传递:默认通过Cookie传递Session ID。
(二)完整流程
- 客户端首次请求:无Session ID,服务端判定为新会话;
- 服务端生成Session与Session ID:创建会话对象,生成唯一ID,存储"ID-会话"映射;
- 服务端返回Session ID:写入Cookie(默认JSESSIONID),随响应返回客户端;
- 客户端后续请求:携带Cookie中的Session ID,服务端通过ID查询会话状态,维持会话。
(三)关键注意事项
- Cookie禁用解决方案:URL重写(Session ID拼接到URL后),存在安全风险,推荐引导开启Cookie;
- 有效期与销毁:默认30分钟过期,用户退出时主动销毁Session并删除Cookie;
- 分布式共享:Session集中存储到Redis,解决多服务器Session不一致问题。
十七、HTTP 304与协商缓存
(一)核心关联
304 Not Modified是协商缓存命中的响应状态码,核心目标是减少重复资源传输,提升加载速度。
(二)完整流程
- 首次请求
- 客户端发送请求,无缓存标识;
- 服务端返回200 OK,携带资源+协商缓存标识(
Last-Modified/ETag);
- 客户端存储资源与缓存标识。
- 再次请求
- 客户端携带缓存标识(
If-Modified-Since对应Last-Modified;If-None-Match对应ETag);
- 服务端对比标识:
- 资源未修改:返回304 Not Modified,无响应体;
- 资源已修改:返回200 OK,携带新资源+新标识。
(三)核心字段对比
| 字段组合 |
核心逻辑 |
优势 |
局限性 |
| Last-Modified + If-Modified-Since |
基于资源修改时间判断 |
实现简单,无需计算资源内容 |
1. 精度低(秒级);2. 内容未变可能误判;3. 部分服务器无法获取准确修改时间 |
| ETag + If-None-Match |
基于资源内容哈希判断 |
精度高,内容不变则标识不变 |
1. 服务端计算哈希有性能开销;2. 不同服务器算法可能不同 |
(四)与强缓存的区别
| 对比维度 |
协商缓存(304) |
强缓存(Cache-Control/Expires) |
| 服务端交互 |
必须发送请求,与服务端校验 |
无需发送请求,客户端本地判断 |
| 状态码 |
304 Not Modified |
200 OK(from cache) |
| 触发时机 |
强缓存未命中时触发 |
优先触发 |
十八、HTTP报文结构
(一)请求报文
核心:客户端向服务端发指令的载体,结构如下:
- 请求行(必选) :
请求方法 + 请求路径 + 协议版本(如GET /index.html HTTP/1.1);
- 请求头(可选) :键值对格式(如
Host: www.example.com、Content-Type: application/json);
- 空行(必选):分隔请求头与请求体;
- 请求体(可选):POST/PUT请求的参数数据(如JSON、表单数据),GET请求无请求体。
(二)响应报文
核心:服务端向客户端返回结果的载体,结构如下:
- 状态行(必选) :
协议版本 + 状态码 + 状态描述(如HTTP/1.1 200 OK);
- 响应头(可选) :键值对格式(如
Content-Type: text/html、Set-Cookie: JSESSIONID=xxx);
- 空行(必选):分隔响应头与响应体;
- 响应体(可选):返回的资源数据(如HTML、JSON、图片二进制数据)。
十九、MySQL大表问题
(一)性能层面问题
- 索引效率下降:B+树层级增高(4-5层),IO次数增加;索引维护成本高,写入时节点分裂/合并耗时久;
- 查询退化 :全表扫描开销剧增;
ORDER BY/GROUP BY易触发临时表/文件排序;
- 写入瓶颈:锁竞争加剧(热点行更新阻塞);binlog量大导致主从同步延迟。
(二)运维层面问题
- 备份/恢复久:千万级表备份需数小时,占用大量IO/CPU资源;
- DDL风险大:低版本锁表导致业务中断;高版本Online DDL仍有IO开销,易引发主从延迟;
- 扩容复杂:分库分表需迁移历史数据,需保证数据一致性和业务无感知。
(三)可用性层面问题
- 单点故障影响广:大表存核心数据,实例宕机导致核心业务中断;
- 资源隔离差:占用大量CPU/IO资源,牵连同实例其他业务,引发连锁故障。
(四)优化思路
- 事前预防:分库分表(哈希/时间分片);冷热数据分离(归档历史数据);
- 事后优化 :精简索引,建立覆盖索引;拆分复杂查询;低峰期执行DDL;使用
gh-ost/pt-online-schema-change工具。
二十、1w vs 1000w表插入成本对比
1000w表插入成本远高于1w表,核心差异如下:
- 索引维护成本:1000w表B+树高4层,多索引需维护多个树,节点分裂/合并次数倍增;1w表树高2层,维护开销低;
- 磁盘IO开销:1000w表数据无法全缓存,插入触发物理IO;数据碎片多,分配存储空间耗时久;1w表可缓存,IO开销小;
- 锁竞争与日志开销:1000w表写并发高,锁等待时间长;binlog/redo log刷盘IO竞争加剧;1w表锁竞争和日志开销可忽略。
二十一、MySQL间隙锁
(一)定义
InnoDB 可重复读(RR) 级别下的行锁变种,锁定"索引记录之间的间隙",防止插入数据,解决幻读问题。
(二)核心作用
阻止其他事务在当前事务查询范围内的间隙中插入数据,从根本上避免幻读(如WHERE id BETWEEN 10 AND 20,锁定10-20之间的间隙)。
(三)触发场景
- 范围查询加锁 :
WHERE id BETWEEN 10 AND 20 FOR UPDATE,锁行+间隙(Next-Key锁);
- 等值查询无匹配 :
WHERE id=15 FOR UPDATE(id=15不存在),锁定15所在的间隙;
- 默认Next-Key锁:InnoDB RR级别下,行锁默认升级为Next-Key锁(行锁+间隙锁)。
二十二、Redis过期删除策略
(一)过期标识
键的过期时间存储在过期字典中,键过期后不会立即删除。
(二)核心删除策略
- 惰性删除
- 逻辑:访问键时检查是否过期,过期则删除;
- 优点:CPU友好,仅在访问时处理;
- 缺点:内存泄漏风险(过期键长期不访问)。
- 定期删除
- 逻辑:每100ms随机抽取过期键,删除过期的;删除比例超25%则继续抽取;
- 优点:平衡CPU与内存开销;
- 缺点:部分过期键无法及时删除。
- 主动删除(AOF/RDB触发)
- RDB:生成快照时不写入过期键;
- AOF:删除过期键时追加
DEL命令到AOF文件;
- 主从:主库删除过期键后,同步
DEL命令给从库。
(三)内存淘汰机制(maxmemory触发)
| 淘汰策略 |
适用场景 |
| volatile-lru |
过期键中删除最少使用的 |
| allkeys-lru |
所有键中删除最少使用的 |
| volatile-ttl |
过期键中删除TTL最短的 |
| noeviction |
不删除键,拒绝写入(默认) |
(四)组合策略
日常清理依赖 惰性删除+定期删除 ,内存达到阈值时触发内存淘汰机制兜底。