Redis命令:LRANGE

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 需防大列表。

相关推荐
蓝胖的四次元口袋2 小时前
Redis知识梳理(5)
数据库·redis·缓存
for_ever_love__2 小时前
半同步复制:数据安全和服务可用之间怎么权衡
redis·mysql·缓存·一致性·数据·半同步复制·方式
Anastasiozzzz2 小时前
InnoDB 为什么不用跳表,Redis 为什么不用 B+树?一场“磁盘”与“内存”的终极对决
数据库·redis·b树
Pin_Qing2 小时前
同一天,谷歌半价卖旗舰,阶跃翻倍收缓存
大数据·开发语言·人工智能·程序人生·缓存
Thomas.Sir4 小时前
第29课:微服务异步调用、线程池优化 & 事件驱动开发
java·redis·微服务
java_nnnn4 小时前
Redis 初识:从单体架构到分布式架构的演进
redis·分布式·架构
Tsuki_tl5 小时前
Redis过期策略
redis·缓存·过期策略·内存淘汰机制·分布式开发·惰性删除·定期删除
敲上瘾5 小时前
分布式系统——Redis哨兵:自动故障转移与选举原理
linux·数据库·redis·分布式·缓存·微服务
骇客野人15 小时前
在麒麟操作系统上 分别安装 jdk1.8, 达梦数据库,redis ,memcache 的操作实施方案和步骤
数据库·redis·memcached