您当前的位置:首页 > 电脑百科 > 数据库 > Redis

Redis底层字符串编码设计思想简介

时间:2022-05-09 10:31:22  来源:  作者:平凡人笔记

承接上文深入redis源码,了解数据结构设计思想

本地调试redis源码

启动redis源码

mac下载C语言编译器CLion,拉取redis源码并导入CLion

Redis底层字符串编码设计思想简介

 

编译redis源码并启动

Redis底层字符串编码设计思想简介

 

编译成功之后,在src目录中就会出现可执行文件

Redis底层字符串编码设计思想简介

 

启动redis-server

Redis底层字符串编码设计思想简介

 

启动成功

Redis底层字符串编码设计思想简介

 

在set方法中打个断点

redis的所有命令都在redisCommand里面定义,找到set命令,并找到对应的触点函数setCommand

Redis底层字符串编码设计思想简介

 

在setCommand函数中打个端点

Redis底层字符串编码设计思想简介

 

通过redis-cli执行set命令,就可以断点跟踪了

Redis底层字符串编码设计思想简介

 

看下编码的过程

Redis底层字符串编码设计思想简介

 

tryObjectEncoding

Redis底层字符串编码设计思想简介

 

len是value的长度,长度小于等于20的话,才可以被转换成整数。

为什么整数范围最大是十进制数20?

在64位系统下C语言中的int还是占4字节,32位,与32位系统中没有区别!

64位操作系统下,采用64位编译器进行编译处理时,发生变化的变量类型是long。

32位系统下,long占4字节,32位,与int相同。

64位系统下,long占8字节,64位,有符号数取值范围是-9223372036854775808至9223372036854775807。

JAVA的long型整数最大值:9223372036854775807,即19位十进制数,64位二进制数,16位16进制数。

long占8个字节,64位二进制数,19位十进制数,算上符号的话就是20位十进制数。

Redis底层字符串编码设计思想简介

 

如果value string可以转换成long,然后将value值赋值给redisObject的ptr指针,强制把整型值转换成指针类型,而不让ptr存内存地址,这样即节省了内存,还减少了一次内存io。

字符串编码

短字符串编码

Redis底层字符串编码设计思想简介

 

短字符串(长度小于等于44)编码是embstr

Redis底层字符串编码设计思想简介

 

长字符串(长度大于44)编码是raw

为什么是44?

要充分理解这个问题,需要先科普下cpu、地址总线、内存之间的关系:

  • • 64位处理器比32位处理器速度更快

32位处理器一次性只能处理32位,也就是4个字节的数据,而64位处理器一次性能处理64位即8个字节的数据,64位处理器的处理速度比32位更快。

  • • 64位处理器比32位能处理的地址范围更大

除了运算能力之外,与32位处理器相比,64位处理器的优势还体现在系统对内存的控制上。由于地址使用的是特殊的整数,而64位处理器的一个ALU(算术逻辑运行器)和寄存器可以处理更大的整数,也就是更大的地址。传统的32位处理器的寻址空间最大为4GB,而64位处理器在理论上则可以达到1800万个TB。

  • • 地址总线

要存取数据或指令就要知道数据或指令存放的位置,地址寄存器存储的就是cpu当前要存取的数据或指令的地址,该地址是由地址总线传输到地址寄存器上的

假设地址总线有n位,即共有n位二进制位来表示地址,那么最多可以表示2^n个地址,另外计算机以一个字节为寻址单位,所以cpu的寻址能力或者最大的寻址范围是2^n个字节。综上,地址总线的位数决定了cpu的寻址能力。

  • • 数据总线的宽度与字长及cpu位数

字长指cpu同一时间内可以处理的二进制数的位数,数据总线传输的数据或指令的位数要与字长一致。否则,如果数据总线长度大于字长则一条数据或指令要分多次传输,则分开传输几组数据也就没有意义;如果数据总线宽度小于字长,则cpu的利用率降低,对资源是种浪费。另外如果字长是n位,一般称cpu是n位的,所以说数据总线的宽度和字长及cpu的位数是一致的。

结合上面的问题,继续分析:

64位系统缓存行(字长)大小是64字节即64位处理器一次性读取64字节的缓存数据。基于缓存局部性原理,一次性要读取的数据不足64字节,也会顺便获取相邻的其他数据共64字节。

从内存中获取到redisObject对象之后,根据ptr指向的内存空间获取数据。

Redis底层字符串编码设计思想简介

 

分析下这个redisObject对象占多少个字节:

type 4bit,encoding4bit,LRU_BITS占24bit即3字节,int类型的refcount占4字节,ptr指针类型占8字节,共16个字节,那么64字节的缓存行还剩48个字节的剩余空间,那么这48字节的缓存行空间存放什么呢?

存放redisObject ptr指针指向的内存空间的数据,即cpu一次性读取的64字节的缓存行中包含redisObject对象以及该对象ptr指针所指向的内存空间的数据,以免再根据redisObject的ptr指针再去内存中获取对应的数据,减少了一次内存io。

那48字节在哪个字符串类型的范围内呢?

Redis底层字符串编码设计思想简介

 

sdshdr8 对应的字符串范围是32-64字节

Redis底层字符串编码设计思想简介

 

c语言中的char类型占1个字节,java中的char类型占2个字节。

redis字符串为了兼容c语言函数库在末尾加上的字符占1个字节。

uint8_t len 占一个字节,uint8_t alloc占一个字节,char flags占一个字节,占一个字节

所以sdshdr8数据结构需要4个字节的元数据

除去这4个字节,缓存行还有48-4=44个字节的剩余空间,如果字符串数据范围小于等于44,把redisObject对象ptr指针所指向内存中的这个数据和redisObject对象放在一起即嵌入式字符串,在内存空间分配的时候,这两部分数据是分配在一起的,这样就可以直接适应缓存行的大小,这样就减少了一次内存io。

List数据类型

  • • LPUSH
Redis底层字符串编码设计思想简介

 

从左边开始往alist中放入元素

Redis底层字符串编码设计思想简介

 

  • • LPOP

从左边获取元素

Redis底层字符串编码设计思想简介

 

依次是c、b、a

Redis底层字符串编码设计思想简介

 

list如果没有元素的话,对应的key也会被清除

  • • RPUSH
Redis底层字符串编码设计思想简介

 

从右边放入元素

Redis底层字符串编码设计思想简介

 

从左边放入元素,从左边拿出元素,则是栈的数据结构即a,b,c的数据放入,c、b、a顺序的拿出,a最开始进,最后出,先进后出,

Redis底层字符串编码设计思想简介

 

同一端,从这边进,也从这边出,这就是栈的数据结构。

一边进,另外一边出,是队列的数据结构即右边放a,b,c,左边拿a,b,c,这是队列的数据结构。

阻塞api

如果没有元素就一直等待,直到有元素或者设置超时时间

Redis底层字符串编码设计思想简介

 

LPOP从list中弹出元素之后就会从list中删除,如果应用程序没有正确处理的话,就会造成元素丢失的情况,BRPOPLPUSH就是为了应对这场场景,弹出元素之后,push到另外一个list中,做一个数据备份,防止数据丢失。

List数据类型底层设计

List是一个有序(按加入的时序排序)的数据结构,Redis采用quicklist(双端链表)和ziplist作为List的底层实现。

可以通过设置每个ziplist的最大容量,quicklist的数据压缩范围,提升数据存取效率。

  • • list-max-ziplist-size -2

单个ziplist节点最大能存储8kb,超过则进行分裂,将数据存储在新的ziplist节点中

  • • list-compress-depth 1

0代表所有节点,都不进行压缩,1代表从头节点往后走一个,尾节点往前走一个不用压缩,其他的全部压缩,2,3,4...依次类推

Redis底层字符串编码设计思想简介

 

双端链表需要两个指针:pre,next,而指针占8个字节的内存空间,所以存储一个元素就至少占16个字节,如果元素比较多的情况下,内存开销就会非常大,所以redis并没有用quicklist 双端链表,而是用更加紧凑的ziplist。



Tags:Redis   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
兄弟,王者荣耀的段位排行榜是通过Redis实现的?
在王者荣耀中,我们会打排位赛,而且大家最关注的往往都是你的段位,还有在好友中的排名。作为程序员的你,是否思考过这个段位排行榜是怎么实现的?了解它的实现原理,会不会对上分有所...【详细内容】
2024-04-15  Search: Redis  点击:(3)  评论:(0)  加入收藏
16个Redis常见使用场景总结
来源:blog.csdn.net/qq_39938758/article/details/105577370目录 缓存 数据共享分布式 分布式锁 全局ID 计数器 限流 位统计 购物车 用户消息时间线timeline 消息...【详细内容】
2024-04-11  Search: Redis  点击:(8)  评论:(0)  加入收藏
Linux获取Redis 性能指标方法
一、监控指标Ø 性能指标:PerformanceØ 内存指标: MemoryØ 基本活动指标:Basic activityØ 持久性指标: PersistenceØ 错误指标:Error二、监...【详细内容】
2024-04-11  Search: Redis  点击:(10)  评论:(0)  加入收藏
Redis与缓存一致性问题
缓存一致性问题是在使用缓存系统,如Redis时经常遇到的问题。当数据在原始数据源(如数据库)中发生变化时,如何确保缓存中的数据与数据源保持一致,是开发者需要关注的关键问题。一...【详细内容】
2024-04-11  Search: Redis  点击:(8)  评论:(0)  加入收藏
Redis 不再 “开源”,未来采用 SSPLv1 和 RSALv2 许可证
Redis 官方于21日宣布修改开源协议 —— 未来所有版本都将使用 “源代码可用” 的许可证 (source-available licenses)。具体来说,Redis 将不再遵循 BSD 3-Clause...【详细内容】
2024-03-27  Search: Redis  点击:(24)  评论:(0)  加入收藏
Redis“叛逃”开源,得罪了几乎所有人
内存数据库供应商Redis近日在开源界砸下了一块“巨石”。Redis即将转向双许可模式,并实施更为严格的许可条款。官方对此次变更的公告直截了当:从Redis 7.4版本开始,Redis将在Re...【详细内容】
2024-03-25  Search: Redis  点击:(13)  评论:(0)  加入收藏
如何使用 Redis 实现消息队列
Redis不仅是一个强大的内存数据存储系统,它还可以用作一个高效的消息队列。消息队列是应用程序间或应用程序内部进行异步通信的一种方式,它允许数据生产者将消息放入队列中,然...【详细内容】
2024-03-22  Search: Redis  点击:(22)  评论:(0)  加入收藏
Redis不再 “开源”
Redis 官方今日宣布修改开源协议 —— 未来所有版本都将使用 “源代码可用” 的许可证 (source-available licenses)。具体来说,Redis 将不再遵循 BSD 3-Clause 开...【详细内容】
2024-03-21  Search: Redis  点击:(15)  评论:(0)  加入收藏
在Redis中如何实现分布式锁的防死锁机制?
在Redis中实现分布式锁是一个常见的需求,可以通过使用Redlock算法来防止死锁。Redlock算法是一种基于多个独立Redis实例的分布式锁实现方案,它通过协调多个Redis实例之间的锁...【详细内容】
2024-02-20  Search: Redis  点击:(50)  评论:(0)  加入收藏
手动撸一个 Redis 分布式锁
大家好呀,我是楼仔。今天第一天开工,收拾心情,又要开始好好学习,好好工作了。对于使用 Java 的小伙伴,其实我们完全不用手动撸一个分布式锁,直接使用 Redisson 就行。但是因为这些...【详细内容】
2024-02-19  Search: Redis  点击:(47)  评论:(0)  加入收藏
▌简易百科推荐
兄弟,王者荣耀的段位排行榜是通过Redis实现的?
在王者荣耀中,我们会打排位赛,而且大家最关注的往往都是你的段位,还有在好友中的排名。作为程序员的你,是否思考过这个段位排行榜是怎么实现的?了解它的实现原理,会不会对上分有所...【详细内容】
2024-04-15    dbaplus社群  Tags:Redis   点击:(3)  评论:(0)  加入收藏
16个Redis常见使用场景总结
来源:blog.csdn.net/qq_39938758/article/details/105577370目录 缓存 数据共享分布式 分布式锁 全局ID 计数器 限流 位统计 购物车 用户消息时间线timeline 消息...【详细内容】
2024-04-11    书圈  Tags:Redis   点击:(8)  评论:(0)  加入收藏
Linux获取Redis 性能指标方法
一、监控指标Ø 性能指标:PerformanceØ 内存指标: MemoryØ 基本活动指标:Basic activityØ 持久性指标: PersistenceØ 错误指标:Error二、监...【详细内容】
2024-04-11  上海天正信息科技有限    Tags:Redis   点击:(10)  评论:(0)  加入收藏
Redis与缓存一致性问题
缓存一致性问题是在使用缓存系统,如Redis时经常遇到的问题。当数据在原始数据源(如数据库)中发生变化时,如何确保缓存中的数据与数据源保持一致,是开发者需要关注的关键问题。一...【详细内容】
2024-04-11  后端Q    Tags:Redis   点击:(8)  评论:(0)  加入收藏
Redis 不再 “开源”,未来采用 SSPLv1 和 RSALv2 许可证
Redis 官方于21日宣布修改开源协议 —— 未来所有版本都将使用 “源代码可用” 的许可证 (source-available licenses)。具体来说,Redis 将不再遵循 BSD 3-Clause...【详细内容】
2024-03-27  dbaplus社群    Tags:Redis   点击:(24)  评论:(0)  加入收藏
Redis“叛逃”开源,得罪了几乎所有人
内存数据库供应商Redis近日在开源界砸下了一块“巨石”。Redis即将转向双许可模式,并实施更为严格的许可条款。官方对此次变更的公告直截了当:从Redis 7.4版本开始,Redis将在Re...【详细内容】
2024-03-25    51CTO  Tags:Redis   点击:(13)  评论:(0)  加入收藏
如何使用 Redis 实现消息队列
Redis不仅是一个强大的内存数据存储系统,它还可以用作一个高效的消息队列。消息队列是应用程序间或应用程序内部进行异步通信的一种方式,它允许数据生产者将消息放入队列中,然...【详细内容】
2024-03-22  后端Q  微信公众号  Tags:Redis   点击:(22)  评论:(0)  加入收藏
Redis不再 “开源”
Redis 官方今日宣布修改开源协议 —— 未来所有版本都将使用 “源代码可用” 的许可证 (source-available licenses)。具体来说,Redis 将不再遵循 BSD 3-Clause 开...【详细内容】
2024-03-21  OSC开源社区    Tags:Redis   点击:(15)  评论:(0)  加入收藏
在Redis中如何实现分布式锁的防死锁机制?
在Redis中实现分布式锁是一个常见的需求,可以通过使用Redlock算法来防止死锁。Redlock算法是一种基于多个独立Redis实例的分布式锁实现方案,它通过协调多个Redis实例之间的锁...【详细内容】
2024-02-20  编程技术汇    Tags:Redis   点击:(50)  评论:(0)  加入收藏
手动撸一个 Redis 分布式锁
大家好呀,我是楼仔。今天第一天开工,收拾心情,又要开始好好学习,好好工作了。对于使用 Java 的小伙伴,其实我们完全不用手动撸一个分布式锁,直接使用 Redisson 就行。但是因为这些...【详细内容】
2024-02-19  楼仔  微信公众号  Tags:Redis   点击:(47)  评论:(0)  加入收藏
站内最新
站内热门
站内头条