请选择 进入手机版 | 继续访问电脑版

[Redis] 详解Redis数据范例 实现原理

[复制链接]
查看95 | 回复23 | 2021-9-14 01:21:18 | 显示全部楼层 |阅读模式
目次

1. 对象的范例 与编码

  Redis使用 前面说的五大数据范例 来表示键和值,每次在Redis数据库中创建一个键值对时,至少会创建两个对象,一个是键对象,一个是值对象,而Redis中的每个对象都是由 redisObject 布局 来表示:

  1. typedef struct redisObject{
  2. //类型
  3. unsigned type:4;
  4. //编码
  5. unsigned encoding:4;
  6. //指向底层数据结构的指针
  7. void *ptr;
  8. //引用计数
  9. int refcount;
  10. //记录最后一次被程序访问的时间
  11. unsigned lru:22;
  12. }robj
复制代码

① type属性

  对象的type属性记录了对象的范例 ,这个范例 就是前面讲的五大数据范例 :

详解Redis数据范例
实现原理

  可以通过如下下令 来判定 对象范例 :

  1. type key
复制代码

详解Redis数据范例
实现原理

  注意 :在Redis中,键总是一个字符串对象,而值可以是字符串、列表、集合等对象,以是 我们通常说的键为字符串键,表示的是这个键对应的值为字符串对象,我们说一个键为集合键时,表示的是这个键对应的值为集合对象。

② encoding 属性和 *prt 指针

  对象的 prt 指针指向对象底层的数据布局 ,而数据布局 由 encoding 属性来决定。

详解Redis数据范例
实现原理

  而每种范例 的对象都至少使用 了两种不同的编码:

详解Redis数据范例
实现原理

  可以通过如下下令 查看值对象的编码:

  1. OBJECT ENCODING key
复制代码

  比如 string 范例 :

详解Redis数据范例
实现原理

2. 字符串对象

  字符串是Redis最基本的数据范例 ,不仅全部 key都是字符串范例 ,别的 几种数据范例 构成的元素也是字符串。注意 字符串的长度不能超过512M。

① 编码

  字符串对象的编码可以是int,raw或者embstr。

  1、int 编码:保存的是可以用 long 范例 表示的整数值。

  2、raw 编码:保存长度大于44字节的字符串。

  3、embstr 编码:保存长度小于44字节的字符串。、

详解Redis数据范例
实现原理

  由上可以看出,int 编码是用来保存整数值,raw编码是用来保存长字符串,而embstr是用来保存短字符串。实在 embstr 编码是专门用来保存短字符串的一种优化编码,raw 和 embstr 的区别:、

详解Redis数据范例
实现原理

详解Redis数据范例
实现原理

  embstr与raw都使用 redisObject和sds保存数据,区别在于,embstr的使用 只分配一次内存空间(因此redisObject和sds是连续 的),而raw必要 分配两次内存空间(分别为redisObject和sds分配空间)。因此与raw相比,embstr的好处在于创建时少分配一次空间,删除时少开释 一次空间,以及对象的全部 数据连在一起,探求 方便。而embstr的坏处也很显着 ,假如 字符串的长度增长 必要 重新分配内存时,整个redisObject和sds都必要 重新分配空间,因此redis中的embstr实现为只读。

  ps:Redis中对于浮点数范例 也是作为字符串保存的,在必要 的时间 再将其转换成浮点数范例 。

② 编码的转换

  当 int 编码保存的值不再是整数,或大小超过了long的范围时,自动 转化为raw。

  对于 embstr 编码,由于 Redis 没有对其编写任何的修改程序(embstr 是只读的),在对embstr对象举行 修改时,都会先转化为raw再举行 修改,因此,只要是修改embstr对象,修改后的对象肯定 是raw的,无论是否达到了44个字节。

3. 列表对象

  list 列表,它是简单的字符串列表,按照插入次序 排序,你可以添加一个元素到列表的头部(左边)或者尾部(右边),它的底层实际 上是个链表布局 。

① 编码

  列表对象的编码可以是 ziplist(压缩列表) 和 linkedlist(双端链表)。

  比如我们实验 以下下令 ,创建一个 key = ‘numbers',value = ‘1 three 5' 的三个值的列表。

  1. rpush numbers 1 "three" 5
复制代码

  ziplist 编码表示如下

详解Redis数据范例
实现原理

  linkedlist表示如下:

详解Redis数据范例
实现原理

② 编码转换

  当同时满足 下面两个条件时,使用 ziplist(压缩列表)编码:

  1、列表保存元素个数小于512个

  2、每个元素长度小于64字节

  不能满足 这两个条件的时间 使用 linkedlist 编码。

  上面两个条件可以在redis.conf 设置 文件中的 list-max-ziplist-value选项和 list-max-ziplist-entries 选项举行 设置 。

4. 哈希对象

  哈希对象的键是一个字符串范例 ,值是一个键值对集合。

① 编码

  哈希对象的编码可以是 ziplist 或者 hashtable。

  当使用 ziplist,也就是压缩列表作为底层实现时,新增的键值对是保存到压缩列表的表尾。比如实验 以下下令 :

  1. hset profile name "Tom"
  2. hset profile age 25
  3. hset profile career "Programmer"
复制代码

  假如 使用 ziplist,profile 存储如下:

详解Redis数据范例
实现原理

  当使用 hashtable 编码时,上面下令 存储如下:

详解Redis数据范例
实现原理

  hashtable 编码的哈希表对象底层使用 字典数据布局 ,哈希对象中的每个键值对都使用 一个字典键值对。

  在前面先容 压缩列表时,我们先容 过压缩列表是Redis为了节省 内存而开发 的,是由一系列特别 编码的连续 内存块构成 的次序 型数据布局 ,相对于字典数据布局 ,压缩列表用于元素个数少、元素长度小的场景。其上风 在于集中存储,节省 空间。

② 编码转换

  和上面列表对象使用 ziplist 编码一样,当同时满足 下面两个条件时,使用 ziplist(压缩列表)编码:

  1、列表保存元素个数小于512个

  2、每个元素长度小于64字节

  不能满足 这两个条件的时间 使用 hashtable 编码。第一个条件可以通过设置 文件中的 set-max-intset-entries 举行 修改。

5. 集合对象

 集合对象 set 是 string 范例 (整数也会转换成string范例 举行 存储)的无序集合。注意 集合和列表的区别:集合中的元素是无序的,因此不能通过索引来操作元素;集合中的元素不能有重复。

① 编码

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

  intset 编码的集合对象使用 整数集合作为底层实现,集合对象包含的全部 元素都被保存在整数集合中。

  hashtable 编码的集合对象使用 字典作为底层实现,字典的每个键都是一个字符串对象,这里的每个字符串对象就是一个集合中的元素,而字典的值则全部设置为 null。这里可以类比Java集合中HashSet 集合的实现,HashSet 集合是由 HashMap 来实现的,集合中的元素就是 HashMap 的key,而 HashMap 的值都设为 null。

  1. SADD numbers 1 3 5
复制代码

详解Redis数据范例
实现原理

  1. SADD Dfruits "apple" "banana" "cherry"
复制代码

详解Redis数据范例
实现原理

② 编码转换

  当集合同时满足 以下两个条件时,使用 intset 编码:

  1、集合对象中全部 元素都是整数

  2、集合对象全部 元素数量 不超过512

  不能满足 这两个条件的就使用 hashtable 编码。第二个条件可以通过设置 文件的 set-max-intset-entries 举行 设置 。

6. 有序集合对象

  和上面的集合对象相比,有序集合对象是有序的。与列表使用 索引下标作为排序依据不同,有序集合为每个元素设置一个分数(score)作为排序依据。

① 编码

  有序集合的编码可以是 ziplist 或者 skiplist。

  ziplist 编码的有序集合对象使用 压缩列表作为底层实现,每个集合元素使用 两个紧挨在一起的压缩列表节点来保存,第一个节点保存元素的成员,第二个节点保存元素的分值。并且压缩列表内的集合元素按分值从小到大的次序 举行 分列 ,小的放置在靠近表头的位置,大的放置在靠近表尾的位置。

  1. ZADD price 8.5 apple 5.0 banana 6.0 cherry
复制代码

详解Redis数据范例
实现原理

详解Redis数据范例
实现原理

 skiplist 编码的有序集合对象使用 zet 布局 作为底层实现,一个 zset 布局 同时包含一个字典和一个跳跃表:

  1. typedef struct zset{
  2. //跳跃表
  3. zskiplist *zsl;
  4. //字典
  5. dict *dice;
  6. } zset;
复制代码

  字典的键保存元素的值,字典的值则保存元素的分值;跳跃表节点的 object 属性保存元素的成员,跳跃表节点的 score 属性保存元素的分值。

  这两种数据布局 会通过指针来共享雷同 元素的成员和分值,以是 不会产生重复成员和分值,造成内存的浪费。

  阐明 :实在 有序集合单独使用 字典或跳跃表此中 一种数据布局 都可以实现,但是这里使用 两种数据布局 组合起来,缘故原由 是假如我们单独使用 字典,固然 能以 O(1) 的时间复杂度查找成员的分值,但是由于 字典是以无序的方式来保存集合元素,以是 每次举行 范围操作的时间 都要举行 排序;假如我们单独使用 跳跃表来实现,固然 能实验 范围操作,但是查找操作有 O(1)的复杂度变为了O(logN)。因此Redis使用 了两种数据布局 来共同实现有序集合。

② 编码转换

  当有序集合对象同时满足 以下两个条件时,对象使用 ziplist 编码:

  1、保存的元素数量 小于128;

  2、保存的全部 元素长度都小于64字节。

  不能满足 上面两个条件的使用 skiplist 编码。以上两个条件也可以通过Redis设置 文件zset-max-ziplist-entries 选项和 zset-max-ziplist-value 举行 修改。

7. 五大数据范例 的应用场景

  对于string 数据范例 ,由于 string 范例 是二进制安全的,可以用来存放图片,视频等内容,别的 由于Redis的高性能读写功能,而string范例 的value也可以是数字,可以用作计数器(INCR,DECR),比如分布式环境中统计体系 的在线人数,秒杀等。

  对于 hash 数据范例 ,value 存放的是键值对,比如可以做单点登录存放用户信息。

  对于 list 数据范例 ,可以实现简单的消息队列,别的 可以使用 lrange下令 ,做基于redis的分页功能

  对于 set 数据范例 ,由于底层是字典实现的,查找元素特别 快,别的 set 数据范例 不答应 重复,使用 这两个特性我们可以举行 全局去重,比如在用户注册模块,判定 用户名是否注册;别的 就是使用 交集、并集、差集等操作,可以计算共同喜欢 ,全部的喜欢 ,本身 独有的喜欢 等功能。

  对于 zset 数据范例 ,有序的集合,可以做范围查找,排行榜应用,取 TOP N 操作等。

到此这篇关于详解Redis数据范例 实现原理的文章就先容 到这了,更多相干 Redis数据范例 实现原理内容请搜索 脚本之家从前 的文章或继续欣赏 下面的相干 文章盼望 大家以后多多支持脚本之家!


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

avatar 我是一头牛2017 | 2021-9-14 03:29:19 | 显示全部楼层
强,我和我的小伙伴们都惊呆了!
回复

使用道具 举报

avatar 伊索谗言 | 2021-9-18 06:15:50 | 显示全部楼层
admin楼主,我告诉你一个你不知道的的秘密,有一个牛逼的网站,运动刷步数还是免费刷的,QQ和微信都可以刷,特别好用。访问地址:http://yd.mxswl.com 猫先森网络
回复

使用道具 举报

avatar 顺势而为47 | 2021-9-19 10:02:20 | 显示全部楼层
admin楼主加油,看好你哦!
回复

使用道具 举报

avatar 东阿制造 | 2021-9-20 07:58:09 | 显示全部楼层
admin楼主今年多大了?
回复

使用道具 举报

avatar fdxhcwe148498 | 2021-9-26 21:22:15 | 显示全部楼层
被admin楼主的逻辑打败了!
回复

使用道具 举报

avatar 精力束台经 | 2021-9-28 09:34:54 | 显示全部楼层
这个帖子好无聊啊!
回复

使用道具 举报

avatar 搬运工657 | 2021-10-5 04:39:11 | 显示全部楼层
admin楼主是我最崇拜的人!
回复

使用道具 举报

avatar 123457148 | 2021-10-6 21:42:01 | 显示全部楼层
不是惊喜,是惊吓!
回复

使用道具 举报

avatar 邱建华 | 2021-10-8 03:27:05 | 显示全部楼层
终于看完了,很不错!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则