redis 大key使用 UNLINK 命令删除、Redis Set / ZSet 存储上限、ZRemRangeByRank命令

官方文档:https://redis.io/docs/latest/commands/unlink/

UNLINK 是 Redis 4.0 引入的异步删除 命令,语法与 DEL 一致:UNLINK key [key ...]

工作原理

  1. 主线程:仅将 key 从 keyspace(字典)中摘除,时间复杂度 O(1),立即返回。
  2. 后台 I/O 线程:异步释放实际内存。

这意味着 UNLINK 之后该 key 对其他客户端立刻不可见,但内存是延迟回收的。

核心差异:

对比 DEL UNLINK
删除方式 同步,主线程阻塞 异步,主线程仅解链接
内存回收 立即释放 后台 BIO 线程异步释放
大 Key 影响 严重阻塞 几乎无阻塞
返回值 被删除 Key 数量 被解链接 Key 数量

适用场景

实践上可以将 UNLINK 作为 DEL 的默认替代品几乎没有副作用,唯一注意点是内存不会立即释放------如果你的逻辑依赖"删完立刻能看到内存下降"(如监控告警),需要考虑这个延迟。

1. 删除大 key(最核心场景)

大 String(几十 MB)、大 Hash/Set/ZSet/List(几十万成员)用 DEL 会阻塞主线程几十甚至几百毫秒,严重影响其他请求。此时必须用 UNLINK

大 Key 删除优先 UNLINK------集合类型(Hash/List/Set/Sorted Set)尤其重要

2. 批量删除大量 key

bash 复制代码
UNLINK key1 key2 key3 ... key10000

避免一次性释放大量内存导致主线程卡顿。

3. 高并发、低延迟敏感的服务

对 P99/P999 延迟要求极高的场景,即使 key 不大,也建议统一用 UNLINK 替代 DEL,消除毛刺风险。

Redis Set / ZSet 存储上限

Redis 不对 collection 做数量限制,只受内存约束

生产环境必须为每个业务 key 设定 member 数量上限,否则:

  • 单个大 ZSET 的 ZADD/ZREM 时间复杂度 O(log N),N 过大时延迟飙升
  • DEL 一个百万级 ZSET 会阻塞 Redis 毫秒到秒级
  • RDB 持久化时大 key 导致 fork 耗时、AOF rewrite 卡顿
  • 主从同步全量同步时大 key 占满带宽

SET 大小建议:

  1. 单 Value 控制在 10 KB 以内------这是 Redis 官方推荐的安全阈值
  2. 超过 100 KB 需要评估------考虑压缩或拆分
  3. 超过 1 MB 必须优化------使用分片存储或更换数据结构

ZRemRangeByRank

Set 最大的坑是 SADD 无限增长却无感知,Set 没有排序,无法区分"哪些是旧的可以删",所以你没办法用一个简单命令裁掉多余部分。

Set 没有内置的容量上限机制------你可以查大小,但 Redis 不会主动阻止它增长,也没有原生命令能在写入时顺手淘汰旧数据。容量控制必须完全依赖业务代码自己去做,而且做起来很别扭

  • 想限制上限,得先 SCARD 判断,超了再手动 SREM------但 Set 无序,你不知道该删哪个
  • 没有"删最旧的一个"这种语义,只能 SRANDMEMBER 随机删,或者业务层自己维护一个删除队列

问题的本质不是"看不见大小",而是Set 缺乏淘汰语义 ,无法表达"按某种顺序淘汰最旧/最低优先级的元素"。而 ZSet 用 score 引入了排序,ZREMRANGEBYRANK 才有了明确的淘汰依据。

如果一个 Set 需要控制上限,直接用 ZSet 替代,score 存时间戳,就能复用窗口裁剪逻辑。

Set 是无序的,无法表达"哪个元素该被淘汰";换成 ZSet 用时间戳做 score,就有了淘汰依据,配合 ZREMRANGEBYRANK 可以在写入时顺手完成容量裁剪,从根本上避免大 key 问题。

ZREMRANGEBYRANK 是 Redis ZSet(有序集合)的命令,用于按排名范围删除元素

ZREMRANGEBYRANK key start stop

  • start / stop基于排名的索引 ,从 0 开始,按 score 从小到大排序
  • 支持负数索引,-1 表示最后一个元素
  • 范围是闭区间,即 start 和 stop 都包含在内
  • 返回值:被删除的元素数量

常见使用场景

场景 说明
排行榜裁剪 只保留 Top N,定期删除排名靠后的元素
限制 ZSet 大小 每次写入后执行 ZREMRANGEBYRANK key 0 -(N+1) 控制总量
滑动窗口清理 配合 score 为时间戳,删除过期数据(更推荐用 ZREMRANGEBYSCORE
消息队列清理 处理完的任务按优先级排名后批量移除

最常用的组合是 :写入时 ZADD,写入后立即 ZREMRANGEBYRANK key 0 -(N+1) 裁剪,实现一个固定容量的排行榜。

相关推荐
woxihuan1234561 小时前
c++怎么利用std--variant处理多种二进制子协议包的自动分支解析【进阶】
jvm·数据库·python
jran-1 小时前
MySQL 视图
数据库·mysql
无小道1 小时前
Mysql——用C语言链接数据库
数据库·mysql
Achou.Wang2 小时前
Selecting channels:Go 并发里的“多路开关”
服务器·数据库·golang
西洼工作室2 小时前
缓存工具类封装:内存与Redis无缝切换
redis·python·缓存·全栈
m0_609160492 小时前
Go语言Beego框架如何用_Go语言Beego框架入门教程【高效】
jvm·数据库·python
闵孚龙2 小时前
Claude Code 缓存优化模式全解析:AI Agent 上下文工程、Prompt Cache、工具 Schema 缓存、Token 成本优化
人工智能·缓存·prompt
未若君雅裁4 小时前
MySQL-MVCC核心原理-版本链ReadView与可见性判断
数据库·mysql
KaMeidebaby8 小时前
卡梅德生物技术快报|骆驼纳米抗体:从原核表达、高通量测序到分子对接全流程实现
前端·数据库·其他·百度·新浪微博