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求可能认识的人。 - 抽奖系统:
SPOP或SRANDMEMBER随机抽取中奖者。
# 标签系统
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
本文来自博客园,作者:我已有个她,转载请注明原文链接:https://www.cnblogs.com/gitgud/p/19936451
浙公网安备 33010602011771号