[Redis 源码解析 1:数据库 redisDb] 服务器中的数据库 Redis 服务器将绝大部分的信息都保存在 server.h/redisServer。 redisDb *db; // 数据库列表 // ... int dbnum; // 数据库数量 // ... } db 中每个redisDb结构代表一个数据库。 ,服务器中的每个数据库都由一个 server.h/redisDb 结构表示. [redisDB数据结构](/Users/mjduan/Documents/markdown/图片/篇章1 redisDB/redisDB数据结构.png) 从上面的示例图可以很清晰地知道 Redis [redisDB的key过期时间](/Users/mjduan/Documents/markdown/图片/篇章1 redisDB/redisDB的key过期时间.png) 2.
3.1、redisDb redis默认支持16个Db,但只会使用一种Db。可以通过select来选择使用哪种Db,默认是 select 0。 127.0.0.1:6379> select 0 OK 127.0.0.1:6379> select 1 OK 127.0.0.1:6379[1]> 源码中redisDb的定义(server.h): The database number is the 'id' field in the structure. */ typedef struct redisDb { dict *dict; list *defrag_later; /* List of key names to attempt to defrag one by one, gradually. */ } redisDb ; redisDb里面有散列表,散列表有很多的key-value,不同的value可能会是不同的类型。
. // 数据库数组,保存着服务器中所有的数据库 redisDb *db; //.. } 在初始化服务器时,程序会根据服务器状态的dbnum属性来决定应该创建多少个数据库: struct 结构(redis.h/redisDb)的指针: typedef struct redisClient { //.. // 客户端当前正在使用的数据库 redisDb *db; */ void setKey(redisDb *db, robj *key, robj *val); /* 判断指定键是否存在 */ int dbExists(redisDb *db, robj *key ); /* 随机返回数据库中的键 */ robj *dbRandomKey(redisDb *db); /* 删除指定键 */ int dbDelete(redisDb *db, robj *key); 四、数据库的过期键操作 在前面我们说到,redisDb结构中有一个expires指针(概况图可以看上图),该指针指向一个字典结构,字典中保存了所有键的过期时间,该字典称为过期字典。
.StringDecrementAsync("ProfileUsageCap", (double)1) // 对应redis api:HGET KEY field1 _redisDB0.HashGetAsync var redisDB = new CSRedisClient[16]; // 多客户端 for (var a = 0; a < redisDB.Length ; a++) redisDB[a] = new CSRedisClient(Configuration.GetConnectionString("redis") + ",defaultDatabase =" + a); services.AddSingleton(redisDB); // ---------------------------- _redisDB[0].IncrByAsync("ProfileUsageCap ", -1) _redisDB[0].HGetAsync(profileUsage, eqidPair.ProfileId.ToString()) _redisDB[0].HIncrByAsync(profileUsage
redis数据库结构介绍 在redis源码中数据库的结构由server.h/redisDb表示, redisDb结构的dict字典保存了数据库中的所有键值对,我们将这个字典称为键空间(key space ),redisDb源码: typedef struct redisDb { dict *dict; /* The keyspace for this DB */ ; 源码中redisDb拥有字典属性dict,字典中存储了数据库中的键,为字符串类型的redisObject。 redisDb结构体中有一个字典属性expires便是用来保存键的过期时间的, 我们称这个字典为过期字典。 如果客户端发来一个repush key value命令,先从redisDb的blocking_keys中查找是否存在对应的key,如果存在就往redisDb的ready_keys这个链表中添加该key;
一、redis 中的数据库 server.h/redisServer 结构中有一个字段,db 字段: redisDb *db; db 被定义成一个 redisDb 数组,其中 redisDb 的定义如下 : typedef struct redisDb { dict *dict; dict *expires; dict ; 我们经常说 redis 具有十六个数据库,可以切换不通的数据库做数据隔离,这里你就可以将一个 redisDb 实例理解为一个数据库,而 db 指针则可以访问 redis 预定义的所有数据库。 因为 redisDb 底层是字典结构,键不允许重复,故而 set 命令同样适用于更新操作。 3、del 命令 del 命令用于删除数据库中一个键值对,标准语法如下: del [KEY] 例如: ? 以上就是 redis 中过期键相关的命令,之前也说过,redisDb 数据结构中有一个 expires 字典,它存储的就是库中所有过期键以及他们生存截止时间。
{ var requestId = _correlationContext.CorrelationContext.CorrelationId; var redisDB = _redisMultiplexer.GetDatabase(CommonConst.DEFAULT_DB); var index = redisDB.SortedSetRank ); var keyIndex = redisDB.SortedSetRank(CommonConst.REQUESTS_SORT_SETKEY, requestId); var response = redisDB.StringGet(requestId); if (response.IsNull) { { _logger.LogInformation("Process start,message: " + message); var redisDB
结构,每个redisDb代表一个数据库。 在服务器内部,客户端状态结构redisClient的db属性,记录客户端当前目标的数据库,该属性是指向redisServer的db数组中的某个具体redisDb结构的指针。 typedef structredisClient{ redisDb *db; }redisClient; 如下图所示: ? 三、数据库键空间 redis是存储键值对的数据库服务器,每个数据库都是一个redisDb结构,其中用dict字典来保存每个键值对。 typedef structredisDb{ dict *dict; }redisDb; dict存储数据库中的所有键值对,也成为键空间。
//保存 db 的数组 redisDb *db; //db 的数量 int dbnum; ... } 再看redisDb的代码: typedef struct ; 总体来说redis的 server 包含若干个(默认16个) redisDb 数据库。 在 redisDb 中使用了 dict *expires,来存储过期时间的。 遍历所有的 redisDb 在每个 redisDb 中如果数据中没有过期键或者过期键比例过低就直接进入下一个 redisDb。 否则,遍历 redisDb 中的过期键,如果删除的键达到有过期时间的的key 的25% ,或者操作时间大于 cpu 时间的 25% 就结束当前循环,进入下一个redisDb。
过期字典是存储在redisDb这个结构里的: typedef struct redisDb { ... dict *dict; //数据库键空间,保存着数据库中所有键值对 dict *expires // 过期字典,保存着键的过期时间 ... } redisDb;
) w.WriteHeader(http.StatusOK) }) server.ListenAndServe() } func processRequest(redisdb *redis.Client ) { // 在这里模拟一些业务逻辑 time.Sleep(time.Second * 5) redisdb.Incr("counter") } 当我们使用此代码运行验证过程时,我们会看到一些请求失败 ) { ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGTERM) defer stop() // redisdb () os.Exit(0) } func processRequest(redisdb *redis.Client) { defer wg.Done() // simulate some 资源清理:添加了 redisdb.Close() 在退出之前正确关闭 Redis 连接。 清洁退出:使用 os.Exit(0) 表示成功终止。
Redis 的键管理 一、Redis 数据库管理# Redis 是一个键值对(key-value pair)的数据库服务器,其数据保存在 src/server.h/redisDb 中(网上很多帖子说在 redisDb 结构应该在 server.h文件中) typedef redisServer { .... // Redis数据库 redisDb *db; 二、Redis 数据库键# 2.1 数据库键空间# Redis 服务器中的每一个数据库是由一个 server.h/redisDb 结构来表示的,其具体结构如下: typedef struct redisDb # 当前系统时间 redis> TIME 1)"1377257296" # 过一段时间后,再查询key redis> GET key // 1377257300 (nil) 2.2.1 过期时间# redisDb server.lua_time_start : mstime(); return now > when; } // 获取键的过期时间 long long getExpire(redisDb
redis如何新增一个kv redis的键值都是redisObject对象,在创建时会生成redisDb中一个键名和一个键值的redisObject对象。 其中redisDb对象构成了redis的键空间。 键空间 redis是一个键值对(key-value pair)数据库服务器,服务器中的每个数据库都由一个redisDb结构表示,redisDb结构中dict字典保存了数据库中的所有键值对,我们将这个字典称为键空间 typedef struct redisDb { // 保存着数据库以整数表示的号码 int id; // 保存着数据库中的所有键值对数据 // 这个属性也被称为键空间( BLPOP dict *blocking_keys; dict *ready_keys; // 用于实现 WATCH 命令 dict *watched_keys; } redisDb
. */ pthread_t main_thread_id; /* 主线程 id */ char *configfile; /*redis.conf 文件绝对路径*/ redisDb *db; /* 存储键值对数据的 redisDb 实例 */ int dbnum; /* DB 个数 */ dict *commands; /* 当前实例能处理的命令表,key 是命令名 *db指针非常重要,它指向了一个长度为 dbnum(默认 16)的 redisDb 数组,它是整个存储的核心,我就是用这玩意来存储键值对。 redisDb redisDb 结构体定义如下。 如图 1-11 是由 redisDb、dict、dictEntry、redisObejct 关系图: 图1-11 图 1-11 注意,一开始的时候,我只使用 ht_table[0] 这个散列表读写数据
// 创建 redis 客户端 func GetRedisClient() *Client { redisdb := NewClient(&Options{ Addr: = nil { fmt.Println(pong, err) } return redisdb } 通过 cient.Ping() 来检查是否成功连接到了 redis 服务器 func GetRedisClientPool() *Client{ redisdb := NewClient(&Options{ Addr: "127.0.0.1:6379", Password: "", DB: 0, PoolSize: 5,}) pong, err := redisdb.Ping().Result( 0, PoolSize: 5,}) pong, err := redisdb.Ping().Result() if err !
{ t.Cleanup(m.Close) func NewMiniRedis() *Miniredis { m := Miniredis{ dbs: map[int]*RedisDB }, subscribers: map[*Subscriber]struct{}{}, } m.signal = sync.NewCond(&m) 核心结构体定义如下: type RedisDB func (m *Miniredis) db(i int) *RedisDB { if db, ok := m.dbs[i]; ok { return db } db := newRedisDB [i] = &db return &db } github.com/alicebob/miniredis/v2@v2.30.2/direct.go先定位到db然后设置值: func (db *RedisDB "hll": delete(db.hllKeys, k) default: panic("Unknown key type: " + t) } func (db *RedisDB
RedisDB的设计结构如下所示:typedef struct redisDb { dict *dict; dict *expires; dict *blocking_keys id; long long avg_ttl; unsigned long expires_cursor; list *defrag_later; } redisDb */void dbAdd(redisDb *db, robj *key, robj *val) { sds copy = sdsdup(key->ptr); int retval = dictAdd
示例代码: // 定义一个全局的redisdb变量 var redisdb *redis.Client // 初始化连接 func initClient() (err error) { redisdb localhost:6379", Password: "", // no password set DB: 0, // use default DB }) _, err = redisdb.Ping = nil { return err } return nil } 全局变量 redisdb 是 redis.Client 类型的指针,用来保存到 Redis 客户端的引用。 它将一个新的 Redis 客户端分配给 redisdb 变量。如果连接成功,它就会 ping Redis 服务器以测试连接。 示例代码: // 向队列中添加任务 func addTaskToQueue(task string, executeTime int64) { err := redisdb.ZAdd("delay-queue
一、服务器中的数据库 Redis服务器将所有数据库都保存在服务器状态redis.h/redisServer结构的db数组中,db数组的每个项都是一个redis.h/redisDb结构,每个redisDb 结构代表一个数据库: struct redisServer { // ... redisDb *db; // 一个数组,保存着服务器中的所有数据库 // ... }; 数据库数量(dbnum属性、 在服务器内部,客户端状态redisClient结构的db属性记录了客户端当前的目标数据库,这个属性是一个指向redisDb结构的指针: typedef struct redisClient { // . .. redisDb *db;//记录客户端当前正在使用的数据库 // ... } redisClient; redisClient.db指针指向redisServer.db数组的其中一个元素,而被指向的元素就是客户端的目标数据库
集群模式:RedisDB 也支持 Redis 集群模式,这是一种用于分布式存储的 Redis 配置,可以将数据分布在多个 Redis 节点上,从而实现水平扩展和高可用性。 RedisDB:https://feapder.com/#/source_code/RedisDB基本使用方法如下:import feapderfrom feapder.db.mysqldb import MysqlDBfrom feapder.db.redisdb import RedisDBclass AirSpiderTest(feapder.AirSpider): __custom_setting ="localhost:6379", REDISDB_USER_PASS="", REDISDB_DB=0 ) def start_requests(self): yield 若为集群或哨兵模式,多个连接地址用逗号分开,若为哨兵模式,需要加个 REDISDB_SERVICE_NAME 参数;REDISDB_USER_PASS: Redis 服务器的连接密码;REDISDB_DB