redis数据结构

redis十大数据类型

Redis 的十大数据结构详解

根据常见的 Redis 文档和社区讨论,Redis 核心提供了多种数据结构(或称为数据类型),其中五种基本类型(String、List、Hash、Set、ZSet)是最基础的,而扩展类型包括 Bitmap、HyperLogLog、GEO、Stream 和 Bitfield。这些通常被归纳为“十大数据结构”,它们在实际应用中覆盖了从简单存储到复杂查询的各种场景。下面我将逐一详细讲解每个数据结构的描述、特点、常见命令、应用场景以及底层实现原理。注意,Redis 的数据类型实际上是针对 value 的设计,而 key 始终是字符串类型。

1. String(字符串)

  • 描述:String 是 Redis 最基础的数据类型,一个键对应一个值,支持存储任意数据,包括文本、数字、图片或序列化对象。值最大可达 512MB,且是二进制安全的(即可以存储任何字节数据,而不限于字符串)。
  • 特点:支持数值操作(如自增/自减)、范围获取和追加。适合简单键值存储。
  • 常见命令
    • 设置值:SET key value [NX|XX] [EX seconds](NX 表示键不存在时设置,XX 表示键存在时设置,EX 设置过期时间)。
    • 获取值:GET key
    • 批量操作:MSET key1 value1 key2 value2MGET key1 key2
    • 数值增减:INCR key(自增1)、DECR key(自减1)、INCRBY key increment
    • 范围操作:GETRANGE key start endSETRANGE key offset value
    • 其他:APPEND key value(追加)、STRLEN key(获取长度)、SETNX key value(分布式锁常用)。
  • 应用场景:缓存(如网页内容)、计数器(如访问量)、分布式锁、限流(如接口调用次数)。
  • 底层原理:使用 SDS(Simple Dynamic String,简单动态字符串)实现,支持三种编码:int(整数型,存储长整型数据)、embstr(嵌入式字符串,≤44字节,键值连续存储,不可修改)、raw(原始字符串,>44字节,键值分离存储,可修改)。SDS 比 C 字符串更高效,避免缓冲区溢出,并支持 O(1) 时间获取长度。

2. List(列表)

  • 描述:List 是一个有序的字符串列表,按插入顺序排序,支持从头部或尾部添加/删除元素。最多可存储 2^32 - 1 个元素(约 42 亿),元素可重复。
  • 特点:支持双端操作,类似于双向链表,但性能更高。
  • 常见命令
    • 插入:LPUSH key value(头部插入)、RPUSH key value(尾部插入)。
    • 获取:LRANGE key start stop(范围获取)、LINDEX key index(按索引获取)。
    • 弹出:LPOP key(头部弹出)、RPOP key(尾部弹出)。
    • 删除:LREM key count value(移除指定元素)。
    • 截取:LTRIM key start stop(保留指定范围)。
    • 移动:RPOPLPUSH source destination(从一个列表尾部弹出并插入另一个头部)。
    • 其他:LSET key index value(修改元素)、LLEN key(获取长度)。
  • 应用场景:消息队列(如生产者-消费者模式)、任务列表、最新消息列表、历史记录。
  • 底层原理:Redis 3.2 后统一使用 quicklist 实现,它是 ziplist(紧凑列表,Redis 7.0 前)或 listpack(Redis 7.0 后)的链表结合。每个 quicklist 节点是一个 listpack,用于压缩存储小列表。配置参数如 list-max-ziplist-size 控制节点大小,list-compress-depth 控制压缩深度,避免大列表的内存浪费。

3. Hash(哈希)

  • 描述:Hash 是一个字符串类型的字段-值映射表,类似于 Java 的 Map 或 Python 的字典。每个 Hash 可存储 2^32 - 1 个键值对(约 42 亿)。
  • 特点:适合存储对象结构,支持部分更新,而非整个替换。
  • 常见命令
    • 设置:HSET key field valueHMSET key field1 value1 field2 value2HSETNX key field value(不存在时设置)。
    • 获取:HGET key fieldHMGET key field1 field2HGETALL key(获取所有字段值)。
    • 删除:HDEL key field
    • 判断:HEXISTS key field
    • 键值操作:HKEYS key(所有字段)、HVALS key(所有值)。
    • 数值增减:HINCRBY key field incrementHINCRBYFLOAT key field increment
  • 应用场景:存储对象(如用户信息、购物车、配置信息),比 String 更节省内存。
  • 底层原理:Redis 7.0 前使用 ziplist(小数据时),7.0 后使用 listpack 或 hashtable。大数据时转为 hashtable(哈希表,使用链地址法解决冲突)。转换阈值:元素数 ≤ hash-max-ziplist-entries(默认 512),字段值长度 ≤ hash-max-ziplist-value(默认 64)。listpack 优化了 ziplist 的连锁更新问题。

4. Set(集合)

  • 描述:Set 是一个无序的字符串集合,元素唯一,不可重复。最多存储 2^32 - 1 个元素,添加/删除/查找复杂度 O(1)。
  • 特点:自动去重,支持集合运算如交并差。
  • 常见命令
    • 添加:SADD key member
    • 获取:SMEMBERS key(所有元素)。
    • 判断:SISMEMBER key member
    • 删除:SREM key member
    • 计数:SCARD key
    • 随机:SRANDMEMBER key [count]SPOP key [count]
    • 移动:SMOVE source destination member
    • 集合运算:SINTER key1 key2(交集)、SUNION key1 key2(并集)、SDIFF key1 key2(差集)。
  • 应用场景:去重(如标签系统)、集合运算(如共同好友)、随机抽取(如抽奖)。
  • 底层原理:Redis 7.2 前使用 intset(整数集合,小整数时)或 hashtable,7.2 后新增 listpack。intset 用于所有元素是整数且 ≤ set-max-intset-entries(默认 512)。listpack 用于小字符串集合(≤ set-max-listpack-entries 默认 128,值长度 ≤ 64)。大数据转为 hashtable。

5. ZSet(有序集合)

  • 描述:ZSet 类似于 Set,但每个元素关联一个 double 类型分数(score),按分数从小到大排序。元素唯一,分数可重复。最多存储 2^32 - 1 个元素。
  • 特点:支持范围查询和排名。
  • 常见命令
    • 添加:ZADD key score member
    • 获取:ZRANGE key start stop [WITHSCORES]ZREVRANGE key start stop(逆序)、ZRANGEBYSCORE key min max
    • 计数:ZCARD keyZCOUNT key min max
    • 删除:ZREM key member
    • 分数操作:ZINCRBY key increment member
    • 排名:ZRANK key memberZREVRANK key member
    • 弹出:ZPOPMIN key [count]ZPOPMAX key [count]
  • 应用场景:排行榜(如游戏分数)、延时队列、访问统计。
  • 底层原理:Redis 7.0 前使用 ziplist,7.0 后使用 listpack 或 skiplist。listpack 用于小数据(元素 ≤ zset-max-listpack-entries 默认 128,值 ≤ 64)。skiplist 是多层有序链表,随机生成层数(最大 32 层),支持 O(log N) 范围查询和插入。

6. Bitmap(位图)

  • 描述:Bitmap 是一个位数组,使用 0/1 表示状态,基于 String 类型实现,支持位级操作。
  • 特点:节省空间,适合大规模二进制数据。
  • 常见命令
    • 设置位:SETBIT key offset value(value 为 0 或 1)。
    • 获取位:GETBIT key offset
    • 计数:BITCOUNT key [start end](统计 1 的个数)。
    • 位运算:BITOP AND|OR|XOR|NOT destkey key [key ...]
  • 应用场景:用户签到统计(如连续登录天数)、活跃用户过滤、二进制状态跟踪。
  • 底层原理:基于 SDS(String 的底层),直接操作二进制位,支持高效的位操作,内存占用低(1 位/元素)。

7. HyperLogLog(基数统计)

  • 描述:HyperLogLog 是一种概率性数据结构,用于估计集合中唯一元素的数量(基数),每个键固定占用 12KB,支持最多 2^64 个元素,误差约 0.81%。
  • 特点:不存储实际元素,只估算数量,节省内存。
  • 常见命令
    • 添加:PFADD key element [element ...]
    • 计数:PFCOUNT key [key ...]
    • 合并:PFMERGE destkey sourcekey [sourcekey ...]
  • 应用场景:网站 UV(独立访客)统计、DAU(日活跃用户)、商品浏览量估算。
  • 底层原理:基于概率算法(如 LogLog 计数),使用固定桶数组记录最大零尾数,估算基数。底层是 SDS。

8. GEO(地理空间)

  • 描述:GEO 用于存储地理位置信息,支持坐标存储、距离计算和范围查询。基于 ZSet 实现,使用 GeoHash 编码经纬度为分数。
  • 特点:高效的位置查询。
  • 常见命令
    • 添加:GEOADD key longitude latitude member
    • 获取位置:GEOPOS key member
    • 距离:GEODIST key member1 member2 [unit](unit 如 km)。
    • 范围查询:GEORADIUS key longitude latitude radius unit [WITHCOORD] [WITHDIST]GEORADIUSBYMEMBER key member radius unit
  • 应用场景:附近的人/店搜索、距离计算、LBS(位置服务)。
  • 底层原理:基于 ZSet,GeoHash 将经纬度转换为一维分数,支持 O(log N) 查询。

9. Stream(流)

  • 描述:Stream 是 Redis 5.0 引入的消息队列结构,支持持久化、自动 ID 生成、消费者组和 ACK 机制。每个消息是键值对列表。
  • 特点:类似于 Kafka 的日志流,支持阻塞读取和分组消费。
  • 常见命令
    • 添加:XADD key ID field value [field value ...](ID 可为 * 自动生成)。
    • 范围获取:XRANGE key start end [COUNT count]XREVRANGE key end start
    • 删除:XDEL key ID
    • 长度:XLEN key
    • 修剪:XTRIM key MAXLEN threshold
    • 读取:XREAD [BLOCK milliseconds] STREAMS key ID
    • 消费者组:XGROUP CREATE key group IDXREADGROUP GROUP group consumer STREAMS key ID
  • 应用场景:消息队列、操作日志、数据同步、实时处理。
  • 底层原理:使用 radix tree(压缩前缀树,rax)存储消息 ID,值用 listpack 存储。rax 支持快速插入/删除/定位。

10. Bitfield(位域)

  • 描述:Bitfield 是对 String 的位级扩展,支持任意位长度的 signed/unsigned 整数存取和操作。
  • 特点:精细位控制,适合自定义位字段。
  • 常见命令
    • 操作:BITFIELD key [GET type offset] [SET type offset value] [INCRBY type offset increment] [OVERFLOW WRAP|SAT|FAIL](type 如 i8/u16 表示 signed/unsigned 位宽)。
  • 应用场景:存储自定义位数据,如游戏状态、配置标志。
  • 底层原理:基于 String 的 SDS,直接在二进制层面操作位,支持溢出策略(WRAP 循环、SAT 饱和、FAIL 失败)。
[up主专用,视频内嵌代码贴在这]