Post

Redis data

Redis 数据类型

1. String 类型

含义

  • Redis 中最基本的数据类型,字符串不仅可以存储普通字符串,还可以存储数字(整数、浮点数)以及二进制数据(如图片、音频等)
  • 每个 String 类型的值最大为 512 MB

底层实现原理

  • 简单动态字符串(SDS):Redis 中的字符串是基于 SDS 实现的,而不是 C 语言的 char*
    • SDS 支持动态扩容,当字符串长度发生变化时会自动调整空间
    • SDS 结构包含了字符串长度信息,避免了 C 字符串以 \0 结尾导致的性能问题
  • 如果存储的是整数,Redis 可能会使用整数编码优化存储

常见场景

  1. 缓存数据:存储简单的键值对,如用户配置、网页 HTML 内容等
  2. 计数器:如页面浏览量(PV)、点赞数等,使用 INCRINCRBY 操作
  3. 分布式锁:通过 SET key value NX EX seconds 实现分布式锁
  4. 存储二进制数据:如图片、音频等文件的小片段

2. Hash 类型

含义

  • 用于存储键值对集合的结构,适合存储对象(如用户信息)
  • 每个 Hash 键对应一个字段和值的集合,支持字段级别操作

底层实现原理

  • 小型 Hash:
    • 使用 ziplist(压缩列表) 存储:当字段数量少于 hash-max-ziplist-entries(默认 512),且每个字段值小于 hash-max-ziplist-value(默认 64 字节)
  • 大型 Hash:
    • 使用 hashtable(哈希表) 存储:当字段数量或字段值超过阈值时,自动转为哈希表

常见场景

  1. 存储对象信息:如用户资料(user:id -> name, age, email
  2. 减少内存消耗:通过将多个属性存储在一个 Hash 中,减少 Redis 键的数量
  3. 数据分析:存储统计信息,例如用户行为(user:stats -> views, clicks

3. List 类型

含义

  • 一个有序的链表,可以在头部(LPUSH)或尾部(RPUSH)插入数据,支持按索引读取(LINDEX
  • 适合存储有序的数据集合

底层实现原理

  • 小型 List:
    • 使用 ziplist(压缩列表):当列表元素数量少于 list-max-ziplist-entries(默认 512),且每个元素小于 list-max-ziplist-value(默认 64 字节)
  • 大型 List:
    • 使用 quicklist(快速列表),是一种压缩列表和双向链表的混合体,既支持快速插入删除,又节省内存

常见场景

  1. 任务队列:如消息队列、异步任务(LPUSH/BRPOP 实现)
  2. 时间序列数据:如日志记录、用户活动记录等
  3. 排行榜:按时间排序的数据集合

4. Set 类型

含义

  • 无序的集合,支持自动去重,常用于存储唯一值
  • 提供交集、并集、差集操作

底层实现原理

  • 小型 Set:
    • 使用 intset(整数集合):当集合内的元素均为整数且数量较少(默认小于 512)
  • 大型 Set:
    • 使用 hashtable(哈希表):当集合数量较多或包含非整数元素时

常见场景

  1. 标签系统:存储用户的兴趣标签(user:tags -> tag1, tag2
  2. 好友关系:如共同好友(交集)、推荐好友(差集)
  3. 去重功能:如统计唯一用户 IP、唯一行为事件

5. Sorted Set 类型

含义

  • 有序集合,类似于 Set,但每个元素关联一个 分数(score),通过分数排序
  • 适合存储需要排序的数据

底层实现原理

  • 使用 跳表(SkipList)hashtable 实现:
    • 跳表用于实现按分数排序
    • 哈希表用于快速查找元素

常见场景

  1. 排行榜:如游戏排名、文章热度
  2. 延时任务:通过分数表示执行时间,按时间顺序取任务
  3. 日志记录:排序存储用户行为日志,按时间戳排序

6. Bitmap 类型

含义

  • 位数组,用于存储二进制数据,每个位(bit)表示一个状态(0 或 1),适合存储大量布尔值

底层实现原理

  • 基于 字符串(String) 实现,按位操作,通过偏移量存储每个位的数据

常见场景

  1. 签到功能:如用户每日签到(1 表示已签到,0 表示未签到)
  2. 活跃用户统计:记录某段时间内的活跃用户
  3. 大规模状态存储:如在线状态、是否完成任务等

7. HyperLogLog 类型

含义

  • 一种概率性数据结构,用于基数统计(不精确,但节省内存)
  • 可统计数十亿数据中不重复的元素个数,误差率约为 0.81%

底层实现原理

  • 基于 HyperLogLog 算法
    • 使用固定的 12 KB 内存存储分桶结构
    • 通过哈希函数将数据分散到多个桶,统计桶中的最大值估算基数

常见场景

  1. UV 统计:统计网站的日活跃用户数
  2. 去重统计:如统计广告点击的去重用户
  3. 大规模数据分析:如统计日志中的唯一 IP

8. Geospatial 类型

含义

  • 用于存储地理位置信息,支持基于经纬度的距离计算和范围查询

底层实现原理

  • 基于 Sorted Set 实现:
    • 使用 GeoHash 算法将地理坐标编码为一个整数值
    • 分数表示坐标值,跳表支持排序和范围查询

常见场景

  1. LBS 服务:如查找附近的人、附近的商家
  2. 路径规划:计算两个位置之间的距离
  3. 物流配送:确定配送范围内的订单

9. Stream 类型

含义

  • 用于处理消息队列,类似于 Kafka 的消息流,支持多生产者、多消费者
  • 支持消息持久化、分组消费、消费确认

底层实现原理

  • 基于 双向链表Radix Tree(压缩树) 实现:
    • 消息 ID 是时间戳 + 序列号,保证全局唯一性
    • 使用 Radix Tree 高效存储和检索

常见场景

  1. 日志处理:如实时日志采集、用户行为分析
  2. 消息队列:构建轻量级的消息队列系统
  3. 事件流:如订单状态流转、实时监控数据

总结

数据类型 含义 底层实现 常见场景
String 基本键值对存储 SDS 缓存、计数器、分布式锁
Hash 存储对象属性 Ziplist/Hashtable 用户信息、统计数据
List 有序链表 Ziplist/Quicklist 消息队列、时间序列
Set 无序集合,自动去重 Intset/Hashtable 标签系统、好友关系、去重
Sorted Set 有序集合,按分数排序 SkipList 排行榜、延时任务
Bitmap 位数组,存储布尔值 String 签到、状态存储、活跃统计
HyperLogLog 基数统计,支持去重 HyperLogLog UV 统计、大规模数据分析
Geospatial 地理位置存储与计算 GeoHash + ZSet 附近的人、物流路径规划
Stream 消息队列,支持持久化 Radix Tree 日志处理、事件流、消息队列
This post is licensed under CC BY 4.0 by the author.