当前位置: 首页 > news >正文

从源码看 Redis:深入理解 redisDb 和 redisObject

Redis 是一个广泛使用的内存数据库,以其高性能和丰富的数据结构而闻名。不同于磁盘数据库,磁盘数据库将数据读取到文件中维护,而内存数据库将数据存储在内存中,意味着其想要维护数据,必须在代码中维护一个保存数据的结构,而redis由c语言编写,对应的其一定是通过结构体来保存数据的结构。

redisDb结构体

在redis源码中,每个redisDb结构体代表着一个数据库,结构体大致如下

typedef struct redisDb {dict *dict;                 dict *expires;              dict *blocking_keys;        dict *ready_keys;           dict *watched_keys;         int id;                     long long avg_ttl;          unsigned long expires_cursor; 
} redisDb;

让我们来一个一个解释其意义

dict:

数据字典,其中保存了所有存入的数据,在redis中没有表的概念,数据作为键值对存储,直接存入数据库中,以hash表的结构存储,我在讲解redis中五个基本数据类型中详细讲解了hash表的结构,想了解可以看我的这篇文章Redis五种数据类型,底层存储数据结构,以及相关命令。

expire:

这也是一个数据字典,不同的是,其存储的是key和其对应的过期时间(时间戳)。将过期时间单独存储,有利于redis便利key查找过期key(有的key不设过期时间,单独存储可以防止便利这些没有过期时间的key)

blocking_keys:

这仍然是一个数据字典,其中保存的是正在阻塞等待中的key,比如说一个客户端对一个list数据使用了blpop命令,但list没有数据,此时客户端就会进入阻塞状态,等待list插入数据,当多个客户端都对一个空的list使用blpop命令,那么则需要一个结构来维护他们的先后关系,blocking_keys的作用就是维护阻塞key和等待其数据的客户端的先后关系。

ready_keys:

这也是一个数据字典,当blocking_keys中维护的key有新数据插入时(每次插入数据都会检查是否包含在blocking_keys中),会讲对应的key放入ready_keys中,等待当前事件循环中的插入数据操作完成后,在便利ready_key获取key,并且根据这个key在block_keys和dict中获取客户端和值并且发送(高并发情况下,一次会有大量的插入操作,先执行完当前事件循环的插入操作,并且放入ready_keys中,插入操作完成后再统一返回给客户端)。当使用publish发布订阅消息时,订阅消息也会放入ready_keys中,与blpop不同的是,所有订阅这个消息的客户端都会收到这个消息,没有先后顺序一分,所以不需要维护客户端的先后关系,也就不需要进入block_keys。

watched_keys:

当我们使用redis开启一个事务时,我们需要先确定这个事务依赖于哪些key,然后通过watch key1 key2 ... 的命令来监控这些key,那么当前这个事务就会作为这些key的value被保存在watched_keys中,当对key进行修改操作时,会去查看watch_keys中是否有这个key,如果有,则将key对应的全部事务进行取消。并且便利watched_keys将其他key中保存的当前事务删除。

id:

唯一id,没什么好说的。

avg_ttl:

保存expire中保存的过期时间的平均值,每当平均时间改变时都要重新计算一次。

expires_cursor:

当前便利位置的游标,redis内存淘汰过程中需要便利检查key是否过期,不过大量的key一次性遍历势必会造成程序卡顿,为了防止这种情况,在周期性模式下,一次性会检查一部分key,然后保存当前位置作为游标,下次检查时会接着游标的位置继续遍历。

结构体示意图如下

redisObject

我们在redisDB结构体的中dict数据字典中保存的都是key和数据,而数据的结构则是redisObject,同redisDB一样,redisObject也是一个结构体,代码如下

typedef struct redisObject {unsigned type:4;         unsigned encoding:4;         unsigned lru:LRU_BITS;   int refcount;            void *ptr;               
};

type:

对象类型,也就是redis五大基本数据类型以及两个高级数据类型(bitmap和hyperloglog底层是string类型,而geo底层是zset类型),其中包括REDIS_STRING,REDIS_LIST,REDIS_SET,REDIS_ZSET,REDIS_HASH,REDIS_MODULE,REDIS_STREAM

encoding:

编码方式,简单来说redis基本数据类型的保存也要精心设计来提高其内部属性的操作性能,因为一个基本数据类型内部也保存了大量的元素或键值对,而编码方式就是某个类型用了什么样的数据结构来保存其内部的键值对或元素,其中包括SDS,整数列表,压缩列表,双向链表,快速列表,hash表,跳表。想了解更多可以看我的另一个文章Redis五种数据类型,底层存储数据结构,以及相关命令icon-default.png?t=N7T8https://blog.csdn.net/dxh9231028/article/details/140824108​​​​​​​

lru:

在基于LRU算法的内存淘汰策略下保存过期时间戳,在基于LFU算法德内存淘汰策略下保存的时一个代表访问频率高低整数(不是访问次数),想了解具体内容可以看我的另一篇帖子redis-过期key删除,内存淘汰策略,内存碎片化处理icon-default.png?t=N7T8https://blog.csdn.net/dxh9231028/article/details/138451287?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22138451287%22%2C%22source%22%3A%22dxh9231028%22%7D

refcount:

引用计数,用于内存管理。当引用计数为 0 时,表示没有任何地方引用该对象,内存可以被回收。

ptr:

指向实际数据值的指针。实际数据的类型和结构取决于 typeencoding 字段的值。比如说如果是string类型,那么就可以指向一个SDS结构体的对象,如果是hash类型,有可能会指向一个hash表等等。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Python笔试面试题AI答之面向对象常考知识点
  • 图形编辑器基于Paper.js教程10:导入导出svg,导入导出json数据
  • 深度对话安天王小丰:我们应该从微软“蓝屏”事件学到什么?
  • 在云服务器上自动化部署项目,jenkins和gitee
  • 9.Redis的Set类型
  • 绝密!OceanBase OBCP备考模拟题讲解(1)
  • Python数值计算(1)——Numpy中数据的保存和加载
  • 芋道源码yudao-cloud 二开笔记(Feign服务调用,如何定义一个 API 接口)
  • 信息学奥赛初赛天天练-52-CSP-J2019基础题3-抽屉原理、鸽巢原理、乘法原理、二叉树遍历、前序遍历、中序遍历、后序遍历
  • 下属“软对抗”,工作阳奉阴违怎么办?4大权谋术,让他不敢造次
  • 复制列表(切片复制)
  • 前端:Vue学习 - 智慧商城项目
  • 数值分析——分段低次插值
  • 怎么给USER新增表空间文件
  • c语言指针中“数组名的理解”以及“一维数组传参”的本质
  • 2017前端实习生面试总结
  • android图片蒙层
  • CentOS 7 防火墙操作
  • express.js的介绍及使用
  • iOS帅气加载动画、通知视图、红包助手、引导页、导航栏、朋友圈、小游戏等效果源码...
  • Linux后台研发超实用命令总结
  • Material Design
  • mysql 5.6 原生Online DDL解析
  • rabbitmq延迟消息示例
  • Sublime text 3 3103 注册码
  • VuePress 静态网站生成
  • 从@property说起(二)当我们写下@property (nonatomic, weak) id obj时,我们究竟写了什么...
  • 记录一下第一次使用npm
  • 技术攻略】php设计模式(一):简介及创建型模式
  • 如何解决微信端直接跳WAP端
  • 如何优雅的使用vue+Dcloud(Hbuild)开发混合app
  • 微信小程序填坑清单
  • 如何正确理解,内页权重高于首页?
  • ​​​​​​​Installing ROS on the Raspberry Pi
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • ​TypeScript都不会用,也敢说会前端?
  • ​第20课 在Android Native开发中加入新的C++类
  • ​软考-高级-系统架构设计师教程(清华第2版)【第15章 面向服务架构设计理论与实践(P527~554)-思维导图】​
  • $ git push -u origin master 推送到远程库出错
  • (C语言)球球大作战
  • (Python) SOAP Web Service (HTTP POST)
  • (分布式缓存)Redis哨兵
  • (附源码)ssm高校运动会管理系统 毕业设计 020419
  • (紀錄)[ASP.NET MVC][jQuery]-2 純手工打造屬於自己的 jQuery GridView (含完整程式碼下載)...
  • (面试必看!)锁策略
  • (亲测有效)解决windows11无法使用1500000波特率的问题
  • (三)Pytorch快速搭建卷积神经网络模型实现手写数字识别(代码+详细注解)
  • (四)React组件、useState、组件样式
  • (转)JAVA中的堆栈
  • (转)用.Net的File控件上传文件的解决方案
  • (转)真正的中国天气api接口xml,json(求加精) ...
  • .locked1、locked勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .NET Micro Framework初体验
  • .NET 回调、接口回调、 委托
  • .net 提取注释生成API文档 帮助文档