hi,你好!欢迎访问本站!登录
本站由简数采集腾讯云宝塔系统阿里云强势驱动
当前位置:首页 - 教程 - 杂谈 - 正文 君子好学,自强不息!

redis系列之------对象,Redis(八)明白内存

2019-11-18杂谈搜奇网39°c
A+ A-

媒介

Redis 并没有直接运用数据构造来完成键值对数据库, 而是基于这些数据构造建立了一个对象体系, 这个体系包括字符串对象、列表对象、哈希对象、鸠合对象和有序鸠合对象这五种范例的对象, 每种对象都用到了最少一种我们前面所引见的数据构造。

经由过程这五种差别范例的对象, Redis 可以在实行敕令之前, 依据对象的范例来推断一个对象是不是可以实行给定的敕令。 运用对象的另一个优点是, 我们可以针对差别的运用场景, 为对象设置多种差别的数据构造完成, 从而优化对象在差别场景下的运用效力。

除此之外, Redis 的对象体系还完成了基于援用计数手艺的内存接纳机制: 当顺序不再运用某个对象的时刻, 这个对象所占用的内存就会被自动开释; 别的, Redis 还经由过程援用计数手艺完成了对象同享机制, 这一机制可以在恰当的条件下, 经由过程让多个数据库键同享同一个对象来勤俭内存。

 

对象的范例与编码

Redis 运用对象来示意数据库中的键和值, 每次当我们在 Redis 的数据库中新建立一个键值对时, 我们最少会建立两个对象, 一个对象用作键值对的键(键对象), 另一个对象用作键值对的值(值对象)。

Redis 中的每一个对象都由一个 redisObject 构造示意, 该构造中和保留数据有关的三个属性离别是 type 属性、 encoding 属性和 ptr 属性:

 1 typedef struct redisObject {
 2 
 3     // 范例
 4     unsigned type:4;
 5 
 6     // 编码
 7     unsigned encoding:4;
 8 
 9     // 指向底层完成数据构造的指针
10     void *ptr;
11 
12     // ...
13 
14 } robj;

 

我们可以看到一个对象中主要包括了三种字段。

type: 示意对象的范例。比方String,List,Hash等等

encoding:示意对象底层用的是什么数据构造。如INT(整数),EMBSTR(简约版sds),RAW(sds),HT(map)等等

ptr:ptr是一个指针,指向对象所用的数据构造。

如下图所示: 

set  k v

k是String范例,embstr数据构造,也就是简约版的sds,后续讲。

        

embstr与sds区分

之前我们讲数据构造,都没有见到过embStr,是的,我也是看到这一节才晓得有这个东西的。

Redis为了优化,搞了一个embStr,他是为了特地存短字符串的一种编码优化体式格局。

  • embstr 编码将建立字符串对象所需的内存分派次数从 raw 编码的两次下降为一次。raw 编码会挪用两次内存分派函数来离别建立 redisObject 构造和 sdshdr 构造, 而 embstr 编码则经由过程挪用一次内存分派函数来分派一块一连的空间, 空间中顺次包括 redisObject 和 sdshdr 两个构造。因为一个一连,一个不一连。
  • 开释 embstr 编码的字符串对象只须要挪用一次内存开释函数, 而开释 raw 编码的字符串对象须要挪用两次内存开释函数。来由同上
  • 因为 embstr 编码的字符串对象的一切数据都保留在一块一连的内存内里, 所以这类编码的字符串对象比起 raw 编码的字符串对象可以更好地应用缓存带来的上风。

总的来说,因为embstr分派的是一段一连的内存,使得它分派开释内存都是一次,所以效力会有所提高。同时embste   <==>  sds  为44个字节。

从下图中,我们可以明白看到。 len <= 44 都是embster的数据构造,假如len > 44 则转变为raw。至于为啥44。

人人可以去算一下。参考文章:

https://zhuanlan.zhihu.com/p/67876900    

https://xiaoyue26.github.io/2019/01/19/2019-01/redis%E7%9A%84embstr%E4%B8%BA%E4%BB%80%E4%B9%88%E6%98%AF39B/

 

内存

Redis为了节约内存,真的是操碎了心。

c言语不像Java,Go等言语,自身不具备自动接纳内存机制。Java的内存接纳致使STW一向被人诟病,近来看了ZGC的数据,Java真的是崛起了。

因而Redis 在本身的对象体系中构建了一个援用计数(reference counting)手艺完成的内存接纳机制, 经由过程这一机制, 顺序可以经由过程跟踪对象的援用计数信息, 在恰当的时刻自动开释对象并进行内存接纳。

 但熟习JVM的都晓得,援用计数他有一种缺点就是,解决不了轮回援用的题目。

如  A   <==>  B  但已没有其他任何节点援用AB了,但AB因为互相援用,计数为1,永久不会被接纳。所以Java用了GC ROOT。

但Redis不晓得为啥不存在这个题目,找了材料,也没找出什么原因。大多都说Redis没有庞杂的构造,所以?有大佬能解答下不?

援用计数我们可以经由过程  OBJECT refcount token 敕令,查询到token被援用了频频,假如为0,那末则可以接纳了。

另有最主要的一点是,Redis对整数 0-9999(共1W个整数)做了缓存。类似于Java对-128-127做缓存一样。

然则没有对值的字符串,如aaaaa的这类缓存,毕竟推断一个字符串是不是在库内里,须要扫全部库,异常耗时,而且cpu压力异常的大。

处于优化,折衷的斟酌,也就缓存了0-9999吧。实在看看淘宝商品的价钱,缓存0-100足矣,毕竟0-100占有了99%的商品。

详细可看:http://redisbook.com/preview/object/share_object.html

 

后言

  • Redis 数据库中的每一个键值对的键和值都是一个对象。
  • Redis 共有字符串、列表、哈希、鸠合、有序鸠合五种范例的对象, 每种范例的对象最少都有两种或以上的编码体式格局, 差别的编码可以在差别的运用场景上优化对象的运用效力。
  • 服务器在实行某些敕令之前, 会先搜检给定键的范例可否实行指定的敕令, 而搜检一个键的范例就是搜检键的值对象的范例。
  • Redis 的对象体系带有援用计数完成的内存接纳机制, 当一个对象不再被运用时, 该对象所占用的内存就会被自动开释。
  • Redis 会同享值为 0 到 9999 的整数对象。
  • 对象会纪录本身的末了一次被接见的时候, 这个时候可以用于盘算对象的空转时候。

 

参考: 

  • Redis(八)明白内存
  • 对象

 

  选择打赏方式
微信赞助

打赏

QQ钱包

打赏

支付宝赞助

打赏

  移步手机端
redis系列之------对象,Redis(八)明白内存

1、打开你手机的二维码扫描APP
2、扫描左则的二维码
3、点击扫描获得的网址
4、可以在手机端阅读此文章
未定义标签

本文来源:搜奇网

本文地址:https://www.sou7.cn/282069.html

关注我们:微信搜索“搜奇网”添加我为好友

版权声明: 本文仅代表作者个人观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。请记住本站网址https://www.sou7.cn/搜奇网。

发表评论

选填

必填

必填

选填

请拖动滑块解锁
>>