Redis 底层数据结构:一个 key 背后到底藏着什么
很多人第一次学 Redis,记住的是五种常用类型:String、List、Hash、Set、ZSet。再往后背面试题,又会遇到 SDS、quicklist、listpack、intset、skiplist、hashtable。 这些名字放在一起很容易让人迷糊:Redis 不是 key-value 数据库吗?为什么一个 Hash 后面还会有 listpack 和 hashtable 两种实现?为什么同样是 Set,有时是 intset,有时又变成哈希表? 真正要理解的不是“Redis 有哪些数据结构”这张清单,而是一个更具体的问题: Redis 为什么要让同一种对外类型,在不同场景下切换不同的内部编码? 顺着这个问题往下看,Redis 的底层数据结构会清楚很多。它不是为了把实现弄复杂,而是在内存、CPU、查询速度、扩容成本之间做了一组很工程化的取舍。 本文写作和更新时的版本背景是:截至 2026 年 5 月 23 日,Redis Open Source 最新稳定版是 8.6.3,这是 2026 年 5 月发布的安全修复版本;Redis GitHub releases 里还能看到 8.8-RC1,但它是预发布版,官方说明不适合生产环境使用。 从底层数据结构这条线看,Redis 8.6 最值得关注的不是“又多背几个结构名”,而是几类更贴近日常排查的问题: 大 Hash 和大 ZSet 的内存占用继续被优化。 Stream 增加了 XADD IDMP / IDMPAUTO,用于幂等写入。 新增 HOTKEYS,能直接辅助定位热点 key。 新增 key 内存大小直方图相关能力,排查 List、Set、Hash、ZSet 的规模分布更方便。 新增 volatile-lrm 和 allkeys-lrm 淘汰策略,按“最近修改时间”参与淘汰。 旧版本里经常出现的 ziplist,在 Redis 7 之后大多已经被 listpack 替代,所以不要再只背“压缩列表”那套旧答案。 ...