为什么Redis List不适合做随机访问频繁的场景_分析双向链表时间复杂度

P粉602998670

P粉602998670

2026-06-26

816人浏览

原创

lrange查中间一段慢是因为定位起始索引需从头或尾逐节点遍历,时间复杂度为o(n),即使返回范围小,跳过前n项仍耗时;只有靠近首尾的偏移(如0-99或-100--1)才接近o(k)。

为什么redis list不适合做随机访问频繁的场景_分析双向链表时间复杂度

为什么 LRANGE 查中间一段也慢?不是“范围查询”吗?

很多人看到 LRANGE key 100 199 就以为 Redis 是“批量读”,实际它必须先找到第 100 个元素,再往后数 100 个——找第 100 个这一步就是 O(n)。Redis 的 List 底层是 quicklist(3.2+ 默认),本质是「双向链表 + 每个节点内嵌 ziplist」,但不管怎么封装,**定位任意索引仍需从头或尾逐个跳节点**。

常见误判场景:

  • LRANGE key -100 -1 取最后 100 条看似高效,但 Redis 仍要先遍历到尾部,再倒退——若列表有 100 万条,这仍是 O(n)
  • 在分页接口里写 LRANGE key 50000 50099,等价于“跳过前 5 万条”,实测延迟飙升,且 CPU 负载明显上升
  • 误以为 quicklist 的 ziplist 分块能加速索引访问:不能。ziplist 内部仍是连续内存的线性结构,没有跳表或索引机制

LINDEXLSET 为什么必须避免在大 List 中使用?

LINDEX key 50000 是典型的“单点随机访问”,它不返回范围,只取一个值,但代价和 LRANGE key 50000 50000 几乎一样:都要从头开始遍历 5 万次指针跳转。同理,LSET key 50000 "new" 先查再改,两趟 O(n)

真实踩坑点:

  • 后台定时任务扫描 List 做状态更新,用了 LINDEX 遍历所有元素 → QPS 上百就卡住
  • 把 List 当作“带顺序的 Hash”用,比如存用户操作日志并按时间戳索引修改 → 实际应换 Sorted Set + score
  • 未注意 quicklist 的压缩阈值(默认 list-max-ziplist-size -2),小 ziplist 节点多,指针跳转次数反而比纯 linkedlist 更多

对比数组、跳表、Sorted Set:为什么它们更适合随机访问?

根本差异不在“能不能查”,而在“查的成本是否可控”:

Redis 8.2.3
Redis 8.2.3

Redis 8.2.3 是一款安全优先的高性能键值存储系统。该版本紧急修复了可能引发远程代码执行(RCE)的高危漏洞(CVE-2025-62507),并解决了 HyperLogLog 及 Cuckoo Filter 等数据结构在特定场景下的崩溃问题。建议所有用户立即升级,以保障生产环境的系统稳定与数据安全。

下载
  • 数组(如 Java ArrayList):内存连续,get(i) 直接算地址偏移,O(1);但 Redis List 不是数组
  • Sorted Set:底层是跳表(skiplist)+ 哈希表,ZRANGE key 50000 50000 WITHSCORES 仍是 O(log n),比 List 的 O(n) 稳定得多
  • 如果真需要按位置快速读写,且数据量不大,用多个 String 键(如 log:20260528:000001)+ 自增 ID,反而更直接

别被“List 支持索引语法”迷惑——语法存在 ≠ 性能可用。

什么情况下 LRANGE 才算真正快?

只有当起始偏移足够靠近头或尾时,LRANGE 才接近 O(k)(k 是返回元素个数):

  • LRANGE key 0 99:从头开始,100 次指针跳,快
  • LRANGE key -100 -1:从尾反向遍历,100 次跳,也快
  • LRANGE key 0 -1:全量读,O(n),但至少没额外跳过

真正危险的是“深偏移 + 小范围”,比如 LRANGE key 99900 99999 —— 它得先跳 99900 次才能开始取,和取前 100 条耗时可能差百倍。

线上 List 如果长度稳定在几千以内,LINDEX 还能忍;一旦破万,任何基于索引的读写都该触发告警或重构。

相关专题

更多
li是什么元素
li是什么元素

li是HTML标记语言中的一个元素,用于创建列表。li代表列表项,它是ul或ol的子元素,li标签的作用是定义列表中的每个项目。本专题为大家li元素相关的各种文章、以及下载和课程。

2023.08.03

596

5

常用的数据库软件
常用的数据库软件

常用的数据库软件有MySQL、Oracle、SQL Server、PostgreSQL、MongoDB、Redis、Cassandra、Hadoop、Spark和Amazon DynamoDB。更多关于数据库软件的内容详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.02

1907

19

内存数据库有哪些
内存数据库有哪些

内存数据库有Redis、Memcached、Apache Ignite、VoltDB、TimesTen、H2 Database、Aerospike、Oracle TimesTen In-Memory Database、SAP HANA和ache Cassandra。更多关于内存数据库相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.14

1579

11

mongodb和redis哪个读取速度快
mongodb和redis哪个读取速度快

redis 的读取速度比 mongodb 更快。原因包括:1. redis 使用简单的键值存储,而 mongodb 存储 json 格式的数据,需要解析和反序列化。2. redis 使用哈希表快速查找数据,而 mongodb 使用 b-tree 索引。因此,redis 在需要高性能读取操作的应用程序中是一个更好的选择。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.02

2502

6

redis怎么做缓存服务器
redis怎么做缓存服务器

redis 作为缓存服务器的答案:redis 是一款开源、高性能、分布式的键值存储,可作为缓存服务器使用。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

518

6

redis怎么解决数据一致性
redis怎么解决数据一致性

redis 提供了两种一致性模型,以维护副本数据一致性:强一致性 (sync) 确保写操作仅在复制到所有从节点后才完成;最终一致性 (async) 则在主节点上写操作后认为已完成,牺牲一致性换取性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

525

6

mysql和redis怎么保证双写一致性
mysql和redis怎么保证双写一致性

确保 mysql 和 redis 双写一致性的技术包括:1、事务性更新:同时更新 mysql 和 redis,保证一致性;2、主从复制:mysql 主服务器更改同步到 redis 从服务器;3、基于事件的更新:mysql 记录更改并发送到 redis等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

2491

6

redis缓存一般存些什么数据
redis缓存一般存些什么数据

redis缓存中存储的数据类型包括:字符串、哈希、列表、集合、有序集合、位图、地理空间数据和hyperloglog。这些数据类型适用于存储各种数据,从简单信息到复杂对象和地理位置。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

943

6

redis的8种数据类型有哪些
redis的8种数据类型有哪些

redis 提供 8 种数据类型:字符串(文本、数字、二进制)、哈希(键值对)、列表(有序集合)、集合(无序唯一元素)、有序集合(按分数排序)、地理空间(地理位置)、hyperloglog(估计大数据基数)和位图(位序列存储)。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

689

6

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
phpEnv手册
phpEnv手册

共0课时 | 0人学习

进程与SOCKET
进程与SOCKET

共6课时 | 0.5万人学习

Redis+MySQL数据库面试教程
Redis+MySQL数据库面试教程

共72课时 | 9万人学习