Redis 数据库

  经过上篇文章,介绍了 Redis 中的对象,Redis 是通过这些对象来保存 Redis 数据库中的数据的。这篇我们就看一下Redis数据库在内存中的结构,以及客户端切换数据库、数据库保存键值对、以及对数据的增删改查等操作的实现方法。

我们本地安装 Redis 会安装redis-cli 和 redis-server两个部分,相当于一个Redis的客户端和服务端。我们通常通过redis-cli来连接redis-server,数据都是存放在redis-server的数据库中,我们来看一下服务器中redis-server和Redis数据库结构。

redis-server

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

struct redisServer {
    // ...
    // 一个数组,保存着服务器中所有数据库
    redisDb *db;
    // 服务器中数据库数量
    int dbnum;
};

dbnum 属性由配置项 database 决定。默认情况下为16。

切换数据库

每个redis-cli都有自己目标数据库,当客户端执行数据库读或者写命令时,目标数据库将成为命令的操作对象。

默认情况下,redis-cli都会连接第0个数据库,客户端可以通过 SELECT 命令切换数据库。如下例子:

尝试用redis-cli 连接本地redis-server:

 访问被拒绝了,是因为我们没在本地启动redis-server。我们启动并连接本地redis-server:

 (上述例子是在macOS系统中,Windows和Linux系统都是大同小异,网上都可以找到解决方案。)

我们连接本地redis-server,并做一些操作:

可以看到,我们现在数据库0设置language,再切换为数据库15设置language,保存了两个key,说明redis-server中每个数据库是独立的。

但是切换数据库是怎么做到的呢?我们来看一下redis-cli的结构

typedef struct redisClient {

    // ...
    // 记录当前客户端正在使用的数据库
    // redisDb *db
    // ...
} redisClient;

redisClient.db 指针指向redisServer.db数组中的其中一个元素,代表正在连接那个被客户端指向的数据库,如下图例子:

 通过修改redisClient.db指针,指向redisServer中不同的数据库,实现切换数据库的功能,这就是 SELECT 命令的实现原理。

数据库键空间

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

typedef struct redisDb {
    
   // ...
  // 数据库键空间,保存着数据库中所有键值对
// dict *dict // ... } redisDb;

键空间的键就是数据库的键,每一个键都是一个字符串对象。

键空间的值近视数据库的值,每一个值可以是字符串对象、列表对象、哈希对象、集合对象和有续集合对象中的任意一个。

举个例子,我们对数据库执行如下命令:

那么数据库键值对在内存中的结构如下图所示:

 因为数据库键空间就是一个字典,所有对Redis数据库的增删改查,相当于对键空间(字典)的增删改查。

 参考文献

Redis设计与实现第二版

 
原文地址:https://www.cnblogs.com/hulunbao/p/14105967.html