前言
参考资料:《Redis设计与实现 第二版》;
第二部分为单机数据库的实现,主要由以下模块组成:数据库、持久化、事件、客户端与服务器;
本篇将介绍 Redis 中的数据库;
1. Redis中的数据库
Redis服务器的所有数据库保存在
redis.h/redisService
结构的db数组中:struct redisService{
//...
//保存所有数据库的数组
redisDB *db; //服务器的数据库数量
int dbnum;
//...
}
dbnum
属性由服务器配置的 database 选项决定,默认为 16;
Redis客户端数据库保存在在
redisClient
结构的db
属性:typedef struct redisClient{
//...
//记录客户端当前正在使用的数据库
redisDB *db;
} redisClient;
- 客户端通过修改目标数据库指针,让它指向 redisService.db 数组中的不同元素;
- 可以通过 SELECT index 命令来切换数据库;
数据库的定义在
redis.h/redisDb
结构中:typedef struct redisDb{
//...
//数据库键空间,保存数据库中所有的键值对
dict *dict; //过期字典,保存着键的过期时间
dict *expires;
} redisDb;
- 键空间的键是数据库的键,每个键是一个字符串对象;
- 键空间的值是数据库的值,每个值可以是字符串对象、列表对象、哈希表对象、集合对象和有序集合对象中的一种;
2. 数据库的键空间
- 数据库键空间是一个字典,所有针对数据库的操作都是通过键空间字典来操作的;
- 在对键空间进行读写操作时,Redis 还会进行一些维护操作:
- 读取键后,会根据键是否存在更新服务器的键空间命中 keyspace_hits 次数或键空间不命中 keyspace_misses 次数。通过 INFO stats 命令查看属性;
- 读取键后,服务器会更新键的 LRU(最后一次使用时间)。通过 ONBJECT idlettime [key] 命令查看key的闲置时间;
- 服务器在读取键时发现键已经过期,会先删除这个过期键;
- 如果有客户端使用 WATCH 命令监视某个键,服务器对该键修改后会标记上脏
dirty
,让事务处理程序注意; - 服务器每修改一个键后,会对脏
dirty
键计数器值增 1,计数器会触发服务器的持久化以及复制操作;
3. 键的生成时间与过期时间
- 键的时间相关设置命令参看《Redis常用命令及示例总结》1.3 生存时间的功能;
- 生存时间:
- 客户端可以通过 EXPIRE 或 PEXPIRE 命令以秒或毫秒精度为数据库中某个键设置生存时间(Time To Live,TTL)。经过指定时间后,服务器自动删除生存时间为0的键;
- 可以通过 SETEX 命令在设置字符串键同时设置过期时间;
- 使用 TTL 或 PTTL 命令获取键的剩余生存时间;
- 过期时间:
- 客户端设置过期时间的命令是 EXPIREAT 或 PEXPIREAT;
- 过期时间是一个 UNIX 时间戳;
- EXPIRE、PEXPIRE 和 EXPIREAT 三个命令都会转换成 PEXPIREAT 命令实现;
4. Redis中的过期键删除策略
有三种删除过期键的策略:
- 定时删除:主动策略。对内存最友好,到期就释放内存。缺点是对CPU事件不友好,当过期键比较多时,会占用一部分CPU时间;
- 惰性删除:被动策略。对CPU时间最友好。每次从键空间获取键时,检查取得的键是否过期,过期则删除。缺点是对内存不友好;
- 定期删除:主动策略。前两种策略的整合与折中。每隔一段时间执行一次删除过期键操作,并通过限制删除操作执行的时长与频率减少删除操作对CPU时间的影响。缺点是难以确定删除操作执行的时长和频率;
惰性删除策略由
db.c/expireIfNeeded
函数实现,流程如下:
- 定期删除策略由
redis.c/activeExpireCycle
函数实现,每当Redis的服务器周期性操作redis.c/serverCron
函数执行时,activeExpireCycle 函数会被调用。在规定的时间内,分多次遍历服务器各个数据库,从数据库的expires
字典中随机检查一部分过期时间,删除其中过期键;
5. AOF、RDB和复制功能对过期键的处理
5.1 生成 RDB 文件
- 在执行 SAVE 或 BGSAVE 命令创建一个新的 RBG 文件时,程序会对数据库中的键进行检查,已过期的键不会被保存到新创建的 RDB 文件中;
5.2 载入 RDB 文件
- 载入 RDB 文件时:
- 若服务器以主服务器模式运行,过期键不载入;
- 若服务器以从服务器模式运行,所有键都会载入;
5.3 AOF 文件写入
- 当服务器以 AOF 持久化模式运行时,未被惰性删除和定期删除的过期键不会对 AOF 文件产生影响;
- 当过期键被惰性删除或定期删除后,程序会向 AOF 文件追加(append)一条 DEL 命令,显示记录该键已被删除;
5.4 AOF 重写
- 与 RDB 文件类似,在执行 AOF 重写过程中,程序会对数据库中的键进行检查,已过期的键不会被保存到重写后的 AOF 文件中;
5.5 复制
- 当服务器运行在复制模式下时,从服务器的过期键删除动作由主服务器控制;
6. 数据库通知
- 数据库通知是 Redis 2.8 版本新增的功能;
- 数据库通知可以让客户端通过订阅给定的频道或模式,来获知数据库中键的变化,以及数据库中命令的执行情况;
- Redis 命令对数据库进行修改后,服务器会根据配置向客户端发送数据库通知;
- 通知的相关命令可以参考 《Redis常用命令及示例总结》7. Pub/Sub(发布/订阅);
- 两类通知类型:
- 键空间通知 key-space notification:关注 “某个键执行了什么命令”;SUBSCRIBE channel:message;
- 键事件通知 key-event notification:关注 “某个命令被什么键执行了”;SUBSCRIBE channel:del;
- 服务器配置的
notify-keyspace-events
选项决定服务器所发送通知的类型:- AKE:发送所有类型的键空间和键事件通知;
- AK:发送所有类型的键空间通知;
- AE:发送所有类型的键事件通知;
- K$:只发送字符串有关的键空间通知;
- EL:只发送列表键有关的键事件通知;
- 发送数据库通知的功能是由
notify.c/notifyKeyspaceEvent
函数实现;
最后
新人制作,如有错误,欢迎指出,感激不尽!
欢迎关注公众号,会分享一些更日常的东西!
如需转载,请标注出处!
Redis | 第4章 Redis中的数据库《Redis设计与实现》的更多相关文章
- 我的Android六章:Android中SQLite数据库操作
今天学习的内容是Android中的SQLite数据库操作,在讲解这个内容之前小编在前面有一篇博客也是讲解了SQLite数据库的操作,而那篇博客的讲解是讲述了 如何在Window中通过DOM来操作数据库 ...
- Redis 数据恢复方法,redis-port 工具将自建 redis 的 rdb文件同步到云数据库
1. Redis 恢复的机制 如果只配置 AOF ,重启时加载 AOF 文件恢复数据: 如果同时配置了 RDB 和 AOF ,启动是只加载 AOF 文件恢复数据: 如果只配置 RDB,启动是将加载 d ...
- Redis Installation、Configuration、Program Based On Redis Learning
目录 . Redis 简介 . Redis安装配置 . 编程使用Redis . 使用Lua脚本 1. Redis 简介 0x1: Redis是什么 Redis是一款Nosql类型的基于key-valu ...
- Android中SQLite数据库小计
2016-03-16 Android数据库支持 本文节选并翻译<Enterprise Android - Programing Android Database Applications for ...
- PHP中的数据库三、redis
h2:first-child, body>h1:first-child, body>h1:first-child+h2, body>h3:first-child, body>h ...
- [转]Node.js中koa使用redis数据库
本文转自:https://blog.csdn.net/offbye/article/details/52452322 Redis是一个常用的Nosql数据库,一般用来代替Memcached做缓存服务, ...
- Redis中单机数据库的实现
1. 内存操作层 zmalloc 系接口 redis为了优化内存操作, 封装了一层内存操作接口. 默认情况下, 其底层实现就是最简朴的libc中的malloc系列接口. 如果有定制化需求, 可以通过配 ...
- 【Spring Boot&&Spring Cloud系列】Spring Boot中使用NoSql数据库Redis
github地址:https://github.com/AndyFlower/Spring-Boot-Learn/tree/master/spring-boot-nosql-redis 一.加入依赖到 ...
- Redis 中的数据库
前面我们花了很多的时间介绍了 redis 中基本的数据结构,及其内部的实现情况,这些都是非常基础的东西,可能不经意间你就会用到他们,希望你花点时间了解一下. 接下来,我们将走近 redis 数据库,学 ...
- NoSql数据库Redis系列(4)——Redis数据持久化(AOF)
上一篇文章我们介绍了Redis的RDB持久化,RDB 持久化存在一个缺点是一定时间内做一次备份,如果redis意外down掉的话,就会丢失最后一次快照后的所有修改(数据有丢失).对于数据完整性要求很严 ...
随机推荐
- 那些年用过的xUnit.net的简单用法
0x01 前言 单元测试,总是伴随着我们的开发过程,优劣自行google.当然呢,不排除有些公司是不做单元测试的, 但是呢,学多一点东西用来防身还是可以的. 0x02 简单的Demo 写个两数求和的方 ...
- iOS设计模式之命令模式
命令模式 基本理解 命令模式(Command),将一个请求封装为一个对象,从而使你可用不同的请求对客户端进行参数化:对请求队列或记录请求日志,以及支持客可撤离的操作. 苹果的Target-Action ...
- ios app名字的多语言支持
经测试,不同版本的xcode会有操作细节不同,本次环境xcode6.4 1)编辑Info.plist,添加一个新的属性Application has localized display name, 设 ...
- BZOJ 2754: [SCOI2012]喵星球上的点名
2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 649 Solved: 305[Submit][Sta ...
- 分析内存使用情况 (JavaScript)
[此文档是初定版,随时可能进行更改.] JavaScript 内存分析器在 Visual Studio 2012 更新 1 和 Visual Studio 2013 中提供,旨在帮助你了解内存使用量和 ...
- uva 408 Uniform Generator
Uniform Generator Computer simulations often require random numbers. One way to generate pseudo-ran ...
- index.do为后缀的是什么开发语言? 有什么技术特点?
@Override 重写父类的方法[email protected] 表示定义的字段可以为空. 一般情况下扩展名可以体现出一个网站使用的技术,***.html?id=***,这个就是普通的html页面,然后通过ja ...
- 学Java的前景与就业,资深程序员教你怎么开始学Java!
IT行业一直是就业的热门岗位,程序员这个职业稳定性和收入比都有着不错的前景,那么学Java的前景和就业是什么样的呢?随着入行Java的准程序员越来越多,各种学习Java的流派也层出不穷!其实在编程的世 ...
- 【Android源码解析】View.post()到底干了啥
emmm,大伙都知道,子线程是不能进行 UI 操作的,或者很多场景下,一些操作需要延迟执行,这些都可以通过 Handler 来解决.但说实话,实在是太懒了,总感觉写 Handler 太麻烦了,一不小心 ...
- u-boot移植(九)---代码修改---NAND
一.NAND原理 NAND 无地址空间,地址和数据的发送都依赖于LDATA[0:7]这一串数据总线. 不看随机页编程,看到从高位到低位的页,总共分为64个页面,每个页的组成是2K + 64 个byt ...