写点什么

redis 数据类型以及它们的底层实现数据结构

作者:想要飞的猪
  • 2022-09-10
    广东
  • 本文字数:2494 字

    阅读完需:约 8 分钟

  1. String 字符串类型应用场景:

  2. key 与 value 键值对时

  3. incr 用于乐观锁(incr:递增数字,可用于实现乐观锁 watch 事务)

  4. senx 分布式锁的应用

  5. list 列表类型列表是双向链表,可以之间在头尾添加或者获取数据,速度很快,最多有 2^32-1 个(40 亿)用于场景:

  6. 当作栈或者是队列,

  7. 可用于各种列表,比如用户列表,商品列表,评论列表等等常用命令:lpush:从左侧插入列表;rpush:从右侧插入列表;lpop:从列表左侧取出;rpop:从列表右侧取出;lindex:获取列表下标位 index 的元素;lrange:截取列表中的元素

  8. set 集合类型无序集合(类似与 list),集合中最大的成员数位 2^32-1 个 用于场景:


  • 适用与不重复并且没有顺序的集合(关注人数,粉丝数量等等)

  • 求两个集合的并集、交集等(共同好友)

  • 随机抽奖等等常用命令:sadd:添加新成员;srem:删除指定成员;spop:随机取出一个并且删除;sinter:求交集;sunion:求并集(比如一个用户多个角色所拥有的所有的权限)


  1. sortset 有序集合类型有序列表(元素本身是没有序的,关联一个 score 根据 score 排序)适用场景:可以用于一些集合的排序(排行榜,点击量排行榜等待)注:多维度的排行榜可以把 score 分为高位 16 与低位 16 位;高 16 位表示优先的维度,低 1 位表示第二个维度,维度只能同升同降常用命令:zadd:添加新元素;zcard:获取集合中所有的元素;zrang:获取集合中指定区间的元素,按 score 从小到大的顺序排序;zrevrange:获取集合中指定区间的元素,按照从大到小的顺序排序;

  2. hash 散列表类型 redis hash 是 string 类型的 field 和值的映射表,它提供了字段与字段值的映射。适用场景:

  3. 对象的存储

  4. 数据库表的映射常用命令:hset:赋值,不区分新增或者是修改;hmset:批量赋值;hsetx:赋值,如果存在则不操作;hexsits:查看莫个 field 是否存在;hget:获取 field 对应的值;hmget:批量获取 field 的值;hincrby:指定莫个字段自增;hlen:获取所有字段的数量。

  5. bitmap 位图类型 bitmap 是进行位操作,通过 bit 位来表示某个元素的值或者是状态,bitmap 会极大的节省空间;适用场景:

  6. 用户每月的签到数:用户 Id 为 key,日期为偏移量,签到时,bit 位置为 1;

  7. 统计活跃用户:时间位 key,用户 id 为偏移量,活跃的置为 1

  8. 查询用户的在线状态:时间为 key,用户 id 为偏移量,1 表示在线常用命令:setbit:设置 key 在 offset 处的偏移量;getbit:获取 key 在 offset 出的状态值;bitcount:获取 key 的 bit 为 1 的数量。

  9. geo 地理位置类型地理位置:主要时与地理位置相关,可以用于附件好友等一些场景

  10. stream 数据流类型 stream 是 Redis5.0 后新增的数据结构,用于可持久化的消息队列。


底层数据结构:redisObject


typedef struct redisObject {     unsigned type:4;//类型 五种对象类型    unsigned encoding:4;//编码     void *ptr;//指向底层实现数据结构的指针     int refcount;//引用计数     unsigned lru:LRU_BITS; //LRU_BITS为24bit 记录最后一次被命令程序访问的时间 }robj;
复制代码


type 表示对象的类型,占 4 位:


REDIS_STRING(字符串)、REDIS_LIST(列表)、REDIS_HASH(哈希)、REDIS_SET(集合)、REDIS_ZSET(有序集合)


可以适用命令 查看:type key


127.0.0.1:6379> type a1 string
复制代码


encoding redis 编码、占 4 位:


每个对象都有不同的编码,redis 可以根据对象情况使用不同的编码类型,大大的提高了 redis 的灵活性和效率;


可以使用命令:object encoding key 查看


127.0.0.1:6379> object encoding a1"int"
复制代码


24 位 LRU :高 16 位记录访问时间,低 8 位记录访问的次数


ptr:指针只想具体的数据,比如 set a 11,ptr 指向包含 11 的 SDS;


7 种类型:


  1. SDS(simple Dynamic String),用于存储字符串与数字;

  2. sds 优势:① 获取字符串长度位 O(1),② 防止溢出,可以在造成溢出前做扩容,③ 可以存储二进制数据,用长度判断结束(c 语言中\0 空字符串,二进制包括空字符串)

  3. 跳跃表

  4. 跳跃表的基本思想:把有序链表分层,每一层都是一个有序链表。

  5. 查找从上往下,最高层往下找,当达到某个节点时,如果节点的值大于要查找的值或者时 null,则往下一层继续往后找

  6. 删除先找到要删除的元素,然后删除每一层即可。

  7. 新增插入到对应的链表位置,然后通过抛硬币的形式决定是否插入上一层。

  8. 字典字典 dict 有称为散列表 hash,是用来存储键值对的一种数据结构,redis 整个数据库是用字段来存储的额。(K-V 结构),对 redis 进行 CURD 操作其实就是对子弟哎中的数据进行的 CURD 操作。

  9. 压缩列表压缩列表(ziplist)是由一系列特殊编码的额连续内存块组成的顺序型数据结构,节省内存,是一个字节数组,可以包含多个节点(entry),每个节点可以保存一个字节数组或一个整数。应用场景:sortted-set 和 hash 元素个数少且是小整数或者短字符串(直接使用)。list 用快速链表(quicklist)数据 结构存储,而快速链表是双向列表与压缩列表的额组合。

  10. 整数集合整数集合(intset)是一个有序的(整数升序)、存储整数的连续存储结构 typedef struct intset{//编码方式 uint32_t encoding;//集合包含的元素数量 uint32_t length;//保存元素的数组 int8_t contents[];}intset;应用场景:可以保存类型为 int16_t、int32_t 或者 int64_t 的整数值,并且保证集合中不会出现重复元素。

  11. 快速 列表快速列表(quicklist)是 Redis 底层重要的数据结构。是列表的底层实现。(在 Redis3.2 之前,Redis 采用双向链表(adlist)和压缩列表(ziplist)实现。)在 Redis3.2 以后结合 adlist 和 ziplist 的优势 Redis 设计出了 quicklist。双向链表优势:

  12. 双向:链表具有前置节点和后置节点的引用,获取这两个节点时间复杂度都为 O(1)。

  13. 普通链表(单链表):节点类保留下一节点的引用。链表类只保留头节点的引用,只能从头节点插入删除

  14. 无环:表头节点的 prev 指针和表尾节点的 next 指针都指向 NULL,对链表的访问都是以 NULL 结 束。环状:头的前一个节点指向尾节点

  15. 带链表长度计数器:通过 len 属性获取链表长度的时间复杂度为 O(1)。

  16. 多态:链表节点使用 void* 指针来保存节点值,可以保存各种不同类型的值。快速列表 quicklist 是一个双向链表,链表中的每个节点时一个 ziplist 结构。quicklist 中的每个节点 ziplist 都能够存储多个数据元素。

  17. 流对象 stream 主要由:消息、生产者、消费者和消费组构成。

用户头像

还未添加个人签名 2020-06-05 加入

还未添加个人简介

评论

发布
暂无评论
redis数据类型以及它们的底层实现数据结构_想要飞的猪_InfoQ写作社区