redis中的数据结构

介绍

  redis中共有8种数据结构,其中常用的有5种。这些数据结构基本采用了底层的8种数据结构实现。

常用的5种数据结构

  • String(字符串)
  • Hash(哈希)
  • List(链表)
  • Set(集合)
  • ZSet(有序集合)

不常用的3种数据结构

  • geospatial(地理位置)
  • hyperloglog
  • Bitmap(位图)

底层使用的数据结构

  • SDS:简单动态字符串,支持动态扩容的字节数组
  • list:链表
  • dict:使用双哈希表实现的, 支持平滑扩容的字典
  • skiplist:附加了后向指针的跳跃表
  • intset:用于存储整数数值集合的自有结构
  • ziplist:压缩列表,一种实现上类似于TLV,但比TLV复杂的, 用于存储任意数据的有序序列的数据结构
  • quicklist:一种以ziplist作为结点的双链表结构, 实现的非常不错
  • zipmap:一种用于在小规模场合使用的轻量级字典结构

redis的五种常用的数据结构


数据结构

String

  String是redis中最基础的数据类型,普通的kay/value都可以归为此类,value也可以是数字。
  redis的String是二进制安全的,可以包含任何数据,如字符串,图片,序列化数据。
  使用get、set、del、incr、decr等命令。
  String底层采用SDS实现。

特性

  • redis为字符串分配空间的次数,是小于等于字符串的长度N,而原C语言中的分配原则必为N。降低了分配次数提高了追加速度,代价就是多占用一些内存空间,且这些空间不会自动释放。
  • 二进制安全的。
  • 高效的计算字符串长度。
  • 高效的追加字符串操作。

场景

  • 缓存:经典使用场景,把常用信息,字符串,图片或者视频等信息放到redis中,redis作为缓存层,mysql做持久化层,降低mysql的读写压力。
  • 计数器:redis是单线程模型,一个命令执行完才会执行下一个,同时数据可以一步落地到其他的数据源。
  • session:常见方案spring session + redis实现session共享。

List

  Lists就是链表,在redis中的List是一个双端链表,是有序的,value可以重复,可以通过下标取出对应的value值,左右两边都能进行插入和删除数据。
  在3.2版本之前,redis中采用ziplist和linkedlist实现,在3.2版本之后采用quicklist实现。
  3.2版本之前,列表对象满足如下条件时采用ziplist,否则采用linkedlist。

  • 列表对象保存的所有字符串元素的长度都小于64字节
  • 列表对象保存的元素数量小于512个

使用特点

  • lpush+lpop=Stack(栈)
  • lpush+rpop=Queue(队列)
  • lpush+ltrim=Capped Collection(有限集合)
  • lpush+brpop=Message Queue(消息队列)

场景

  • timeline:时间轴,按时间的顺序。
  • 消息队列。

Hash

  redis的散列可以存储多个键值对之间的映射,散列存储的值既可以是字符串也可以是数字值,并且用户同样可以对散列存储的数字值执行自增操作或者自减操作。散列可以看作是一个文档或关系数据库里的一行。
  使用所有hash的命令都是h开头的hget、hset、hdel等。
  底层有两种数据结构实现:

  • 一种是ziplist,当存储的数据超过配置的阀值时就是转用hashtable的结构。使用ziplist的条件是:
    • 当键的个数小于hash-max-ziplist-entries(默认512)
    • 当所有值都小于hash-max-ziplist-value(默认64)
  • 另一种就是hashtable。这种结构的时间复杂度为O(1),但是会消耗比较多的内存空间。

场景

  • 缓存: 能直观,相比string更节省空间,的维护缓存信息,如用户信息,视频信息等。

Set

  集合类型也是用来保存多个字符串的元素。
  与列表的不同之处:

  • 不允许有重复的元素
  • 集合中的元素是无序的,不能通过索引下标获取元素
  • 支持集合间的操作,可以取多个集合取交集、并集、差集

  集合采用HashTable来实现元素不可重复。在hashtable中将set的值作为hashtable的键,而值则为空。
  使用命令都是以s开头的sset、srem、scard、smembers、sismember。

场景

  • 标签:给用户添加标签,或者用户给消息添加标签,这样有同一标签或者类似标签的可以给推荐关注的事或者关注的人。
  • 点赞,或点踩,收藏等,可以放到set中实现。

ZSet

  有序集合和散列一样,都用于存储键值对:有序集合的键被称为成员(member),每个成员都是各不相同的。有序集合的值则被称为分值(score),分值必须为浮点数,有序集合中根据分数进行排序。
  有序集合是redis里面唯一一个既可以根据成员访问元素(这一点和散列一样),又可以根据分值以及分值的排列顺序访问元素的结构。
  使用有序集合的命令都是以z开头zadd、zrange、zscore。
  底层有两种数据结构实现:

  • 第一种是压缩列表,ziplist
  • 第二种是skiplist和dict的结合

场景

  • 排行榜:有序集合经典使用场景。例如小说视频等网站需要对用户上传的小说视频做排行榜,榜单可以按照用户关注数,更新时间,字数等打分,做排行。

参考文献 & 鸣谢