概要
redis 不仅仅是一个简单的 key-value 存储系统,其丰富的数据结构是支撑高性能业务场景的核心。本文将深入解析 redis 的 5 种基础数据类型 和 4 种高级数据类型,并结合生产环境中的最佳实践,探讨如何避免“大 key”陷阱。
五大基础数据类型
redis 的核心数据结构主要有五种,每种都有其独特的底层实现和适用场景:
1. string (字符串)
- 特点:最基本的数据类型,二进制安全。既能存文本、数字,也能存图片、序列化对象。
- 容量:单个 value 最大 512 mb。
- 底层实现:简单动态字符串 (sds)。
- 典型场景:
- 缓存:用户 session、html 页面片段。
- 计数器:利用
incr命令实现点赞数、访问量统计。 - 分布式锁:利用
setnx实现。
2. hash (哈希)
- 特点:键值对集合,适合存储对象。
- 优势:支持字段级操作(
hget,hset),修改对象单个属性无需整体回写,节省网络流量和内存。 - 底层实现:当数据量小时使用 ziplist/listpack (紧凑列表),数据量大时自动转为 hashtable。
- 典型场景:
- 购物车:key 为用户 id,field 为商品 id,value 为数量。
- 用户信息:存储用户名、邮箱、年龄等分散属性。
3. list (列表)
- 特点:有序的字符串列表,支持两端插入/弹出。
- 底层实现:quicklist (redis 3.2+)。它是双向链表与 ziplist 的结合体,既保证了链表的操作灵活性,又利用了紧凑列表的内存节省特性。(注:旧版文档常误述为纯双向链表)
- 典型场景:
- 消息队列:利用
lpush+rpop实现简单队列。 - 最新列表:如微博最新推文、文章最新评论。
- 消息队列:利用
4. set (集合)
- 特点:无序且不重复的字符串集合。
- 优势:支持交集、并集、差集运算,时间复杂度优秀。
- 典型场景:
- 去重:统计网站独立访客 (uv)。
- 标签系统:用户的兴趣标签。
- 好友关系:共同好友计算(交集)。
5. zset (sorted set, 有序集合)
- 特点:在 set 的基础上,为每个元素关联一个 score (分数),元素按分数自动排序。
- 底层实现:skiplist (跳表) + dict (字典)。跳表保证了范围查询和排序的高效性。
- 典型场景:
- 排行榜:游戏积分榜、热搜榜。
- 延时队列:将执行时间戳作为 score。
四种高级数据类型
针对特定场景,redis 引入了更 specialized 的数据结构:
| 数据类型 | 引入版本 | 核心特性 | 内存占用特点 | 典型应用场景 |
|---|---|---|---|---|
| bitmap | 2.2 | 位图结构,以 bit (0/1) 为单位存储数据 | 极低 (例如:1000万用户仅需 ~1.2mb) | 用户签到、状态标记 (在线/离线)、权限位控制 |
| hyperloglog | 2.8 | 基于概率算法的基数估算结构 | 固定且极小 (无论数据量多大,恒定占用 12kb) | 海量数据去重统计 (如网站 uv)、独立访客计数 |
| geo | 3.2 | 地理位置索引,支持经纬度存储与空间查询 | 依赖 zset (底层将经纬度编码为 score 存入有序集合) | “附近的人”、距离计算、指定半径内的搜索 |
| stream | 5.0 | 专为消息队列设计,支持消费组与持久化 | 较高 (需存储消息内容及元数据,支持持久化) | 可靠消息队列、日志收集、实时数据流处理 |
💡 深度解析
- bitmap 极致省空间:1000 万用户签到,若用 string 需数十 mb,用 bitmap 仅需 ~1.2 mb。
- hyperloglog 的取舍:它不是精确计数,而是估算(误差率约 0.81%),但在亿级数据去重场景下,12kb 的恒定内存是巨大的优势。
- stream vs list vs pub/sub:
- list:简单队列,无 ack 机制,消费者挂掉消息可能丢失。
- pub/sub:发布订阅,消息不持久化,消费者下线即丢失消息。
- stream:支持消息持久化、ack 确认机制、消费者组 (consumer group) 模式,是构建可靠消息系统的首选。
生产技术细节:关于 bigkey
问题:string 类型最大能存 512mb,生产中会这么用吗?
答案:绝对不会。
虽然理论上限很高,但在生产环境中,bigkey (大键) 是 redis 性能杀手。
为什么不能存大 value?
- 单线程阻塞:redis 处理命令是单线程的。读取或删除一个 100mb 的 key,可能需要几十毫秒甚至上百毫秒。在此期间,所有其他请求都会排队等待,导致系统吞吐量骤降,甚至引发超时雪崩。
- 网络拥塞:传输大数据包会占用大量网卡带宽,阻塞正常的小包通信。
- 内存碎片:频繁分配和释放大内存块容易导致内存碎片率升高。
最佳实践建议
- 控制大小:建议单个 value 控制在 10kb 以内,尽量不超过 1mb。
- 拆分策略:
- 如果必须存大对象,将其拆分为多个 key(例如:
user:1001:info_1,user:1001:info_2)。 - 对于 hash 类型,如果 field 过多,也可以按范围拆分。
- 如果必须存大对象,将其拆分为多个 key(例如:
- 异步删除:redis 4.0+ 提供了
unlink命令,用于异步非阻塞地删除大 key,替代阻塞式的del。
小结
redis 的强大在于其多样化的数据结构能够精准匹配不同的业务需求:
- 基础五型覆盖了 90% 的日常开发场景(缓存、队列、排行、社交)。
- 高级四型解决了特定领域的痛点(海量统计、地理搜索、可靠消息)。
- 生产红线:时刻警惕 bigkey,合理设计 key 的结构与大小,是保障 redis 集群稳定运行的关键。
到此这篇关于redis 数据类型全景指南从基础到高级的文章就介绍到这了,更多相关redis 数据类型内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论