百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

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

mhr18 2024-11-26 12:14 18 浏览 0 评论

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

本地调试redis源码

启动redis源码

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

编译redis源码并启动

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

启动redis-server

启动成功

在set方法中打个断点

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

在setCommand函数中打个端点

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

看下编码的过程

tryObjectEncoding

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位十进制数。

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

字符串编码

短字符串编码

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

长字符串(长度大于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指向的内存空间获取数据。

分析下这个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字节在哪个字符串类型的范围内呢?

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

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

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

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

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

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

List数据类型

  • ? LPUSH

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

  • ? LPOP

从左边获取元素

依次是c、b、a

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

  • ? RPUSH

从右边放入元素

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

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

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

阻塞api

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

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...依次类推

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

相关推荐

【推荐】一个开源免费、AI 驱动的智能数据管理系统,支持多数据库

如果您对源码&技术感兴趣,请点赞+收藏+转发+关注,大家的支持是我分享最大的动力!!!.前言在当今数据驱动的时代,高效、智能地管理数据已成为企业和个人不可或缺的能力。为了满足这一需求,我们推出了这款开...

Pure Storage推出统一数据管理云平台及新闪存阵列

PureStorage公司今日推出企业数据云(EnterpriseDataCloud),称其为组织在混合环境中存储、管理和使用数据方式的全面架构升级。该公司表示,EDC使组织能够在本地、云端和混...

对Java学习的10条建议(对java课程的建议)

不少Java的初学者一开始都是信心满满准备迎接挑战,但是经过一段时间的学习之后,多少都会碰到各种挫败,以下北风网就总结一些对于初学者非常有用的建议,希望能够给他们解决现实中的问题。Java编程的准备:...

SQLShift 重大更新:Oracle→PostgreSQL 存储过程转换功能上线!

官网:https://sqlshift.cn/6月,SQLShift迎来重大版本更新!作为国内首个支持Oracle->OceanBase存储过程智能转换的工具,SQLShift在过去一...

JDK21有没有什么稳定、简单又强势的特性?

佳未阿里云开发者2025年03月05日08:30浙江阿里妹导读这篇文章主要介绍了Java虚拟线程的发展及其在AJDK中的实现和优化。阅前声明:本文介绍的内容基于AJDK21.0.5[1]以及以上...

「松勤软件测试」网站总出现404 bug?总结8个原因,不信解决不了

在进行网站测试的时候,有没有碰到过网站崩溃,打不开,出现404错误等各种现象,如果你碰到了,那么恭喜你,你的网站出问题了,是什么原因导致网站出问题呢,根据松勤软件测试的总结如下:01数据库中的表空间不...

Java面试题及答案最全总结(2025版)

大家好,我是Java面试陪考员最近很多小伙伴在忙着找工作,给大家整理了一份非常全面的Java面试题及答案。涉及的内容非常全面,包含:Spring、MySQL、JVM、Redis、Linux、Sprin...

数据库日常运维工作内容(数据库日常运维 工作内容)

#数据库日常运维工作包括哪些内容?#数据库日常运维工作是一个涵盖多个层面的综合性任务,以下是详细的分类和内容说明:一、数据库运维核心工作监控与告警性能监控:实时监控CPU、内存、I/O、连接数、锁等待...

分布式之系统底层原理(上)(底层分布式技术)

作者:allanpan,腾讯IEG高级后台工程师导言分布式事务是分布式系统必不可少的组成部分,基本上只要实现一个分布式系统就逃不开对分布式事务的支持。本文从分布式事务这个概念切入,尝试对分布式事务...

oracle 死锁了怎么办?kill 进程 直接上干货

1、查看死锁是否存在selectusername,lockwait,status,machine,programfromv$sessionwheresidin(selectsession...

SpringBoot 各种分页查询方式详解(全网最全)

一、分页查询基础概念与原理1.1什么是分页查询分页查询是指将大量数据分割成多个小块(页)进行展示的技术,它是现代Web应用中必不可少的功能。想象一下你去图书馆找书,如果所有书都堆在一张桌子上,你很难...

《战场兄弟》全事件攻略 一般事件合同事件红装及隐藏职业攻略

《战场兄弟》全事件攻略,一般事件合同事件红装及隐藏职业攻略。《战场兄弟》事件奖励,事件条件。《战场兄弟》是OverhypeStudios制作发行的一款由xcom和桌游为灵感来源,以中世纪、低魔奇幻为...

LoadRunner(loadrunner录制不到脚本)

一、核心组件与工作流程LoadRunner性能测试工具-并发测试-正版软件下载-使用教程-价格-官方代理商的架构围绕三大核心组件构建,形成完整测试闭环:VirtualUserGenerator(...

Redis数据类型介绍(redis 数据类型)

介绍Redis支持五种数据类型:String(字符串),Hash(哈希),List(列表),Set(集合)及Zset(sortedset:有序集合)。1、字符串类型概述1.1、数据类型Redis支持...

RMAN备份监控及优化总结(rman备份原理)

今天主要介绍一下如何对RMAN备份监控及优化,这里就不讲rman备份的一些原理了,仅供参考。一、监控RMAN备份1、确定备份源与备份设备的最大速度从磁盘读的速度和磁带写的带度、备份的速度不可能超出这两...

取消回复欢迎 发表评论: