Redis 数据类型详解

44 阅读4分钟

通用对象模型

typedef struct redisObject {
    unsigned type:4;        // 数据类型(String、Hash、List等)
    unsigned encoding:4;    // 实际编码方式
    unsigned lru:24;        // 最近访问时间,用于LRU淘汰
    int refcount;           // 引用计数,用于内存回收
    void *ptr;              // 指向实际数据结构的指针
} robj;c

Redis的每个键值不是直接保存的而是使用一个redisObject结构体封装保存的。

数据类型

string

  • 适用场景: 用户信息,计数,商品数据等缓存

  • 设计原理:

    • string有三种编码方式

      • int => 整数 不额外分配内存,
      • embstr => <=44b 单次内存分配 redisOBJ & SDS连续存储
      • raw => 大于44b 两次内存分配 Obj & SDS分开存储
    • SDS (动态字符) : 内存预分配:扩容策略(小于1MB时翻倍,大于1MB时每次加1MB)

  • 特性:

    • 原子性操作: Redis中,由于单线程模型,每个命令都是原子执行的。单线程模型保证每个命令执行不被中断 (decrby,incr操作都是原子性,计数与库存扣减等场景都必须要保证其原子性)

    • 分布式锁 SetNx :

      # 如果lock:order不存在,则设置值为1,返回1(成功)
      # 如果lock:order已存在,则不设置,返回0(失败)
      SETNX lock:order 1;
      
      
      
         def acquire(self, lock_key, expire_time=30):
              """
              获取分布式锁
              :param lock_key: 锁的键名
              :param expire_time: 锁的过期时间(秒)
              :return: 是否获取成功
              """
              # 使用SET with NX和EX参数,保证原子性
              result = self.redis.set(
                  lock_key, 
                  "locked", 
                  nx=True, 
                  ex=expire_time
              )
              return result is not None
          
          def release(self, lock_key):
              """释放锁"""
              self.redis.delete(lock_key)
      

Hash

  • 适用场景: 用户信息,商品详情等具有多属性的实体(购物车之类)

  • 设计原理 :

    • 底层为两种编码方式:ziplist(压缩列表,适合小数据量,默认val长度不超过64字节,field数量不超过512),HashTable(哈希表,当不满足ziplist会自动转化为hashtable,扩展或收缩时需要rehash来完成操作)
  • 特性:优化结构化数据的存储与访问 ,可以单独对属性进行读写,减少序列化操作整个对象

List

  • 适用场景:文章列表,热点推文等
  • 设计原理: redis3.2+版本后list默认的底层实现为QuickList(ziplist和linkedlist结合实现,平衡内存效率和查询性能)。
  • 特性:基于双向有序列表 可重复的集合两端操作速度快 (O(1))

Set

  • 适用场景:好友关系(共同好友) ,投票抽奖类的业务

  • 设计原理:

    • 两种编码方式:intSet (整数集合,元素都为整数,数量不超过默认的512),HashTable(当不满足intSet时,使用hashtable,value为null,只存key元素)
  • 特性: 无序唯一的集合,可以提供搞笑的集合运算(交集,差集,并集)

Sorted Set

  • 适用场景: 排行榜之类 延迟队列实现(执行时间作为score)

  • 设计原理:

    • 两种编码方式:zipList(元素为数量小于默认128,长度小于默认64字节)SkipLIst + Dict (跳跃表&字典混合结构,跳跃表将数据顺序用纵向的层级关系,高层指针跨越节点提升查找效率 O(log n),dict提供O(1)的Zscore操作)
  • 特性: 唯一且有序的集合,每个元素关联一个score作为排序依据。

BitMap

  • 适用场景:签到,大数据量的统计(活跃用户)
  • 设计原理:本质时string,使用sds存储位数据,使用RAW编码,自动补0扩展,提供位级操作接口
  • 特性: 在字符基础上进行位操作节省内存空间

HyperLogLog

  • 适用场景:大规模去重统计(网站统计UV PV等)
  • 设计原理:基于12kb的固定大小寄存器数组,使用14bit的寄存器(可计算2的14次方 16384),对输入值进行hash,利用前导0的数量进行估计基数,使用调和平均数提高准确性,标准误差0.81%
  • 特性:用于基数估计,用极小的且固定的内存空间(约12kb)统计海量数据,结果有一定误差。

梳理xmind

whiteboard_exported_image.png