Redis LLEN 命令详细教程
LLEN 返回列表当前包含的元素个数,是列表类型唯一的"长度查询"命令。它自 Redis 1.0.0 起提供,复杂度恒为 O(1),无论列表里有一百个还是上亿个元素,耗时都一样------这是因为 Redis 在列表内部直接维护了长度计数器。它常用于监控队列积压、判断列表是否为空、以及在批量读取前预估数据量。
资料合集:https://pan.quark.cn/s/10e98d308913、https://pan.quark.cn/s/f56bc69c5338
一、概览与语法
redis
LLEN key
| 项目 | 说明 |
|---|---|
| 数据类型 | List |
| 支持版本 | Redis 1.0.0 起 |
| key | 目标列表 Key |
| 参数个数 | 仅一个 Key,不接受任何选项 |
| 返回值 | 整数,列表长度;Key 不存在时返回 0 |
| 时间复杂度 | O(1) |
| ACL | @read、@list、@fast |
| 命令标记 | readonly、fast |
官方说明:返回存储在 key 的列表的长度。如果 key 不存在,则将其视为空列表并返回 0;如果 key 中存储的值不是列表,则返回错误。$TRAE_REF
列表的最大长度为 2^32 - 1 个元素(超过 42 亿),因此 LLEN 的返回值范围是 0 到 2^32 - 1。
二、基础示例
以下命令在测试实例的 redis-cli 中执行。文中结果是预期说明,未实际连接 Redis 运行。
redis
DEL tutorial:{llen}:mylist
EXISTS tutorial:{llen}:mylist
LPUSH tutorial:{llen}:mylist "World"
LPUSH tutorial:{llen}:mylist "Hello"
LLEN tutorial:{llen}:mylist
DEL tutorial:{llen}:mylist
LLEN tutorial:{llen}:mylist
预期结果:DEL 返回 0(Key 原本不存在);EXISTS 返回 0;两次 LPUSH 分别返回 1、2;LLEN 返回 (integer) 2;DEL 返回 1;最后一条 LLEN 对已删除的 Key 返回 (integer) 0。
三、返回值与空结果
LLEN 的返回值语义简单而重要:它永远返回整数,不会返回空值。
| 情形 | 返回 |
|---|---|
| Key 存在且是列表 | 列表中的元素个数(正整数) |
| Key 不存在 | 0 |
| Key 是其他类型 | 报 WRONGTYPE(不返回 0) |
由此可以推出一个关键结论:LLEN 返回 0 等价于"该列表 Key 不存在"。因为 Redis 中的列表一旦被弹空,Key 会被立即删除,不存在"长度为 0 的空列表 Key"。这与 LRANGE 返回空数组的情形不同------LRANGE 无法区分"Key 不存在"和"区间没取到元素",而 LLEN 的 0 是确定的。
redis
DEL tutorial:{llen}:empty
LLEN tutorial:{llen}:empty
EXISTS tutorial:{llen}:empty
预期结果:第一条 DEL 返回 0;LLEN 返回 0;EXISTS 返回 0,二者互相印证:长度为 0 的列表就是不存在的列表。
四、边界情况与错误处理
| 场景 | 行为 |
|---|---|
| Key 不存在 | 返回 0,不报错、不创建 Key |
| Key 类型不是 List | 报 WRONGTYPE |
| 缺少 Key 参数 | 报语法错误 |
| 多余的参数 | 报 ERR wrong number of arguments for 'llen' command |
| Key 设置了 TTL 且未过期 | 正常返回长度,TTL 不受影响 |
redis
SET tutorial:{llen}:str text
LLEN tutorial:{llen}:str
LLEN
预期结果:SET 返回 OK;对 String 类型执行报 WRONGTYPE;不传 Key 报 ERR wrong number of arguments for 'llen' command。
五、与相近命令的区别
LLEN 属于 Redis 各数据类型的"长度/基数"命令家族,用法高度一致,只是作用对象不同:
| 命令 | 作用类型 | 返回 | 复杂度 |
|---|---|---|---|
| LLEN | List | 列表中的元素个数 | O(1) |
| STRLEN | String | 字符串的字节长度 | O(1) |
| HLEN | Hash | 哈希的字段个数 | O(1) |
| SCARD | Set | 集合的成员个数 | O(1) |
| ZCARD | Sorted Set | 有序集合的成员个数 | O(1) |
| XLEN | Stream | 流中的消息条数 | O(1) |
与列表内其他命令的区别:
| 命令 | 与 LLEN 的区别 |
|---|---|
| LRANGE | 返回元素内容而非个数,复杂度 O(S+N) |
| LPOS | 按值查找位置,复杂度 O(N) |
| EXISTS | 只判断 Key 是否存在,不关心类型是否为列表 |
| LLEN | 只返回长度,O(1),最轻量的列表信息查询 |
判断"列表是否为空"时,LLEN key == 0 与 EXISTS key == 0 在列表类型下等价,但 LLEN 兼具类型校验作用:若 Key 被别的类型占用,EXISTS 仍返回 1,而 LLEN 会直接报 WRONGTYPE,更利于发现类型污染。
六、客户端示例
前提为已安装 redis-py 并准备好本地测试实例。redis-py 的 llen(name) 返回整数。
python
import redis
r = redis.Redis(host="localhost", port=6379, decode_responses=True)
key = "tutorial:{llen}:py"
try:
r.delete(key)
print(r.llen(key)) # 0,Key 不存在
r.rpush(key, "a", "b", "c")
print(r.llen(key)) # 3
r.lpop(key)
print(r.llen(key)) # 2
r.delete(key)
print(r.llen(key)) # 0,弹空后再次确认
finally:
r.delete(key)
r.close()
Java(Jedis)示例,llen(key) 返回 long:
java
try (Jedis jedis = new Jedis("localhost", 6379)) {
String key = "tutorial:{llen}:java";
jedis.del(key);
System.out.println(jedis.llen(key)); // 0
jedis.rpush(key, "a", "b", "c");
System.out.println(jedis.llen(key)); // 3
jedis.lpop(key);
System.out.println(jedis.llen(key)); // 2
jedis.del(key);
}
七、原子性与事务
只读且原子:LLEN 不修改任何数据,单命令原子执行,返回的是某一时刻列表长度的精确快照。可在副本节点执行以分担读压力。
"先查长度再操作"需警惕竞态 :LLEN key 返回大于 0 后紧接着执行 LPOP,这两步之间其他消费者可能已经弹空了列表。因此不要用 if LLEN > 0 then LPOP 的写法当作安全保证。正确做法是:直接调用 LPOP 并处理空值返回,或使用 BLPOP/LMOVE 等原子命令,确有必要时用 Lua 脚本把判断与操作合并。LLEN 适合用于监控与统计,不适合作为并发控制的前置条件。
事务与 Pipeline:LLEN 可在 MULTI/EXEC、Lua 脚本与管道中正常使用;批量采集多个 Key 的长度时用管道一次性发出,减少往返。
八、性能与使用注意事项
恒为 O(1):这是 LLEN 最大的优势,也是最容易被误解的地方。很多人以为统计列表长度需要遍历,事实上 Redis 在列表对象里直接保存了长度字段,读取它不随元素增加而变慢。因此对超长列表频繁调用 LLEN 也不会成为性能瓶颈。
不产生副作用:不创建 Key、不改 TTL、不影响内容,可安全地高频调用。
注意返回值类型 :客户端拿到的是整数,做比较时避免与布尔值混用;if llen: 在 Python 中长度 0 为假,逻辑正确但可读性差,建议显式写 llen == 0。
九、典型业务场景
队列积压监控 :LLEN queue 是观察任务队列深度的标准手段。生产端 RPUSH、消费端 LPOP/BLPOP 时,定期采集队列长度即可绘制积压曲线,用于告警或自动扩缩容。
空列表短路:批量任务中先判断列表是否有数据,为空则跳过后续读取,避免无意义的 LRANGE 调用。
分页预估 :读取列表前用 LLEN 拿到总数,计算分页数或用 LRANGE 0 total-1 一次性拉取(注意大列表的风险)。
进度计算:把待处理项与已完成项分别放在两个列表,用两者的 LLEN 比值计算任务完成百分比。
缓存命中判断:空列表 Cache 场景中,用 LLEN 判断缓存是否已写入。
十、练习、排错与总结
练习:新建 tutorial:{llen}:ex,先执行 LLEN ex 确认返回 0 且 EXISTS 为 0;RPUSH 写入 5 个元素后确认 LLEN 返回 5;LPOP 两次后确认返回 3;把剩余元素全部 RPOP 弹空,再次 LLEN 确认返回 0 且 EXISTS 为 0;用 SET 把该 Key 改成 String 类型后执行 LLEN,确认报 WRONGTYPE。
排错要点:LLEN 返回 0 有两种可能------Key 不存在,或 Key 从未存在过(对列表而言二者等价),配合 EXISTS 即可确认;报 WRONGTYPE 说明 Key 被其他类型占用,用 TYPE 检查;若业务上出现"列表长度为 0 但 Key 还在"的预期,说明对 Redis 列表模型理解有误,空列表不会以 Key 形式存在;把 LLEN 当作并发安全的前置检查会引发竞态,应改用原子命令。清理使用 DEL tutorial:{llen}:mylist tutorial:{llen}:empty tutorial:{llen}:str tutorial:{llen}:py tutorial:{llen}:java tutorial:{llen}:ex。速记:1.0 起支持、返回列表长度、恒为 O(1)、Key 不存在返回 0 而非空值、返回 0 即表示列表 Key 不存在、不为空值说明永远可以安全取整数、只读不改数据可安全高频调用、与 STRLEN/HLEN/SCARD/ZCARD/XLEN 同属长度家族、不要用"先 LLEN 再操作"做并发控制。