1. 使用LPUSH/RPUSH和LPOP/RPOP等O(1)操作,避免使用索引访问如LINDEX,它是O(N)。2. 批量操作:使用管道(pipeline)或Lua脚本减少RTT。3. 控制列表长度,超过阈值时分片或使用其他数据结构如Hash。4. 阻塞命令BRPOPLPUSH用于队列,避免空轮询。5. 开启持久化但调优AOF/RDB以最小化影响。
来源1
Redis List 是基于双向链表实现的,头部和尾部操作的时间复杂度都是 O(1),所以在实现队列或栈时,应优先使用 lpush、rpush、lpop、rpop 等操作,避免使用 lset、lindex 等操作,这两者的复杂度是 O(n)。Redis 队列阻塞命令 brpoplpush 比轮询 pop 要高效的多。
来源2
列表长度过长会影响性能,建议列表长度不要超过 5000,超过 10000 时建议拆分成多个 list 分片存储。可以使用 hash 字段来存储拆分后的 list,比如可以用 lrange 0 1000 作为key的分片标识。
来源3
使用 pipeline 可以将多条命令一次性发送到服务器,减少网络 RTT 时间。Lua 脚本可以将多条命令封装成一个原子操作,既保证了原子性,又减少了网络开销。
来源4
Redis 的 List 主要用来实现队列(依賴 LPUSH+RPOP 或 LPUSH+BRPOP),但是实现栈的功能比較好,队列的實現會有問題的,RPOP 的效率不高,官方不推薦用來做队列方向的應用。推薦使用 Redis 的 container 類別,該類別內部使用多個 List 做數據分片,能有效避免 List 內數據無限增長導致的內存碎片。
来源5
Redis list 是用 quicklist 实现的,原本的 linkedlist 的缺点是为了避免,折中的数据结构。压缩列表 ziplist 是为了节省内存而设计的,不会产生碎片内存,但性能比起原来的 adlist 慢一些,数据量大的时候,ziplist 就不好用了。压缩列表是按照顺序来存的,所以从中取某个元素的时间复杂度是 O(N)。
来源6
Redis 官方有建议:Redis 的最佳实践,Redis 队列阻塞命令 brpoplpush 比轮询 pop 要高效的多。另外,阻塞操作会让空闲的连接释放 cpu 资源(因为阻塞模式下会让出 cpu 给其它进程),如果不阻塞,空闲的连接也会被操作系统调度(一般是 10ms 一次),如果有很多空闲连接,会增加系统负载。
来源7
使用 SCAN 命令代替 KEYS 命令来遍历列表键,避免阻塞主线程。优化网络:使用连接池,保持长连接,减少连接建立开销。
FAQ
Q: Redis List 适合做什么场景?
A: 适合轻量级队列、栈、最近访问列表,不适合随机访问或大数据量。
Q: 列表太长怎么处理?
A: 分片存储到多个List,或切换到Sorted Set。
Q: Pipeline 和 Lua 脚本哪个更好?
A: Pipeline 减少RTT,Lua 保证原子性,二者结合最佳。
Q: 为什么不推荐用List做队列?
A: RPOP效率低,推荐阻塞命令或专业队列如Stream。