Redis数据库——键空间

news2024/11/25 23:42:13

一.服务器中的数据库

        Redis服务器将所有数据库都保存在服务器状态redis.h/redisServer结构的db数组中,db数组的每一个项都是一个redis.h/redisDb结构,每一个RedisDb结构代表一个数据库。

        在初始化服务器时,程序会根据服务器状态的dbnum属性来决定应该创建多少个数据库。

typedef struct redisDb {
    dict *dict;                 /* The keyspace for this DB */
    dict *expires;              /* Timeout of keys with a timeout set */
    dict *blocking_keys;        /* Keys with clients waiting for data (BLPOP)*/
    dict *ready_keys;           /* Blocked keys that received a PUSH */
    dict *watched_keys;         /* WATCHED keys for MULTI/EXEC CAS */
    int id;                     /* Database ID */
    long long avg_ttl;          /* Average TTL, just for stats */
    unsigned long expires_cursor; /* Cursor of the active expire cycle. */
    list *defrag_later;         /* List of key names to attempt to defrag one by one, gradually. */
} redisDb;

struct redisServer {
    /* General */
    pid_t pid;                  /* Main process pid. */
    pthread_t main_thread_id;         /* Main thread id */
    char *configfile;           /* Absolute config file path, or NULL */
    char *executable;           /* Absolute executable file path. */
    char **exec_argv;           /* Executable argv vector (copy). */
    int dynamic_hz;             /* Change hz value depending on # of clients. */
    int config_hz;              /* Configured HZ value. May be different than
                                   the actual 'hz' field value if dynamic-hz
                                   is enabled. */
    mode_t umask;               /* The umask value of the process on startup */
    int hz;                     /* serverCron() calls frequency in hertz */
    int in_fork_child;          /* indication that this is a fork child */
    //数据库数组
    redisDb *db;
    ...
    ...
    int dbnum;                      /* Total number of configured DBs */
    ...
    ...
};

        dbnum属性的值有服务器配置的database选项决定,默认情况下该选项的值为16,所以Redis服务器默认会创建16个数据库。

 二. 切换数据库

        每一个Redis客户端都有自己的目标数据库,每当客户端执行数据库写命令或者数据库读命令的时候,目标数据库就会成为这些命令的操作对象。

        默认情况下,Redis客户端的目标数据库为0号数据库,但客户端可以通过执行select命令来切换目标数据库。

         在服务器内部,客户端的状态client结构的db属性记录了客户端当前的目标数据库,这个属性是指向redisServer.redisDb结构的指针。

typedef struct client {
    uint64_t id;            /* Client incremental unique ID. */
    connection *conn;
    int resp;               /* RESP protocol version. Can be 2 or 3. */
    //记录当前正在使用的数据库
    redisDb *db;            /* Pointer to currently SELECTed DB. */
    ...
    ...
}client;

        client.db指针指向redisServer.db数组的其中一个元素,而被指向的元素就是客户端的目标数据库。

         select的实现原理:通过修改client.db指针,让它指向服务器不同的数据库,从而实现切换目标数据库的功能。

        目前,Redis仍然没有可以返回客户端目标数据库的命令,虽然redis-cli客户端在输入符旁边提示当前所使用的目标数据库。

        但是,你在其他语言的客户端中执行redis命令,并且该客户端好像没有向redis-cli那样显示目标数据库的号码,在多次切换数据库之后,你可能会忘记当前使用的哪个数据库。

        为了避免误操作,在执行Redis命令,特别向FLUSHDB这样的危险命令前,最好先执行一个select命令,显示的切换到指定数据库,然后再执行别的命令。

三.数据库的键空间

        Redis是一个键值对数据库服务器,服务器中的每一个数据库是由一个redis.h/redisDb结构表示。其中redisDb结构中的dict字典保存了数据库中的所有键值对,我们简称这个字典为键空间。

typedef struct redisDb {
    //键空间
    dict *dict;                 /* The keyspace for this DB */
    dict *expires;              /* Timeout of keys with a timeout set */
    dict *blocking_keys;        /* Keys with clients waiting for data (BLPOP)*/
    dict *ready_keys;           /* Blocked keys that received a PUSH */
    dict *watched_keys;         /* WATCHED keys for MULTI/EXEC CAS */
    int id;                     /* Database ID */
    long long avg_ttl;          /* Average TTL, just for stats */
    unsigned long expires_cursor; /* Cursor of the active expire cycle. */
    list *defrag_later;         /* List of key names to attempt to defrag one by one, gradually. */
} redisDb;

        键空间和用户所见到的数据库是直接对应的:

  • 键空间的键也就是数据库的键,每一个键都是一个字符串对象。
  • 键空间的值也就是数据库的值,每一个值可以是字符串对象,列表对象,哈希表对象,集合对象和有序集合对象中的任意一种Redis对象。 

         举个例子:

127.0.0.1:6379> set message "hello world"
OK
127.0.0.1:6379> rpush alphabet "a" "b" "c"
(integer) 3
127.0.0.1:6379> hset book name "Redis in Action"
(integer) 1
127.0.0.1:6379> hset book author "Josiah L. Carlson" publisher "Manning"
(integer) 2
127.0.0.1:6379> 
  • messge是一个字符串键,键的名字是一个包含字符串messge的字符串对象,键的值是一个包含字符串"hello world"的字符串对象。
  • alphabet是一个列表键,键的名字是一个包含字符串alphabet的字符串对象,键的值是一个包含三个元素的列表对象。
  • book是一个哈希键,键的名字是一个包含字符串book的字符串对象,键的值是一个包含三个键值对的哈希表对象。

        3.1 数据库的增删查改 

        因为数据库的键是一个字典,所以对数据库的增删查改,实际是对字典的增删查改。

                 3.1.1添加新建

        添加一个新的键值对到数据库,实际上就是将一个新键值对添加到键空间字典中,其中键为字符串对象,而值为Redis任意一种类型的Redis对象。

        比如:

127.0.0.1:6379> set date "2023.12.1"
OK

         添加一个新键值对,键是一个值为date字符串的字符串对象,键的值为2023.12.1字符串的字符串对象。

                3.1.2 删除键 

        删除数据库中的一个键,实际上就是在键空间里面删除键所对应的键值对对象。就是删除字典中的一个节点。

127.0.0.1:6379> del book
(integer) 1

                3.1.3 更新键 

         对一个数据库键进行更新,实际上就是对键空间里面键对应的值对象进行更新根据值对象的类型不同,更新的具体方法也会不同。

127.0.0.1:6379> get message
"hello world"
127.0.0.1:6379> set message "blah blah"
OK
127.0.0.1:6379> get message
"blah blah"

        上面是对数据库键message对应的值"hello world"字符串修改成了"blah blah"字符串。

127.0.0.1:6379> hset book page 320
(integer) 1
127.0.0.1:6379> 

        上面是修改数据库键book对应的值哈希对象,新加一个节点键为page,值为320。 

                3.1.4 对键取值 

            对一个数据库键进行取值,实际上就是对键空间里面取出键所对应的值对象根据值对象的类型不同,更新的具体方法也会不同。

127.0.0.1:6379> get message
"hello world"

        get命令首先在键空间(client.db)中查找键message,找到键后,去到该键对应的字符串对象,之后返回值对象所包含的字符串"hello world"

127.0.0.1:6379> lrange alphabet 0 -1
1) "a"
2) "b"
3) "c"
127.0.0.1:6379> 

        lrange命令首先在键空间(client.db)中查找键alphabet,找到键后,去到该键对应的列表对象值,之后返回列表对象中包含的三个字符串对象的值。

                3.1.5 其他键空间操作

        除了增删查改操作外,还有针对数据库本身的Redis命令, 也是通过键空间进行处理完成的。

  • FLUSHDB:通过删除键空间的所有键值对实现的
  • RANDOMKEY:通过在键空间随机返回一个键实现的
  • DSSIZE:返回键空间中包含的键值对的数量

        其他命令exits,rename,keys等,都是通过对键空间进行操作来实现的。

                3.1.6 读写键空间的维护操作

        当使用Redis命令对数据库进行读写时,服务器不仅会对键空间执行指定的读写操作,还会执行额外的维护操作。

  • 在读取一个键时(读操作和写操作都会对键进行读取),服务器会更具键是否存在来更新服务器的键的空间命中(hit)次数或键的空间不命中次数,可以通过命令info stats命令的keyspace_hits属性和keyspce_misses属性查看。
  • 在读取一个键后。服务器会更新一个键的LRU(最后一次使用)时间,这个值可以用于计算键的闲置时间。使用OBJECT IDLETIME <key>命令来查看键key的闲置时间。
  • 如果服务器在读取一个键发现该键已经过期,那么服务器会先删除这个过期键,然后执行余下操作。
  • 如果客户端使用watch监视一个键,当服务器对监视的键进行修改后,会把这个键标记为脏(dirty),从而让事务注意到这个键已经被修改过。
  • 服务器每修改一个键之后,都会对脏(dirty)键计数器的值增1。这个计数器会触发服务器的持久化以及复制操作
  • 如果服务器开启了数据库通知功能,那么在对键进行修改后,服务器将按配置发送相应的数据库通知。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1332641.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

喷淋实验--嵌入式实训

喷淋实验--嵌入式实训 1.MQTT通信原理 采集信息&#xff1a; 小程序/Linux 订阅者 1703161172612/AIOTSIM2APP 元宇宙 发布者 1703161172612/AIOTSIM2APP Linux订阅的主题是元宇宙发布的主题 控制设备&#xff1a; 小程序/Linux 发布者 1703161172612/APP2AIOTSIM 元宇宙 订阅者…

java并发编程八 CAS 与 volatile和原子整数与原子引用

文章目录 CAS 与 volatile慢动作分析volatile为什么无锁效率高CAS 的特点 原子整数原子引用不安全实现安全实现-使用锁安全实现-使用 CAS CAS 与 volatile 在java并发编程七六中&#xff0c;可以看到的 AtomicInteger 的解决方法&#xff0c;内部并没有用锁来保护共享变量的线…

前端扫盲:什么是API网关?为什么它有用?

API 通常被称为应用程序从后端服务访问数据和业务逻辑的前门。API 本质上是一个软件向其他人或程序提供的接口&#xff0c;允许他们与该软件进行交互。 在创建 API 时&#xff0c;需要选择编程语言(Java、Python、PHP 等)来编写 API 逻辑&#xff0c;还需要将 API 部署到服务器…

前端项目为什么需要 TypeScript 来强化?

什么是TypeScript? TypeScript 是一个为开发大规模应用程序而设计的语言。它是 JavaScript 的一个超集&#xff0c;包含 JavaScript 全部的功能&#xff0c;并扩展了一些新的特性。具体来说&#xff0c;TypeScript 增加了如类型注解和编译时类型检查等特性&#xff1a; let n…

制作自己的 Docker 容器

软件开发最大的麻烦事之一&#xff0c;就是环境配置。用户必须保证操作系统的设置&#xff0c;各种库和组件的安装&#xff0c;只有它们都正确&#xff0c;软件才能运行。docker从根本上解决问题&#xff0c;软件安装的时候&#xff0c;把原始环境一模一样地复制过来。 以 koa-…

分布式事务三阶段提交3PC详解

文章目录 概述工作流程优缺点总结代码样例 概述 3PC 利用超时机制解决了 2PC 同步阻塞问题&#xff0c;避免资源被永久锁定&#xff0c;进一步加强了整个事务过程可靠性。但 3PC 同样无法应对类似宕机问题&#xff0c;只不过出现多数据源中数据不一致问题概率更小。 a. 概念&a…

Python中json模块的使用与pyecharts绘图的基本介绍

文章目录 json模块json与Python数据的相互转化 pyecharts模块pyecharts基本操作基础折线图配置选项全局配置选项 json模块的数据处理折线图示例示例代码 json模块 json实际上是一种数据存储格式&#xff0c;是一种轻量级的数据交互格式&#xff0c;可以把他理解成一个特定格式…

Spark编程实验三:Spark SQL编程

目录 一、目的与要求 二、实验内容 三、实验步骤 1、Spark SQL基本操作 2、编程实现将RDD转换为DataFrame 3、编程实现利用DataFrame读写MySQL的数据 四、结果分析与实验体会 一、目的与要求 1、通过实验掌握Spark SQL的基本编程方法&#xff1b; 2、熟悉RDD到DataFram…

springboot实现发送邮件开箱即用

springboot实现发送邮件开箱即用 环境依赖包yml配置Service层Controller层测试 环境 jdk17 springboot版本3.2.1 依赖包 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId><ver…

【OAuth2】:赋予用户控制权的安全通行证--原理篇

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于OAuth2的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.什么是OAuth? 二.为什么要用OAuth?…

第11章 GUI Page400~402 步骤二 画直线

运行效果&#xff1a; 源代码&#xff1a; /**************************************************************** Name: wxMyPainterApp.h* Purpose: Defines Application Class* Author: yanzhenxi (3065598272qq.com)* Created: 2023-12-21* Copyright: yanzhen…

《每天一分钟学习C语言·九》引用,指针函数,函数指针等

1、 普通全局变量——作用域是整个源程序&#xff08;含有多个源文件&#xff0c;在各个源文件中都有效&#xff09; static全局变量——作用域在当前源文件 2、 引用 &#xff08;1&#xff09;申明引用的同时必须要初始化 &#xff08;2&#xff09;引用变量是目标变量的一个…

Windows 11中显示文件扩展名的方法与Windows 10大同小异,但前者更人性化

默认情况下&#xff0c;Windows 11会隐藏已知文件类型的文件扩展名。这可能会使在不首先打开文件的情况下很难识别文件类型。 幸运的是&#xff0c;你可以将Windows 11配置为显示已知文件类型的扩展名。该方法类似于Windows 10&#xff0c;但该选项现在组织在下拉菜单中&#…

分布式锁功效初探——以电商问题为例

文章目录 电商库存问题单机处理-Sychronized多机器处理-分布式锁入门级别&#xff0c;用redis实现&#xff0c;setnx问题1&#xff1a;逻辑可能异常&#xff0c;造成死锁问题2&#xff1a;机器宕机问题3&#xff1a;锁一直失效&#xff0c;乱套锁续命 redisson分布式丢锁问题主…

python实现元旦多种炫酷高级倒计时_附源码【第20篇—python过元旦】

文章目录 &#x1f30d;python实现元旦倒计时 — 初级(控制台)⛅实现效果&#x1f30b;实现源码&#x1f31c;源码讲解 &#x1f30d;python实现元旦倒计时 — 中级(精美动态图)⛅实现效果&#x1f30b;实现源码&#x1f31c;源码讲解 &#x1f30d;python实现元旦倒计时 — 高…

C++使用HTTP库和框架轻松发送HTTP请求

编程中使用 HTTP 库或框架发送 HTTP 请求 一、引言二、使用Curl库发送HTTP请求三、使用Boost.Beast库发送HTTP请求四、使用cpp-httplib库发送HTTP请求五、自己实现socket发送 HTTP 请求总结 一、引言 使用C编程发送HTTP请求通常需要使用第三方的HTTP库或框架。在C中&#xff0…

57 代码审计-JAVA项目框架类漏洞分析报告

目录 过滤器及拦截器相关区别解释Struts2-016远程代码执行漏洞分析-黑盒流程SpringBoot-SpEL表达式注入漏洞分析-白盒思路 过滤器及拦截器相关区别解释 Filter是基于函数回调的&#xff0c;而Interceptor则是基于Java反射的。 Filter依赖于Servlet容器&#xff0c;而Intercept…

gitattributes配置文件的作用

0 Preface/Foreword Git版本管控工具功能强大&#xff0c;在使用过程中&#xff0c;在多人合作的项目开发过程中&#xff0c;经常会遇到提交代码时出现的warning提醒&#xff0c;尤其是换行符。 Linux/Unix/Mac OS操作系统的换行符使用LF符号&#xff08;\n&#xff09;&…

Dash中 基本的 callback 5

app.callback 在Dash中&#xff0c;app.callback 被用于创建交互性应用程序&#xff0c;它用于定义一个回调函数&#xff0c;该函数在应用程序中发生特定事件时被触发。回调函数可以修改应用程序的布局或更新图表等内容&#xff0c;从而实现动态交互。 下面是一个简单的 app.…

LaTex详细安装及配置(Windows)

文章目录 引言LaTeX简介优势与应用领域 安装环境安装texlive下载texlive安装 编辑器安装texstudio下载texstudio安装 环境配置 使用第一个LaTex文档新建文件编程查看 效果 结语 引言 在当今信息技术高度发达的时代&#xff0c;文档的编辑和排版是我们日常工作和学习中不可或缺…