清淨
  • Java

    • Java 基础
  • 框架

    • Flyway
    • MapStruct
    • Spring Cloud
  • 中间件

    • Elasticsearch
    • Redis
    • RabbitMQ
    • Kafka
  • 三剑客

    • HTML
    • CSS
    • JavaScript
  • 进阶

    • jQuery
    • ECMAScript6
    • TypeScript
  • Vue

    • Vue2
    • Vue3
    • VuePress
  • Linux
  • Jenkins
  • Maven
  • MySQL
  • 插件工具
  • 代码集成
  • 其它

    • 数据结构与算法
    • 计算机网络
    • 操作系统
    • 设计模式
迁移日志
订阅号
微信订阅号
微信订阅号
GitHub
  • Java

    • Java 基础
  • 框架

    • Flyway
    • MapStruct
    • Spring Cloud
  • 中间件

    • Elasticsearch
    • Redis
    • RabbitMQ
    • Kafka
  • 三剑客

    • HTML
    • CSS
    • JavaScript
  • 进阶

    • jQuery
    • ECMAScript6
    • TypeScript
  • Vue

    • Vue2
    • Vue3
    • VuePress
  • Linux
  • Jenkins
  • Maven
  • MySQL
  • 插件工具
  • 代码集成
  • 其它

    • 数据结构与算法
    • 计算机网络
    • 操作系统
    • 设计模式
迁移日志
订阅号
微信订阅号
微信订阅号
GitHub
  • Redis

    • 简介
    • 安装
    • Redis 配置
    • 数据类型
    • Lua 脚本
    • Java 客户端
    • 实战

      • 短信登录
      • 查询缓存
      • 缓存穿透
      • 缓存击穿
      • 缓存雪崩
      • 全局唯一 ID
      • 超卖问题
      • 一人一单
      • 分布式锁
      • Redisson
      • 异步秒杀
      • 消息队列
      • 签到(BitMap)
      • UV 统计
    • 持久化
    • 集群

      • 主从集群
      • 哨兵集群
      • 分片(Cluster)集群
    • 最佳实践

      • Key-Value 设计
      • 服务端配置
    • 底层数据结构

      • 动态字符串 SDS
      • IntSet
      • Dict
      • ZipList
      • QuickList
      • SkipList
      • RedisObject
    • 数据类型底层实现

      • String
      • List
      • Set
      • ZSet
      • Hash
    • 内存管理策略

IntSet

IntSet 是 Redis 中 set 集合的一种实现方式,基于整数数组实现,具备长度可变、有序、不重复等特征。

其结构如下:

typedef struct intset {
    // 编码方式,支持存放 16 位、32 位、64 位整数。
    // 数组中的每个元素都使用相同的编码方式,这样做是为了方便寻址。寻址的计算公式就是 strat_addr + (encoding * array_index)
    uint32_t encoding;
    // 元素个数
    uint32_t length;
    // 整数数组,保存集合中第一个元素的起始地址
    int8_t contents[];
} intset;

在保存元素时,Redis 会按照升序的方式对元素进行排序。如下:

20250428131922

可能你已经注意到了,如果我之前采用的编码方式是 INT_16,也就是每个数字占用 2 个 字节,但是现在我要插入一个 50000 的数字,显然它超过了 215 - 1 = 32767。所以,这时候,数组需要扩容以改变每个数字的编码方式。扩容后,显然需要使用 INT_32 来存储,也就是每个数字占用 4 个字节。扩容流程如下:

20250428133230

IntSet 在插入数据的时候会先判断数据是否存在,如果已经存在了,就不会插入了(使用的是二分查找)。

想要编辑此页?
上次更新: 2025/5/11 19:09
贡献者: Junfeng Dai
←动态字符串 SDSDict→
[ 纸上得来终觉浅绝知此事要躬行 ]
Copyright © 2021-present Junfeng Dai
蜀ICP备2021009537号