Redis LRANGE 命令详细教程
LRANGE 返回列表中指定索引区间的元素,是读取列表片段的基础命令。索引从 0 开始计数,区间为闭区间(stop 索引也被包含),支持负索引从表尾倒数。它从 Redis 1.0.0 起提供,LRANGE key 0 -1 是查看整个列表最常用的写法。
资料合集:https://pan.quark.cn/s/10e98d308913、https://pan.quark.cn/s/f56bc69c5338
一、概览与语法
redis
LRANGE key start stop
| 项目 | 说明 |
|---|---|
| 数据类型 | List |
| 支持版本 | Redis 1.0.0 起 |
| key | 目标列表 Key |
| start | 区间起始索引,0 基,可为负数 |
| stop | 区间结束索引,闭区间(包含该索引),可为负数 |
| 返回值 | 数组:区间内的元素,按索引从小到大排列;无匹配时返回空数组 |
| 时间复杂度 | O(S+N),S 为 start 偏移到列表较近端点的距离,N 为返回的元素数 |
| ACL | @read、@list、@slow |
| 命令标记 | readonly |
官方说明:返回存储于 key 的列表中指定区间的元素。偏移量 start 与 stop 都是 0 基索引;负偏移从表尾倒数,-1 表示最后一个元素,-2 表示倒数第二个元素,以此类推。$TRAE_REF
二、基础示例
以下命令在测试实例的 redis-cli 中执行。文中结果是预期说明,未实际连接 Redis 运行。示例沿用官方文档的数据与结果。
redis
DEL tutorial:{lrange}:mylist
RPUSH tutorial:{lrange}:mylist "one" "two" "three"
LRANGE tutorial:{lrange}:mylist 0 0
LRANGE tutorial:{lrange}:mylist -3 2
LRANGE tutorial:{lrange}:mylist -100 100
LRANGE tutorial:{lrange}:mylist 5 10
预期结果:RPUSH 返回 3;四条 LRANGE 分别返回:"one"(单元素区间);"one"、"two"、"three"(负索引 -3 即表头);"one"、"two"、"three"(越界部分被钳制);空数组(起点 5 已超出列表范围)。
三、索引与区间语义
LRANGE 的区间规则有几个容易踩坑的点:
- 0 基索引:表头是 0,不是 1。
- 闭区间 :stop 索引包含在结果里,
LRANGE key 0 2返回 3 个元素,这与很多编程语言"含头不含尾"的切片惯例不同。 - 负索引 :-1 是表尾。
LRANGE key -2 -1返回最后两个元素。 - 越界不报错:stop 超过列表末尾时被钳制到最后一个元素;start 超过列表末尾时返回空数组;start 大于 stop 时返回空数组。
- Key 不存在:视为空列表,返回空数组,不报错。
redis
LRANGE tutorial:{lrange}:mylist 1 2
LRANGE tutorial:{lrange}:mylist -2 -1
LRANGE tutorial:{lrange}:mylist 2 1
预期结果:第一条返回 "two"、"three"(闭区间共 2 个元素);第二条返回 "two"、"three"(最后两个元素);第三条 start 大于 stop,返回空数组。
四、常用区间写法
| 写法 | 含义 |
|---|---|
LRANGE key 0 -1 |
整个列表 |
LRANGE key 0 9 |
前 10 个元素 |
LRANGE key -10 -1 |
最后 10 个元素 |
LRANGE key 10 19 |
第 11 到第 20 个元素(分页) |
LRANGE key 0 0 |
只看表头元素 |
LRANGE key -1 -1 |
只看表尾元素 |
配合 LPUSH/LTRIM 的限长列表,LRANGE key 0 N-1 就是"最新 N 条"的标准读取方式。
五、返回值与空结果的区分
LRANGE 在多种情形下都返回空数组,彼此无法从返回值区分:
| 情形 | 返回 |
|---|---|
| Key 不存在 | 空数组 |
| Key 为空列表 | 空数组(列表非空才存在,正常不会出现) |
| start 超出列表末尾 | 空数组 |
| start 大于 stop | 空数组 |
如果业务需要区分"列表不存在"和"区间没取到元素",应额外执行 EXISTS 或 TYPE 判断,而不是只看 LRANGE 结果。
redis
LRANGE tutorial:{lrange}:nokey 0 -1
EXISTS tutorial:{lrange}:nokey
预期结果:第一条返回空数组;第二条返回 0,说明 Key 确实不存在。
六、边界情况与错误处理
| 场景 | 行为 |
|---|---|
| Key 不存在 | 返回空数组 |
| Key 类型不是 List | 报 WRONGTYPE |
| start/stop 缺失或不是整数 | 报语法错误或参数类型错误 |
| 索引越界 | 钳制处理,不报错 |
| 列表为空 | 空数组 |
redis
SET tutorial:{lrange}:str text
LRANGE tutorial:{lrange}:str 0 -1
预期结果:对 String 类型执行报 WRONGTYPE,类型检查先于区间计算。
七、与相近命令的区别
| 命令 | 定位方式 | 是否修改列表 | 说明 |
|---|---|---|---|
| LRANGE | 按索引区间批量读取 | 否 | 闭区间,支持负索引 |
| LINDEX | 按单个索引读取 | 否 | 只取一个元素 |
| LPOS | 按值查找返回索引 | 否 | 与 LRANGE 方向相反:一个按值找位置,一个按位置取值 |
| LTRIM | 按索引区间裁剪 | 是 | 区间语义与 LRANGE 完全一致,常配合使用 |
| LLEN | 只返回长度 | 否 | 判断非空用 LLEN 更轻量 |
组合用法:LRANGE 读出的区间与 LTRIM 裁剪的区间遵循同一套索引规则,两者搭配即可实现"读取后保留"的逻辑;分页读取用 LRANGE key start start+pageSize-1。
八、客户端示例
前提为已安装 redis-py 并准备好本地测试实例。redis-py 的 lrange(name, start, end) 返回元素列表。
python
import redis
r = redis.Redis(host="localhost", port=6379, decode_responses=True)
key = "tutorial:{lrange}:py"
try:
r.delete(key)
r.rpush(key, "one", "two", "three")
print(r.lrange(key, 0, -1)) # ['one', 'two', 'three']
print(r.lrange(key, 0, 1)) # ['one', 'two']
print(r.lrange(key, -2, -1)) # ['two', 'three']
print(r.lrange(key, 5, 10)) # [],区间无交集
print(r.lrange("no-such", 0, -1)) # [],Key 不存在
finally:
r.delete(key)
r.close()
Java(Jedis)示例,lrange 返回 List<String>:
java
try (Jedis jedis = new Jedis("localhost", 6379)) {
String key = "tutorial:{lrange}:java";
jedis.del(key);
jedis.rpush(key, "one", "two", "three");
System.out.println(jedis.lrange(key, 0, -1));
// [one, two, three]
System.out.println(jedis.lrange(key, 0, 1));
// [one, two]
System.out.println(jedis.lrange(key, 5, 10));
// []
jedis.del(key);
}
九、性能与使用注意事项
复杂度:O(S+N),只搬运请求区间内的元素,不扫描全表,因此"取前 N 条""取最后 N 条"都很快。
警惕全量读取 :LRANGE key 0 -1 在百万级元素的列表上会一次性构造巨大响应,阻塞事件循环并占用网络带宽,属于典型慢命令。大列表应始终限制区间或先用 LLEN 评估长度。
只读命令:不修改列表,可在副本节点执行分担读压力;在 MULTI/EXEC、Lua 脚本与管道中正常使用。
分页注意:基于索引的分页在列表头部持续 LPUSH 时会出现"整页平移"(读到重复或漏读),要求稳定的分页位点时考虑改用有序集合或游标方案。
十、典型业务场景
Feed 与最新消息读取 :LPUSH 写入 + LTRIM 限长的列表,用 LRANGE key 0 N-1 读取最新一批内容。
任务队列巡检 :LRANGE key 0 9 预览队列头部待处理任务,不弹出、不消费,供监控面板展示。
历史记录分页 :浏览历史、操作日志按 LRANGE key offset offset+pageSize-1 分段展示。
与 LTRIM 组合维护:读取的同时裁剪,例如保留最近 100 条的滑动窗口逻辑。
十一、练习、排错与总结
练习:新建 tutorial:{lrange}:ex,用 RPUSH 写入 a b c d e;执行 LRANGE ex 1 3 确认返回 b,c,d(注意闭区间 3 个元素);LRANGE ex -2 -1 返回 d,e;LRANGE ex 3 2 返回空数组;LRANGE ex 0 -1 返回全部 5 个元素;对不存在的 Key 执行返回空数组且不报错。
排错要点:结果比预期少一个元素时,检查是否按"含头不含尾"的习惯写了 stop(应为 start start+N-1);顺序与预期相反时确认写入端用的是 LPUSH 还是 RPUSH;返回空数组时区分 Key 不存在与区间无交集,用 EXISTS/TYPE 进一步判断;报 WRONGTYPE 时用 TYPE 检查类型;慢日志出现 LRANGE 0 -1 时改为限定区间。清理使用 DEL tutorial:{lrange}:mylist tutorial:{lrange}:str tutorial:{lrange}:py tutorial:{lrange}:java tutorial:{lrange}:ex。速记:1.0 起支持、按索引区间读取、0 基闭区间含 stop、负索引从表尾倒数、-1 是最后一个元素、越界钳制不报错、Key 不存在返回空数组、空数组无法区分"不存在"与"无交集"、O(S+N) 与列表总长无关、全量读取用 0 -1 需防大列表。