Redis 常见数据结构

字符串(String)

内部实现:SDS (Simple Dynamic String)

最基础的类型,一个 Key 对应一个 Value,是二进制安全的,可以存储文本、数字或者是序列化后的对象。

# 普通文本
SET user:100:name "Jack"
# 计数器,可以使用 INCR 增加
SET post:42:views 1000
# 序列化对象
SET user:100:data '{"id":100,"city":"Beijing"}'

哈希(Hash)

内部实现:ziplist(压缩列表)或 hashtable(哈希表)

相比 String 类型,Hash 可以只修改对象中的某个字段,而不需要读取整个对象再写回,节省带宽和 CPU。

适合存储对象,示例:

  • 购物车:以用户 ID 为 Key,商品 ID 为 Field,数量为 Value。
# 用户信息
HSET user:100 name "Jack" age 25 city "Shanghai"
# 购物车
# Key: cart:用户ID, Field: 商品ID, Value: 数量
HSET cart:8888 1001 2
HSET cart:8888 1002 1

列表(List)

内部实现:quicklist(双向链表和压缩列表的结合)

简单的字符串列表,按照插入顺序排序,可以充当栈或队列。

可以利用 LPUSH + BRPOP 做一个消息队列。当然也可以用作 最新消息排序 ,存储最新的 N 条记录。

# 消息队列
LPUSH task_queue "send_email_1"
LPUSH task_queue "send_email_2"
# 消费:RPOP task_queue

# 最新动态
LPUSH user:100:feed "post_id_99"
LTRIM user:100:feed 0 9 # 始终只保留最新的10条

集合(Set)

内部实现:intset(整数集合)或 hashtable

无序的字符串集合,元素具有 唯一性,且支持求交集、并集、差集。

常用场景:

  • 去重操作:记录独立的访客记录(UV)。
  • 社交关系:利用 SINTER 求共同好友;利用 SDIFF 求可能认识的人。
  • 抽奖系统:SPOPSRANDMEMBER 随机抽取中奖者。
# 标签系统
SADD post:42:tags "PHP" "ThinkPHP8" "Redis"

# 共同好友
SADD user:A:friends "user:B" "user:C" "user:D"
SADD user:E:friends "user:C" "user:D" "user:F"
# 求交集:SINTER user:A:friends user:E:friends -> 结果为 user:C, user:D

有序集合(Sorted Set / ZSet)

内部实现:SkipList 和 ziplist

在 Set 的基础上,为每个成员关联一个 分数(Score),并按分数排序。

常用场景:

  • 排行榜(Leaderboard): 最经典的应用,按分数、等级、热度排序。
  • 延时队列:将任务到期的时间作为 Score,定时轮询获取已到期的任务。
  • 限流:滑动窗口限流算法,将时间戳作为 Score。
# 游戏排行榜
ZADD game:rank 5000 "player:Jack"
ZADD game:rank 6200 "player:Rose"
ZADD game:rank 4800 "player:Tom"
# 获取前三名:ZREVRANGE game:rank 0 2 WITHSCORES

# 延时任务
# Score为Unix时间戳
ZADD delay_tasks 1714288800 "order_timeout_task_1"

除了上述五大基础类型,Redis 还有几种针对特定场景的“黑科技”:

特殊/高级数据结构 (High-level)

Bitmap (位图)

利用 String 类型的位操作。

场景:海量用户签到、布隆过滤器、统计活跃用户。极度节省空间(1 亿人签到只需要约12MB)。

# 用户签到
# Key: sign:用户ID:年月, Offset: 日期
SETBIT sign:100:202604 1 1  # 4月1日签到
SETBIT sign:100:202604 2 1  # 4月2日签到
BITCOUNT sign:100:202604    # 统计本月签到次数

HyperLogLog

概率算法。

场景:超大规模基数统计(如百万级网页的UV)。它能用固定的 12KB 空间统计 2^64 个元素,误差约0.81%。

# 网站 UV 统计
PFADD website:uv:20260428 "ip_1" "ip_2" "ip_3" ... "ip_1000000"
PFCOUNT website:uv:20260428 # 获取估算去重总数

Geo (地理位置)

场景:附近的人、计算两个经纬度之间的距离、打车软件调度。

# 附近的车
# 添加坐标:GEOADD cars 123.45 67.89 "car_001" 123.89 45.67 "car_002"
# 查找附近5km内的车:GEORADIUS cars 121.47 31.23 5 km

Stream

场景:专业级的消息队列。支持消费组、消息确认 (ACK) 和持久化,是 Redis 5.0 后为了弥补 List 做 MQ 的不足而推出的。

# 持久化流
# 生成消息:XADD mystream * sensor-id "123" temperature "19.8"
# 结果示例:1714288800123-0 (ID包含毫秒时间戳)
# 读取消息:XREAD COUNT 1 STREAMS mystream 0
posted @ 2026-04-27 12:54  我已有个她  阅读(9)  评论(0)    收藏  举报