Redis的五大数据类型实现原理

[Redis数据结构|Java实现] 一:SDS简单动态字符串 [Redis数据结构|Java实现] 一:SDS简单动态字符串SDS的概念JAVA实现核心代码测试测试结果: SDS的概念 SDS: 保存了len和free属性,并保存了字节数组,同时以‘\0’结尾。 可以在改变字符串长度的时候,减少内存的分配次数,提高性能。 并且可以重用一部分c中的String Api. free属性为0,表示这个SDS没有未使用的空间。 len的属性为5,表示这个SDS保存了5字节长的字符串。 buf是一个char类型的数组,最后一个位置保存了’\0’(为了复用语言的api)。 [ 阅读详情

1. 对象的类型与编码

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

typedef struct redisObject{
     //类型
     unsigned type:4;
     //编码
     unsigned encoding:4;
     //指向底层数据结构的指针
     void *ptr;
     //引用计数
     int refcount;
     //记录最后一次被程序访问的时间
     unsigned lru:22;
 
}robj
① type属性

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

可以通过如下命令来判断对象类型:

type key

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

② encoding 属性和 *prt 指针

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

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

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

OBJECT ENCODING  key

比如 string 类型:

2. 字符串对象

字符串是Redis最基本的数据类型,不仅所有key都是字符串类型,其它几种数据类型构成的元素也是字符串。注意字符串的长度不能超过512M。

① 编码

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

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

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

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

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

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’ 的三个值的列表。

rpush numbers 1 "three" 5

ziplist 编码表示如下:

linkedlist表示如下:

② 编码转换

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

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

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

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

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

4. 哈希对象

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

① 编码

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

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

hset profile name "Tom"
hset profile age 25
hset profile career "Programmer"

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

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

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。

SADD numbers 1 3 5

SADD Dfruits "apple" "banana" "cherry"

② 编码转换

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

1、集合对象中所有元素都是整数

2、集合对象所有元素数量不超过512

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

6. 有序集合对象

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

① 编码

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

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

ZADD price 8.5 apple 5.0 banana 6.0 cherry

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

typedef struct zset{
     //跳跃表
     zskiplist *zsl;
     //字典
     dict *dice;
} 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 操作等。

sds:SDS是一个基于Java开发的简单,易用,高性能的服务降级系统,支持限流,熔断和降级等功能,服务端必备!! SDS(​​服务降级系统) 1.背景 移动互联网时代的来临,给业务增长插上翅膀的同时,也给服务端应用带来了巨大的挑战,大流量,高并发和海量数据似乎成为了服务端应用的标配。 为了对端上请求进行统一处理,鉴权和负载均衡等,服务端一般会有个网关层,网关层拦截所有的流量,进行统一的限流,鉴权和流量转发管理,对外屏蔽内部的处理细节,网关层的下游,是一个由某个服务治理框架来管理多个应用的​​大型服务网络,虽然我们能使用微服务架构来对应用进行分解,让多个应用之间作用,边界更清晰,做到独立横向扩展,并能匹配团队来进行快速迭代开发和维护。微服务架构,会导致团队需要维护的应用数量成倍增加,错综复杂的服务依赖,可能架构师都说无需各应用的依赖关系,一旦有人应用或下游依赖出问题,就可能导致整个核心服务瘫痪,而大多数服务治理框架的自动容错,隔离和恢复能力都比较简单,缺乏专业的界面来进行策略调整和维护,所以急需一个专 立即下载

相关推荐

一生一芯 预学习阶段 NEMU代码学习(2)

如果 nemu_state.state == NEMU_ABORT:说明程序处于 "中止" 状态,输出 "ABORT",并且使用 ANSI_FG_RED 红色格式化显示。如果 halt_ret == 0,表示程序正常终止(触发了 "GOOD TRAP"),输出 "HIT GOOD TRAP",并使用 ANSI_FG_GREEN 绿色显示。如果要执行的指令数量 n 小于预定义的常量 MAX_INST_TO_PRINT,则将 g_print_step 置为 true,表示会逐步打印指令执行的过程。

weixin_45041054的博客 828

SDS - 基于Java的服务降级系统

SDS - 基于Java的服务降级系统 SDS(Service Downgrade System)是一个基于Java开发的开源项目,旨在为Java应用提供简单易用的高性能服务降级解决方案。它支持限流、熔断和降级等功能,可以帮助服务端应用在大流量、高并发和海量数据场景下保持稳定运行。 核心功能 SDS的核心功能包括: 限流:支持多种限流方式,包括访问量限流、并发限流、异常限流、超时限流和令牌桶限流...

gitblog_00970的博客 428

Unity 接入 Steam 平台

Unity 接入 steam sdk 的登录和应用内购买功能

MarinaTsang的博客 3907

JAVA面试+Redis

反射是通过获取类的class对象,然后动态的获取到这个类的内部结构,动态的去操作类的属性和方法。应用场景有:要操作权限不够的类属性和方法时、实现自定义注解时、动态加载第三方jar包时、按需加载类,节省编译和初始化时间;获取class对象的方法有:class.forName(类路径),类.class(),对象的getClass()java.lang----包含一些Java语言的核心类,如String、Math、Integer、 System和Thread,提供常用功能java.net。

jie___ge的博客 844

Cadence Virtuoso里搞定斩波运放AC仿真:PSS+PAC保姆级设置避坑指南

然而,当工程师们尝试在Cadence Virtuoso环境中对这种特殊结构进行AC特性分析时,往往会遇到传统AC仿真方法失效的困境——这正是PSS(Periodic Steady-State)与PAC(Periodic AC)仿真组合大显身手的场景。实际项目中我们常采用"先快后精"的两步法:先用快速设置确认大体趋势,再针对关键频段进行精细仿真。例如某次设计迭代中,将harmonics从10增加到20后,发现在1MHz处的相位裕度估算误差达15°,这解释了之前样机测试时的振荡问题。

weixin_33508411的博客 453

【数据分析生命周期全揭秘】从零开始打造你的数据科学项目 | 最全指南

在当今数据驱动的世界中,数据科学正在颠覆传统行业,成为企业决策和价值创造的重要引擎。然而,如何科学、系统地开展一个数据分析项目?这是很多人关心的核心问题。本篇文章基于经典数据分析课程内容,深入解读数据分析生命周期的每个阶段,让你快速掌握从“发现问题”到“落地应用”的完整流程。如果你正在学习或准备从事数据分析领域,这篇文章一定会对你大有帮助!数据分析生命周期的六大阶段数据分析生命周期的六个阶段相辅相成,每个阶段都至关重要:发现问题:明确需求,提出假设。数据准备:清洗、转换和可视化数据。

AI手套的博客 1743

一篇带你搞懂Redis数据结构之SDS

SDS巧妙的利用空间换时间的思想,虽然额外牺牲了一些空间,但是换来的是在高频场景下更佳优异的性能表现以及更好的兼容性。希望这篇文章能对大家在日常工作中有所启发。

wdj_yyds的博客 1557

eNSP网络构建—建立小型局域网

企业私有网络构建运维 实战案例——使用模拟器构建局域网络 案例分析 1.架构分析 (1)需求分析 本实验的目的在于建立小型局域网。由于公司由不同部门组成,并分布在不同地点,因此需要划分不同网络实现互联互通。设计以下网络:两个部门各使用一台交换机连接,然后连接到总交换机,再通过路由器与外网以及其他部门网络相连。为了控制网络上的广播风暴,增加网络的安全性,在交换机上需要设置VLAN,在路由器与交换机之...

_ 4万+

redis源码阅读—sds

文章目录sdshdr定义sds逻辑图sds优势更快的获取字符串长度杜绝缓冲区溢出减少修改字符串时带来的内存重分配次数二进制安全关键代码获取常见值创建对象添加字符(扩容)重点!!! sdshdr定义 真实的数据并不是直接存储,也有封装,看下面的代码就知道分为五种,分别是sdshdr5,sdshdr8,sdshdr16,sdshdr32,sdshdr64。sdshdr5和另外四种的区别比较明显,sdshrd5其实对内存空间的更加节约。包括已用长度len,总长度alloc(分配的长度),标记flags,实际数据b

qq_36581961的博客 668

Multisim14使用教程详尽版--(2025最新版)

摘要:本文详细介绍了Multisim14电路仿真软件的功能和使用方法。主要内容包括:1)主流电路仿真软件比较,突出Multisim在教学、竞赛设计中的优势;2)软件界面说明,涵盖菜单栏、工具栏、元器件库和仪器仪表;3)18类元器件分类详解及其使用操作;4)15种仪器仪表的原理和应用场景;5)电路原理图设计与仿真流程;6)基本电路分析方法(直流静态工作点分析、交流分析等)。文章还提供了硬件工程师笔试面试相关资源链接,涵盖电阻、电容、三极管等器件知识及AD软件操作指南。通过系统讲解,帮助用户掌握Multisim

XU157303764的博客 2万+

《C++面向对象程序设计》✍千处细节、万字总结(建议收藏)

《C++面向对象程序设计》✍千处细节、万字总结 文章目录《C++面向对象程序设计》✍千处细节、万字总结一、面向对象程序设计二、C++基础2.1 C++的产生和特点2.2 一个简单的C++示例程序2.3 C++在非面向对象方面对C语言的扩充输入和输出cinconst修饰符void型指针内联函数带有默认参数值的函数函数重载作用域标识符"::"强制类型转换new和delete运算符引用三、类和对象(一)3.1 类的构成3.2 成员函数的定义3.3 对象的定义和使用3.4 构造函数与析构函数构造函数成员初始化列表

像写诗一样优雅地写代码~ 78万+

【 Redis五大数据类型实现原理】

键不同,值相同。

2401_86968712的博客 2544

2017年全国大学生电子设计竞赛综合测评题目解析——Multisim仿真

1.题目 给定两个单电源的双运放芯片READ2302G芯片(当时记得增益带宽积好像是6M),一片HD74LS74数字芯片双D触发器,需要详细电路图、手写报告,5个波形输出,测频,测幅,8:00公布题目,15:00停止答题,中间可以吃饭(也可以不吃继续做),15:00清场,休息一段时间后开始进场测试,打分。 2.要求 (1)一片运放搭建方波振荡电路,频率 20 KHz,误差 0.1 KHz,幅度 3...

DengFengLai123的博客 2万+

redis的五大数据类型实现原理

1、对象的类型与编码   Redis使用前面说的五大数据类型来表示键和值,每次在Redis数据库中创建一个键值对时,至少会创建两个对象,一个是键对象,一个是值对象,而Redis中的每个对象都是由 redisObject 结构来表示: 1 2 3 4 5 6 7 8 9 10 11 12 13...

阿瞒--治国之能臣 乱世之奸雄 251

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Redis——五大数据类型实现原理

redis的五大数据类型实现原理1. 字符串(string)2. list(列表)3. hash(字典)4. set ( 集合对象 )5. Sorted set (有序集合对象) redis中所有数据结构都以唯一的key字符串作为名称,然后通过这个唯一的key来获取对应的value 不同的数据类型数据结构差异就在于value的结构不一样 1. 字符串(string) value的数据结构(数组)...

wxina 299

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

【redis】五大数据类型实现原理

Redis 的五大数据类型 String、Hash、List、Set、ZSet 分别通过不同的数据结构实现,充分利用了内存数据库的特性,满足了不同场景下的数据存储和访问需求。通过这些底层实现,Redis 能够在高性能的同时,提供灵活的数据操作方式。

Senkorl blog 1041

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

redis五大数据类型实现原理

目录 1、对象的类型与编码 ①、type属性 ②、encoding 属性和 *prt 指针 2、字符串对象 3、列表对象 4、哈希对象 5、集合对象 6、有序集合对象 7、五大数据类型的应用场景 8、内存回收和内存共享 ①、内存回收 ②、内存共享 9、对象的空转时长   前面两篇博客,第一篇介绍了五大数据类型的基本用法,第二篇介绍了Redis底层的六...

li_mancheng的博客 222

Redis详解(五)------ redis的五大数据类型实现原理

目录 1、对象的类型与编码 ①、type属性 ②、encoding 属性和 *prt 指针 2、字符串对象 3、列表对象 4、哈希对象 5、集合对象 6、有序集合对象 7、五大数据类型的应用场景 8、内存回收和内存共享 ①、内存回收 ②、内存共享 9、对象的空转时长   前面两篇博客,第一篇介绍了五大数据类型的基本用法,第二篇介绍了Redis底层的六种数据结构。在Redis中,并没有直接使用这些数据结构来实现键值对数据库,而是基于这些数据结构创建了一个对象系统..

204

Redis的五大数据类型实现原理、Redis单线程模型

https://www.cnblogs.com/ysocean/p/9102811.html

yeguangchen的博客 190

Redis 详解 (五) redis的五大数据类型实现原理

目录 1、对象的类型与编码 ①、type属性 ②、encoding 属性和 *prt 指针 2、字符串对象 3、列表对象 4、哈希对象 5、集合对象 6、有序集合对象 7、五大数据类型的应用场景 8、内存回收和内存共享 ①、内存回收 ②、内存共享 9、对象的空转时长   前面两篇博客,第一篇介绍了五大数据类型的基本...

weixin_30745641的博客 121
上一篇: 那些你必须知道的MyBatis实用知识点
下一篇: 缓存热点,缓存穿透,终极解决方案看过来
Java技术那些事儿
博客等级 码龄5年 2306粉丝 2584原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值