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) 裁剪,实现一个固定容量的排行榜。

相关推荐
IT龟苓膏1 天前
Redis 数据类型底层原理:SDS、quicklist、intset、skiplist、Bitmap、HyperLogLog 一篇讲清
数据库·redis·skiplist
流星白龙1 天前
【MySQL高阶】19.变更缓冲区,自适应哈希索引,日志缓冲区
数据库·windows·mysql
晴天¥1 天前
Oracle中的监听配置与管理(动态、静态监听配置对比以及listener.ora和tnsnames.ora)
数据库·oracle
瀚高PG实验室1 天前
python连接HGDB超时
数据库·瀚高数据库·highgo
是烨笙啊1 天前
在 Claude code 中如何利用模型缓存节省 token
人工智能·缓存·ai编程
闪电悠米1 天前
黑马点评-Redisson-01_why_redisson
java·服务器·网络·数据库·缓存·wpf
Counter-Strike大牛1 天前
SpringBoot2.7.10+MyBatisPlus实现MySQL+DM双数据库切换
数据库·mysql
dllxhcjla1 天前
Redis
数据库·redis·缓存
睡不醒男孩0308231 天前
数据库高可用运维实操指南:基于CLup的PostgreSQL生产环境自动化管理
运维·数据库·postgresql
神仙别闹1 天前
基于Python + SQL server 实现(GUI)原神圣遗物管理与角色数值模拟系统
java·数据库·python