从源码看 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五种数据类型,底层存储数据结构,以及相关命令
https://blog.csdn.net/dxh9231028/article/details/140824108
lru:
在基于LRU算法的内存淘汰策略下保存过期时间戳,在基于LFU算法德内存淘汰策略下保存的时一个代表访问频率高低整数(不是访问次数),想了解具体内容可以看我的另一篇帖子redis-过期key删除,内存淘汰策略,内存碎片化处理
https://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:
指向实际数据值的指针。实际数据的类型和结构取决于 type 和 encoding 字段的值。比如说如果是string类型,那么就可以指向一个SDS结构体的对象,如果是hash类型,有可能会指向一个hash表等等。
相关文章:
从源码看 Redis:深入理解 redisDb 和 redisObject
Redis 是一个广泛使用的内存数据库,以其高性能和丰富的数据结构而闻名。不同于磁盘数据库,磁盘数据库将数据读取到文件中维护,而内存数据库将数据存储在内存中,意味着其想要维护数据,必须在代码中维护一个保存数据的结…...
unity中实现流光效果——世界空间下
Properties{_MainTex ("Texture", 2D) "white" {}_FlowColor ("Flow Color", Color) (1, 1, 1, 1) // 流光颜色_FlowFrequency ("Flow Frequency", Float) 1.0 // 流光频率_FlowSpeed ("Flow Speed", Float) 1.0 // 流光…...
项目经验分享:用4G路由器CPE接海康NVR采用国标GB28181协议TCP被动取流一段时间后设备就掉线了
最近我们在做一个生态化养殖的项目时,发现一个奇怪的现象: 项目现场由于没有有线网络,所以,我们在现场IPC接入到海康NVR之后,再通过一款4G的CPE接入到天翼云的国标GB28181视频平台;我们采用UDP协议播放NVR…...
【RabbitMQ】RabbitMQ不公平分发_预取值
一、不公平分发 1、简介 RabbitMQ中的不公平分发(Unfair Dispatch)是指当多个消费者(Consumers)同时订阅同一个队列(Queue)时,消息的分发机制并非严格平均或公平,而是基于某些条件…...
最新AI模型使用指南和模型
市面上最好的AI大模型 OpenAI GPT-4: 概述:GPT-4 是 OpenAI 发布的最新一代大型语言模型,具备更强的理解和生成自然语言的能力。特点: 强大的文本生成和理解能力。支持多语言处理。可用于各种应用场景,如对话生成、内容…...
数据结构之八大基本排序方法
在数据结构中,排序是一个重要的操作,它有助于提高数据的可读性和可操作性。排序算法有多种,各有优缺点,适用于不同的场景。以下是八大经典排序算法的介绍: 1. 冒泡排序(Bubble Sort) 原理&…...
《Milvus Cloud向量数据库指南》——什么是高可用:深入理解数据库系统中的高可用性架构
什么是高可用:深入理解数据库系统中的高可用性架构 在信息技术日新月异的今天,高可用性(High Availability,简称HA)已成为衡量一个系统,尤其是数据库系统稳定性和可靠性的重要标准。高可用性的核心目标在于确保系统能够持续不断地提供服务,最大限度地减少因维护活动、硬…...
C++ | Leetcode C++题解之第319题灯泡开关
题目: 题解: class Solution { public:int bulbSwitch(int n) {return sqrt(n 0.5);} };...
C# 使用 NLog 输出日志到文件夹
在项目中使用 NuGet 安装 NLog 包以及 NLog.Config 包 配置 nlog.config 在项目的根目录下创建一个 Nlog.config 文件(如果还没有),然后添加如下配置: <?xml version"1.0" encoding"utf-8" ?> <…...
node.js使用NodeMachineID 生成唯一UUID和注意事项
node-machine-id用于获取或生成唯一的机器ID 如何使用 const { machineId, machineIdSync } require(node-machine-id) JSON.stringify(machineIdSync({original: true})) ;方法: machineIdSync 此函数同步获取操作系统本机UUID/GUID,默认情况下进行哈…...
AI大模型在数据治理中的应用
目前,企业的数据治理工作以人工实施为主,其中一些重复性较强的工作,如:数据标准制定和映射、元数据信息完善、数据目录挂载等,需要消耗大量的人力和时间成本,这给本来就难以量化业务价值的治理工作的顺利推…...
【初学人工智能原理】【12】循环:序列依赖问题
前言 本文教程均来自b站【小白也能听懂的人工智能原理】,感兴趣的可自行到b站观看。 代码及工具箱 本专栏的代码和工具函数已经上传到GitHub:1571859588/xiaobai_AI: 零基础入门人工智能 (github.com),可以找到对应课程的代码 正文 对于…...
【QT】无法打开QT的ui文件,出现闪退情况
打开qt的ui文件出现闪退的情况: 解决办法:点击扩展-Qt VS Tools-Options 找到Qt General中的Qt Designer 的Run in detached window改为True。...
三、Spring-WebFlux实战案例-流式
目录 一、springboot之间通讯方式 1. 服务端 (Spring Boot) 1.1 添加依赖 1.2 控制器 2. 客户端 (WebClient) 2.1 添加依赖 2.2 客户端代码 3. 运行 二、web与服务之间通讯方式 1、服务端代码 2、客户端代码 3、注意事项 三、移动端与服务端之间通讯方式…...
html+css 实现hover双层按钮
前言:哈喽,大家好,今天给大家分享htmlcss 绚丽效果!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 文…...
SPIFFS与LittleFS的对gz文件格式的区别
SPIFFS 只能安装在Arduino上。LittleFS支持Arduino IDE和VScode的 PlatformIO。 SPIFFS serveStatic: server.serveStatic("/", SPIFFS, "/") 负责提供 SPIFFS 文件系统中的文件。您可以在 SPIFFS 上放置 .gz 文件,并该方法将自动处理它们。 …...
STM32L051K8U6-开发资料
STM32L051测试 (四、Flash和EEPROM的读写)-云社区-华为云 (huaweicloud.com) STM32L051测试 (四、Flash和EEPROM的读写) - 掘金 (juejin.cn) STM32L0 系列 EEPROM 读写,程序卡死?_stm32l0片内eeprom_stm3…...
Markdown语法学习
Markdown学习 一、基础语法讲解 1. 换行 本行末尾双空格然后回车(在Typora的中直接回车也可以) 2. 换段 本段末尾两次回车 3. 加粗 **加粗** __加粗__效果:加粗 4. 斜体 *加粗* _加粗_效果:斜体 5. 斜体加粗 ***加粗**…...
[最短路Floyd],启动!!!
B3647 【模板】Floyd #include<bits/stdc.h> #define ll long long #define fi first #define se second #define pb push_back #define PII pair<int,int > #define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) using namespace std; const int N …...
7月29(信息差)
🌍最强模型 Llama 3.1 如期而至!扎克伯格最新访谈:Llama 会成为 AI 界的 Linux 🎄谷歌AlphaProof攻克国际奥赛数学题 https://www.51cto.com/article/793632.html ✨SearchGPT第一波评测来了!响应速度超快还没广告&…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...
保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...
LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...
