redis设计与实现读书笔记

这篇具有很好参考价值的文章主要介绍了redis设计与实现读书笔记。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

这里主要记录一下在阅读redis设计与实现中碰到的一些没有记录过的知识。

引用计数技术

Redis的对象系统实现了基于引用计数技术的内存回收机制,当程序不再使用某个对象的时候,这个对象所占用的内存就会被自动释放;另外,Redis还通过引用计数技术实现了对象共享机制,这一机制可以在适当的条件下,通过让多个数据库键共享同一个对象来节约内存。

关于引用计数技术:当一个程序开始使用这个对象时,它会将这个对象的引用计数加1;而当一个程序抛弃该对象时,它会将这个对象的引用计数减1。当某个对象的引用计数降至0时,Redis会自动回收该对象占用的内存空间。

关于redis的实现:每个redisObject对象在创建时都会初始化一个refcount属性,用来记录该对象被引用的次数。

关于redis通过引用计数技术实现了对象共享机制和垃圾回收机制

Redis通过引用计数技术和对象共享机制来节约内存空间。当多个Redis客户端使用相同的字符串值时,Redis会将它们的redisObject对象合并成一个,并且他们引用计数属性会自增以记录所有这些客户端都在使用这个对象。

具体地说,Redis的共享机制是通过字典结构实现的,Redis内部维护了一个字符串对象池(stringpool),里面保存着所有已经创建的字符串对象。当一个新的字符串被创建时,Redis首先检查stringpool中是否已经存在该字符串,如果存在,那么就直接返回这个对象的引用,并且将它的引用计数加1;如果不存在,则创建一个新的redisObject对象,并将该对象加入到stringpool中,同时返回该对象的引用。

对象共享机制的优点

这种实现方式能够显著减少Redis的内存占用,因为许多大量出现的字符串只需要被存储一次,并且可以被多个客户端共享使用。同时,由于引用计数技术的存在,只有当所有的客户端都不再使用某个共享对象时,Redis才会自动回收该对象所占用的内存空间。

redis对象系统介绍

对象的类型与编码

Redis 中的每个对象都由一个redis0bject结构表示,该结构中和保存数据有关的三个属性分别是type属性、encoding属性和ptr属性:

type属性:记录了对象的类型。

为下图中类型的一个

redis设计与实现读书笔记

对于Redis数据库保存的键值对来说,键总是一个字符串对象,而值则可以是字符串对象、列表对象、哈希对象、集合对象或者有序集合对象的其中一种。

对象的ptr指针指向对象的底层实现数据结构,而这些数据结构由对象的encoding属性决定。 

encoding属性:记录了对象所使用的编码,也就是说这个对象使用了什么数据结构作为对象的底层实现。

encording属性的作用

通过encoding属性来设定对象所使用的编码,而不是为特定类型的对象关联一种固定的编码,极大地提升了Redis 的灵活性和效率,因为Redis可以根据不同的使用场景来为一个对象设置不同的编码,从而优化对象在某一场景下的效率。

redis设计与实现读书笔记

 这就是encording属性的作用,可以方便的更改对象的底层数据结构。

字符串对象

首先,字符串对象可以使用的编码有三种int、 raw或者embstro。

int:如果一个字符串对象保存的是整数值,并且这个整数值可以用long类型来表示,就会使用int编码也就是以整数类型存储。

raw:如果字符串对象保存的是一个字符串值,并且这个字符串值的长度大于32字节,那么字符串对象将使用一个简单动态字符串(SDS)来保存这个字符串值。

embsto:如果字符串对象保存的是一个字符串值,并且这个字符串值的长度小于等于32字节,那么字符串对象将使用embstr编码的方式来保存这个字符串值。

embsto与raw的区别

 embstr编码是专门用于保存短字符串的一种优化编码方式,其与raw一样也是一个redisObject和sdshdr结构来表示字符串对象,区别在于,raw编码会调用两次内存分配函数来创建redisObject和sdshdr,而embstr通过一次内存分配函数来分配一块连续的空间依次包含redisObject和sdshdr。

对于是embstr编码还是raw编码的字符串对象来说,执行命令时产生的效果是相同的,但使用embstr编码字符串对象来保存短字符串值有以下好处:

redis设计与实现读书笔记

 但是在长字符串的情况下,这种连续的内存结构,就会因为要为每个字符串值单独分配一块内存,这种情况导致内存浪费,所以在长字符串的情况下就会使用raw编码。 

对于redis来说,浮点数的保存也是以字符串来进行保存的。

编码转换

int编码的字符串对象和embstr编码的字符串对象在条件满足的情况下,会被转换为raw编码的字符串对象。

int变为字符串

对于这个对象保存的值进行修改让这个对象保存的值不再是整数,就会让int变成字符串。

embstr变成raw

这个主要是在修改embstr的时候会发生这种情况,因为在embstr编码的字符串对象实际上是只读的,也就是说对于embstr编码的对象来说,它没有修改程序,所以在对embstr编码的对象进行数据修改的时候一般来说是先进行转换出raw之后,才会进行修改。

列表对象

编码类型,ziplist或者linkedlist

ziplist底层是用压缩链表,linkedlist底层是双向链表。

redis设计与实现读书笔记

不在这两个条件的情况下会变成linkedlist编码。

哈希对象

编码类型:ziplist或者hashtable。

ziplist底层是压缩链表,hashtable底层是dict

redis设计与实现读书笔记

 不在这两个条件的情况下会变成hashtable编码。

集合对象

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

intset的底层是整数集合,集合对象的所有元素,都被包含在整数集合里面,hashtable的底层是dict,每一个键都是一个字符串对象,对象里包含了一个集合元素。值全部设置为null.

redis设计与实现读书笔记

有序集合对象

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

ziplist底层是压缩链表,skiplist是跳表加字典

这里具体介绍一下skiplist为什么要现在跳表加字典来作为底层,

在理论上,有序集合可以单独使用字典或者跳跃表的其中一种数据结构来实现,但无论单独使用字典还是跳跃表,在性能上对比起同时使用字典和跳跃表都会有所降低。举个例子,如果我们只使用字典来实现有序集合,那么虽然以O(1)复杂度查找成员的分值这一特性会被保留,但是,因为字典以无序的方式来保存集合元素,所以每次在执行范围型操作―—比如 ZRANK、ZRANGE等命令时,程序都需要对字典保存的所有元素进行排序,完成这种排序需要至少o(NlogN)时间复杂度,以及额外的o(N)内存空间(因为要创建一个数组来保存排序后的元素)。

 另一方面,如果我们只使用跳跃表来实现有序集合,那么跳跃表执行范围型操作的所有优点都会被保留,但因为没有了字典,所以根据成员查找分值这一操作的复杂度将从0(1)上升为o(logN)。因为以上原因,为了让有序集合的查找和范围型操作都尽可能快地执行,Redis 选择了同时使用字典和跳跃表两种数据结构来实现有序集合。

所以redis使用了跳表加字典来作为底层,在需要执行那个数据结构更擅长的方面时,使用那个数据结构的api.

然后,因为这两种数据结构都会通过指针来共享相同元素的成员和分值,所以不会有同一个数据被存储两次这种事情,也就不会用内存浪费。

类型检查机制

这个机制相当于redis在用户输入针对键的命令后,由服务器检查输入数据库键的值对象是否为执行命令需要的类型,如果是就会执行。然后这样又有一个问题,那就是对于很多对象都要两种编码类型,我们不会一直清楚这个对象现在是什么编码类型,所以这里就有了redis的命令多态。

多态命令

Redis除了会根据值对象的类型来判断键是否能够执行指定命令之外,还会根据值对象的编码方式,选择正确的命令实现代码来执行命令。

这两种机制的实现图如下

redis设计与实现读书笔记

 对象的空转时长

redis0bject结构包含的最后一个属性为1ru属性,该属性记录了对象最后一次被命令程序访问的时间,当服务器占用内存数超过maxmemory选项所设置的上限值,空转时长长的会优先被回收。

关于共享对象那个事情,有一个问题就是Redis不共享包含宇符串的对象

因为当服务器考虑将一个共享对象设置为键的值对象时,程序需要先检查给定的共享对象和键想创建的目标对象是否完全相同,只有在共享对象和目标对象完全相同的情况下,程序才会将共享对象用作键的值对象,而一个共享对象保存的值越复杂,验证共享对象和目标对象是否相同所需的复杂度就会越高,消耗的CPU时间也会越多:

如果共享对象是保存整数值的字符串对象,那么验证操作的复杂度为O(1);如果共享对象是保存字符串值的字符串对象,那么验证操作的复杂度为O(N);如果共享对象是包含了多个值(或者对象的)对象,比如列表对象或者哈希对象,那么验证操作的复杂度将会是O(N)。

因此,尽管共享更复杂的对象可以节约更多的内存,但受到CPU时间的限制,Redis只对包含整数值的字符串对象进行共享。文章来源地址https://www.toymoban.com/news/detail-427246.html

到了这里,关于redis设计与实现读书笔记的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 《Effective C++ 改善程序与设计的55个具体做法》读书笔记

    条款01 视C++为一个语言联邦 C Object-Oriented C++ Template C++ STL C++ 高效编程守则视情况而变化,取决于你使用 C++ 的哪一部分。 条款02 尽量与const,enum,inline替换#define 对于单纯常量,最好以 const 对象或 enums 替换 #defines 。 对于形似函数的宏( macros ),最好改用 inline 函数替换

    2024年02月12日
    浏览(26)
  • 《深入理解Java虚拟机》读书笔记:HotSpot的算法实现

    HotSpot的算法实现概要 由于目前的主流Java虚拟机使用的都是准确式GC(这个概念在第1章介绍Exact VM对Classic VM的改进时讲过),所以当执行系统停顿下来后,并不需要一个不漏地检查完所有执行上下文和全局的引用位置,虚拟机应当是有办法直接得知哪些地方存放着对象引用。

    2024年02月13日
    浏览(52)
  • MCU+DSP,当下主流的架构设计,来到21569这里,应该如何去实现?

    作者的话 当下的音频DSP设计中,我们习惯于MCU+DSP的架构。DSP做音效,MCU做上位机,做控制,这种搭配的组合是非常成熟的,那么他的底层逻辑是什么?怎么才能实现? 实现逻辑 我们以ADI的SHARC系列DSP来讲的话,21569在之前的调音台、车载DSP的应用中,已经展现的淋漓尽致。

    2024年01月19日
    浏览(25)
  • 微信小程序毕业设计作品成品(21)微信小程序在线有声读书阅读系统设计与实现

    博主介绍: 《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程,免费 项目配有对应开发文档、开题报告、任务书、PPT、论文模版

    2024年02月08日
    浏览(36)
  • 6月份读书学习好文记录

    https://blog.csdn.net/csdnnews/article/details/130878125?spm=1000.2115.3001.5927 这是属于 AI 开发者的好时代,有什么理由不多去做一些尝试呢。 https://blog.csdn.net/csdnnews/article/details/130838259?spm=1000.2115.3001.5927 去年 11 月底 ChatGPT 横空出世时,可能谁也没想到,一场规模庞大的变革将由此开启。

    2024年02月16日
    浏览(13)
  • 4月份读书学习好文记录

    找到自己感兴趣的方向,而不是人云亦云,知道自己想要的是什么,而不是一直得过且过! 差距是怎么出现的,四年来的点点滴滴!!! https://blog.csdn.net/jdcdev_/article/details/130052555?spm=1000.2115.3001.5927 2b74dd1aab6f0e641c3d1c2.png#pic_center) https://csdnnews.blog.csdn.net/article/details/130023310?s

    2024年02月01日
    浏览(26)
  • Linux部署Redis哨兵集群 一主两从三哨兵(这里使用Redis6,其它版本类似)

          Redis-Sentinel是redis官方推荐的高可用性解决方案,sentinel哨兵是特殊的redis服务,不提供读写服务,主要用来监控redis实例节点,当用redis作master-slave的高可用时,如果master本身宕机,redis本身或者客户端都没有实现主从切换的功能,而redis-sentinel就是一个独立运行的进程

    2024年02月04日
    浏览(39)
  • 读书笔记怎么写?沟通圣经《非暴力沟通》读书笔记

    沟通看似简单,在沟通的过程中,你是否传达错信息,引起别人的不快,甚至爆发重大冲突。 《非暴力沟通》由马歇尔·B·卢森堡博士所著,因童年经历,马歇尔博士提出了非暴力沟通。本书主要介绍什么是非暴力沟通,以及非暴力沟通在不同情境下的运用技巧,是非常有用

    2024年02月16日
    浏览(27)
  • 项目记录:利用Redis实现缓存以提升查询效率

    当我们查询所有数据时,如果缓存中没有,则去数据库查询,如果有,直接查缓存的数据就行。注意定期更新缓存数据。 BoundHashOperations是绑定键值的方法,意味着之后的操作都是对此键进行操作。 ObjectMapper类提供了一系列json序列化和反序列化的操作。 缓存更新操作是通过

    2024年02月03日
    浏览(37)
  • 【Redis】Redis是什么、能干什么、主要功能和工作原理的详细讲解

    🚀欢迎来到本文🚀 🍉个人简介:陈童学哦,目前学习C/C++、算法、Python、Java等方向,一个正在慢慢前行的普通人。 🏀系列专栏:陈童学的日记 💡其他专栏:C++STL,感兴趣的小伙伴可以看看。 🎁希望各位→点赞👍 + 收藏⭐️ + 留言📝 ​ ⛱️万物从心起,心动则万物动🏄

    2024年02月11日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包