Redis 数据类型有哪几种?

Redis 提供 5 种基础数据类型 + 4 种扩展数据类型,共计 9 种:

数据类型 底层编码 说明 典型场景
String int / embstr / raw 最基本的类型,可存字符串、整数、浮点数 缓存、计数器、分布式锁
List quicklist(双向链表 + ziplist 有序可重复的字符串列表 消息队列、最新消息排行
Hash ziplist / hashtable 键值对集合,类似 Java 的 HashMap 存储对象、用户信息
Set intset / hashtable 无序不重复的字符串集合 标签、共同好友、去重
ZSet(Sorted Set) ziplist / skiplist + hashtable 有序不重复集合,每个元素关联一个 score 排行榜、延迟队列
扩展类型 说明 典型场景
Bitmap 位操作,基于 String 实现 签到打卡、用户活跃统计
HyperLogLog 基数估算,基于 String 实现 UV 统计(允许误差)
GEO 地理位置信息,基于 ZSet 实现 附近的人、距离计算
Stream 消息流(Redis 5.0 新增) 消息队列(比 List 更完善)

深度解析

一、五种基础数据类型

1. String(字符串)

String 是 Redis 中最简单的数据类型,一个 Key 对应一个 Value。它可以存储字符串、整数、浮点数,最大能存 512MB 的数据。

底层编码有三种:

  • int:当值为整数且不超过 long 范围时使用,8 字节长整型
  • embstr:当字符串长度 ≤ 44 字节时使用,一次内存分配,紧凑存储
  • raw:当字符串长度 > 44 字节时使用,SDS(Simple Dynamic String)实现

Redis 数据类型有哪几种?

上图展示了 String 类型在不同场景下的三种编码方式。关键点如下:

  • int 编码:值为整数时,直接存储在 RedisObject 的 ptr 字段中,无需额外分配内存,效率最高。
  • embstr 编码:短字符串(≤ 44 字节)时,RedisObject 和 SDS 在一次内存分配中连续存放,CPU 缓存命中率高,分配和释放都只需一次操作。
  • raw 编码:长字符串(> 44 字节)时,RedisObject 和 SDS 分开分配,ptr 指针指向独立的 SDS 内存块。需要两次内存分配,但不受连续内存的限制。

常见使用场景

# 简单缓存
SET user:1001 "张三"
GET user:1001

# 计数器(原子操作)
SET article:1001:views 0
INCR article:1001:views    # views + 1
INCRBY article:1001:views 10  # views + 10

# 分布式锁
SET lock:order:1001 "unique_id" NX EX 30

2. List(列表)

List 是一个有序可重复的字符串链表,支持从两端插入和弹出元素。

底层采用 quicklist(快速列表)实现,它是 ziplist(压缩列表) + 双向链表的组合体。

Redis 数据类型有哪几种?

上图展示了 List 底层的 quicklist 结构。核心设计思想:

  • 双向链表:每个节点(quicklistNode)通过 prev 和 next 指针相连,支持双向遍历。
  • 每个节点是一个 ziplist:不是每个元素一个节点,而是一个节点存多个连续元素(ziplist),兼顾内存紧凑和操作效率。
  • 为什么这样设计:纯双向链表每个元素都有前后指针,内存开销大;纯 ziplist 虽然紧凑,但元素太多时插入删除需要大量内存搬移。quicklist 取两者之长,每个 ziplist 节点控制在合理大小(默认 8KB),中间节点还可以用 LZF 压缩。

常见使用场景

# 消息队列(LPUSH + BRPOP 实现阻塞队列)
LPUSH queue:task "task_data"
BRPOP queue:task 30  # 阻塞等待 30 秒

# 最新列表(如朋友圈时间线)
LPUSH timeline:user:1001 "msg_id:2001"
LRANGE timeline:user:1001 0 9  # 获取最新 10 条

3. Hash(哈希)

Hash 是一个键值对集合,类似 Java 中的 HashMap,适合用来存储对象。

底层编码有两种:

  • ziplist:当元素数量较少(默认 ≤ 128 个)且所有值都较短(默认 ≤ 64 字节)时使用
  • hashtable:当不满足 ziplist 条件时,转为真正的哈希表

Redis 数据类型有哪几种?

上图展示了 Hash 类型的两种编码及转换逻辑:

  • ziplist 编码:字段和值以连续的方式存储在压缩列表中,没有指针开销,内存极其紧凑。适合存储少量字段的对象。缺点是查找时需要遍历,时间复杂度 O(n),但元素少时影响可忽略。
  • hashtable 编码:与 Java 的 HashMap 类似,通过哈希函数定位桶,再用链地址法处理哈希冲突。查找时间复杂度 O(1)。当元素增多或值变大时自动从 ziplist 转换过来。

常见使用场景

# 存储用户信息
HMSET user:1001 name "张三" age 25 city "北京"
HGET user:1001 name          # "张三"
HMGET user:1001 name age     # "张三" "25"

# 修改单个字段(不需要读取整个对象)
HSET user:1001 age 26

小贴士:相比用 String 存储 JSON 对象,Hash 的优势在于可以只读写单个字段,无需序列化/反序列化整个对象,既省带宽又省时间。

4. Set(集合)

Set 是一个无序不重复的字符串集合,支持集合间的交集、并集、差集运算。

底层编码有两种:

  • intset(整数集合):当所有元素都是整数且数量 ≤ 512 时使用
  • hashtable:不满足上述条件时使用,Value 全部设为 null

Redis 数据类型有哪几种?

常见使用场景

# 标签系统
SADD article:1001:tags "Java" "Redis" "面试"
SMEMBERS article:1001:tags

# 共同好友(交集)
SINTER user:1001:friends user:1002:friends

# 去重
SADD unique:visitors "192.168.1.1"
SISMEMBER unique:visitors "192.168.1.1"  # 判断是否已存在

5. ZSet(有序集合)

ZSet(Sorted Set)在 Set 的基础上,给每个元素关联一个 score(分数),按分数自动排序。

底层编码有两种:

  • ziplist:元素少且短时使用
  • skiplist + hashtable:元素较多时使用,跳表保证范围查询效率,哈希表保证 O(1) 查找分数

Redis 数据类型有哪几种?

上图展示了 ZSet 底层的跳表(skiplist)结构。跳表的核心思想:

  • 多层索引:每个节点随机决定层数,层数越高节点越少。查找时从最高层开始,逐层往下找,类似二分查找的思路。
  • 查找效率:平均 O(logN),媲美红黑树,但实现更简单,范围查询更方便(只需在底层链表上遍历)。
  • 为什么不用红黑树:跳表的范围查询更高效,实现更简单(不用旋转维护平衡),内存占用也可以通过调节层高来控制。
  • hashtable 的作用:跳表虽然查找快,但按 member 查 score 仍需 O(logN)。配合 hashtable 后,可以通过 member 直接 O(1) 找到对应节点。

常见使用场景

# 排行榜
ZADD rank:score 100 "张三" 95 "李四" 88 "王五"
ZREVRANGE rank:score 0 2 WITHSCORES  # Top3

# 延迟队列(score 存时间戳)
ZADD delay:queue 1711500000000 "order:1001"
ZRANGEBYSCORE delay:queue 0 <当前时间戳>  # 获取到期任务

二、四种扩展数据类型

1. Bitmap(位图)

基于 String 实现,把 String 当成 bit 数组来操作,适合处理海量布尔值数据。

# 用户签到(key=年月, offset=日期, value=0/1)
SETBIT sign:1001:202603 26 1   # 3 月 26 日签到
GETBIT sign:1001:202603 26     # 查询某天是否签到
BITCOUNT sign:1001:202603      # 统计本月签到天数

极其节省内存:一个月的签到数据只需约 4 字节(31 个 bit)。

2. HyperLogLog

基于概率的基数估算算法,标准误差 0.81%。每个 Key 只需 12KB 内存就能估算 2^64 个不同元素的基数。

# UV 统计
PFADD uv:20260327 "user1" "user2" "user3"
PFCOUNT uv:20260327     # 估算独立访客数
PFMERGE uv:week uv:mon uv:tue  # 合并多天数据

3. GEO(地理位置)

基于 ZSet 实现,使用 GeoHash 编码经纬度为 score,支持距离计算和范围查询。

# 附近的人
GEOADD nearby 116.40 39.90 "天安门" 116.41 39.91 "王府井"
GEORADIUS nearby 116.40 39.90 1 km  # 查找 1km 内的地点
GEODIST nearby "天安门" "王府井" km  # 计算两点距离

4. Stream(消息流)

Redis 5.0 新增,是更完善的消息队列方案,支持消费组、消息确认、持久化,类似轻量版 Kafka。

# 生产消息
XADD stream:order * order_id 1001 amount 99.9

# 消费组消费
XGROUP CREATE stream:order group1 $
XREADGROUP GROUP group1 consumer1 COUNT 1 BLOCK 5000 STREAMS stream:order >
上一篇 Linux指令一周通 PDF下载
下一篇 C盘满了怎么清理?10种安全释放Win10/Win11空间的方法(详细图文版)

站点性能

运行正常
实时心跳0 ms
页面加载
0
SQL 查询
0
服务端响应
0 ms
峰值内存
0 MB
阿陶学长

阿陶学长管理员

专注于分享最有价值的互联网干货

本月创作热力图

最新评论
暂无评论
AeroCore图片