Redis数据类型及实现

先列举:

五大类型:String、List、Hash、Set、Sorted Set、

其它: pubsub(应该算独立功能吧?)、HyperLogLog(2.8.9+)、Geo(3.2+)、Stream(redis5+)

* * * redisObject * * *

redis中实现了很多自定义数据结构,但redis并没有直接使用这些结构来构建k-v系统,而是使用这些结构创建了一个对象系统;这个对象系统包含了上面我们列举的字符串对象、列表对象、哈希对象、集合对象等等;

注:本文假定阅读者对于redis底层数据结构及实现有一定了解

注:底层数据结构包括: 简单动态字符串SDS、链表linkedlist、跳跃表skiplist、压缩列表ziplist、整数集合等等

使用对象的优点

  • 执行命令前,方便根据对象类型判断一个对象是否可执行给定的命令;
  • 针对不同的使用场景,为对象设置多种不同的数据结构实现,以优化性能;
  • redis的对象系统还实现了基于引用计数技术的内存回收机制;
  • 通过引用计数,还实现了对象共享机制;
  • redis的对象带有访问时间记录信息,可用于计算数据库键的空转时长,以辅助实现maxmemory;

redisObject

  • type:类型
    • REDIS_STRING: string
    • REDIS_LIST: list
    • REDIS_HASH: hash
    • REDIS_SET: set
    • REDIS_ZSET: zset
  • encoding:编码,即底层数据结构的类型;
    • REDIS_ENCODING_INT:int = long型整数
    • REDIS_ENCODING_EMBSTR:embstr = embstr编码的SDS
    • REDIS_ENCODING_RAW:raw = SDS
    • REDIS_ENCODING_HT:hashtable = 字典(哈希表)
    • REDIS_ENCODING_LINKEDLIST:linkedlist = 链表
    • REDIS_ENCODING_ZIPLIST:ziplist = 压缩列表
    • REDIS_ENCODING_INTSET:intset = 整数集合
    • REDIS_ENCODING_SKIPLIST:skiplist = 跳跃表
  • ptr:指向底层数据结构实现的指针;

说明: redis是一个键值对系统,它的键总是字符串对象,值为上述类型中声明的对象类型(新版本有扩充),使用type命令可查看数据库键的类型,实际就是数据库键对应的值的类型;


-------- 快乐的分割线-------下面介绍五大类型 ----------------


String 字符串

redisObject的type为REDIS_STRING,用type命令查询,显示string,编码表示底层数据结构:

  • int: 如果一个字符串对像保存的是整数值,且该值可用long类型来表示,那么该对象会将整数值保存在ptr属性中(void*转换为long),并将encoding设置为int
  • raw:字符串值(含浮点型),且长度大于32Byte(默认),那字符串对象将使用一个SDS来保存这个值,并将encoding设置为raw
  • embstr:字符串值(含浮点型),且长度小于等于32字节,则使用embstr编码的方式来保存

注1:embstr是一种专门保存短字符串的优化编码,与raw一样使用redisObject+sdshdr结构,区别是,raw调用两次内存分配函数来分别创建redisObject结构和sdshdr结构,而embstr则调用一次内存分配函数来分配一块连续的内存空间,该空间依次包含这两种结构

注2:浮点型数据,在redis也是做为字符串对象保存的,保存或者计算时会有一个类型转换的过程

List 列表

可以用ziplistlinkedlist表示,后来用quicklist(3.2+)

  • ziplist 满足以下条件时使用压缩列表做为list的底层实现:
    • 所有元素字符串长度都小于64Byte(默认值)
    • 元素数量小于512
  • linkedlist 不满足使用ziplist的条件时,使用linkedlist
  • quicklist redis3.2开始支持,是一个由ziplist组成的双端列表,链表的每一个节点都是一个ziplist,貌似3.2之后,list只用quicklist结构实现

list-max-ziplist-size:每个ziplist(即quicklist的节点)大小,默认-2,此值可正可负,其中正数表示每个压缩列表中存放的最大元素个数,如果是负数,表示按字节数来限定元素个数:

  • -1 每个节点的ziplist字节大小不能超过4kb
  • -2 每个节点的ziplist字节大小不能超过8kb(默认值)
  • -3 每个节点的ziplist字节大小不能超过16kb
  • -4 每个节点的ziplist字节大小不能超过32kb
  • -5 每个节点的ziplist字节大小不能超过64kb

Hash 哈希

编码为ziplisthashtable

  • ziplist 用两个ziplist节点分别表示键和值,添加键值对时,先将键节点推入到表尾,再将值节点推入到表尾,因些键值对总是紧挨着且先加入的在表头方向; 满足如下条件时使用ziplist做底层实现:
    • 所有键值对的键和值字符串的长度全部小于64Byte(默认值,配置项:hash-max-ziplist-value
    • 键值对数量小于512(默认值,配置项:hash-max-ziplist-entries
  • hashtable 不满足使用ziplist的条件时,将使用hashtable做为底层结构

Set 集合

集合对象的编码可以是intset或者hashtable

  • intset 满足以下条件时用作集合的底层实现:
    • 集合对象保存的所有元素值都是整数值
    • 元素数量不超过512(默认值,配置项:set-max-intset-entries
  • hashtable 不适用intset时,使用hashtable做为底层实现,使用hashtable时,只使用键,值为Null,类似于java的HashSet

Sorted Set 有序集合

有序集合的编码可以是ziplistskiplist

  • ziplist 使用ziplist实现时,每个有序集合元素使用挨在一起的两个ziplistNode表示,第一个表示元素成员member,第二个表示分值score;ziplist中的集合元素按分值从小到大排列,小的靠近表头方向,大的靠近表尾方向;满足如下条件时使用:
    • 元素数量小于128(默认值,配置项:zset-max-ziplist-entries
    • 所有元素成员的长度小于64(默认值,配置项:zset-max-ziplist-value
  • skiplist 使用zset结构做为底层实现,每个zset同时包含一个字典dict和一个跳跃表skiplist:
    • skiplist 按分值从小到大保存了有序集合的元素,保证有序,提高范围型操作性能
    • dict 字典则是为每个元素创建了成员到分值的映射,提供快速查找性能

注:编码为skiplist时,跳跃表和字典会共享成员及分值,内存中只占一分,因为不存在内存浪费;


----- 快乐的分割线 -------- 下面其它类型,还没好好研究完---------


pubsub 发布/订阅

发布/订阅似乎是一项独立功能,不能算一种数据类型,不过从使用上差不多,估且也算在这儿吧;

redis的发布/订阅功能分为两类:频道的发布/订阅及模式的发布/订阅;redis的服务器在redis内部用redisServer结构表示,而发布订阅的实现,依赖于redisServer中的两个属性:

  • 频道(channel) pubsub_channels字典,字典的键表示被订阅的频道,而值是一个链表,存储了所有订阅该频道的客户端;
    • 订阅:定位到频道的订阅链表,在表尾添加一个含订阅客户端的节点
    • 退订:定位到频道的订阅链表,遍历,找到含退订客户端的节点,删除
    • 发布:定位到频道的订阅链表,遍历,依次发消息
  • 模式(patter) pubsub_patterns 链表,每个节点都包含一个pubsubPattern结构,该结构中存储了订阅模式的客户端和订阅的模式;
    • 订阅:创建一个pubsubPattern结构,添加到pubsub_patterns 链表尾
    • 退订:遍历pubsub_patterns,找到含要退订的模式和客户端的节点,删除
    • 发布:遍历pubsub_patterns,向模式匹配的客户发消息

注:订阅将阻塞线程,应该在独立线程独立客户端中使用;

HyperLogLog

使用type查询一个HyperLogLog类型的值,是string,似乎,是基于string结构实现的HyperLogLog功能?待探究

Geo

Stream

尚未研究,且目前5.0版本中,作者不建议在生产环境中使用stream,所以学习后再补充


-------- 快乐的分割线------- 知识扩展 ----------------


转载于:https://my.oschina.net/u/2407208/blog/3009667

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值