一 数据库基本实现/命令下发的实现

  redis.c里,大家能看到redisCommandTable[] 的实现,列出了支持的所有命令。大部分的入参为redisClient *c,当一条REDIS命令下发,调用流程如下

在createClient里会组装下传的client,其中就会调用selectDb()来选择数据库(redis所有的数据库都存在redisServer.db里),而数据库中存储了一个字典结构dict *dict,这个dict里的键就是执行REDIS命令的键,值即redis对象robj。

redisDb里的结构如下,下图已经是个抽象的图,比如HashObject,理论上应该有个redisObjct的结构,然后ptr指到一个dict的结构,然后才到一个个的entry等:

那么所有的对DB的读、新增、更新,都是现在redisDb.dict里找/新增 键值(对象的键值)(比如上图的book),然后更新dict里对应键的那个值(robj,比如HashObject)里的内容(比如name,author或者publisher):

二 键的生存/过期时间

如下,redisDb中的expires字典保存了数据库中键的过期时间,我们称之为过期字典。

typedef struct redisDb {
.......
// 键的过期时间,字典的键为键,字典的值为过期事件 UNIX 时间戳
// [JZ]:expires里键即上面的dict的键,即数据库的键,值为一个object
dict *expires; /* Timeout of keys with a timeout set */
}

过期时间可以增加/修改/移除,可用来计算剩余时间。

三 过期键的删除策略:

1.定时删除,即设置过期时间时,设置定时器,到时删除。 优点,节省内存,保证了尽快删除,但是耗CPU,而且实现定时器需要用到redis服务器里的时间事件,复杂度为o(N),不够高效

2.惰性删除,每次操作键时,判断是否过期,进行相应操作。优点是节省CPU,但是过期键可能长时间存在(如果键不被操作,就会一直存在,那么相当于内存泄露),因而消耗内存

3.定期删除,每隔一段时间进行键的扫描,过期删除。优点是改进了上面两种方法的缺点,一方面不会对CPU时间影响大,另一方面不会有内存的泄露和浪费。缺点是: 如果删除操作太频繁,或者执行时间太长,定期删除策略就会退化成定时删除,以至于CPU时间过多的耗费在删除过期键的操作上。 如果删除操作执行太少,或者执行时间太短,那么又会有内存浪费的情况(怎么优点缺点像是换个角度说同一件事情.......)

REDIS最终是是用惰性删除(expireIfNeeded())和定期删除(activeExpireCycle())结合的方式,实现了过期键的清理。

四 RDB文件

RDB文件即第一小节讲的DB的来源,redis.c里的main函数里,loadDataFromDisk()->rdbLoad()实现了DB文件的load功能,文件的名字来自于$REDIS_DEFAULT_RDB_FILENAME(AOF:$REDIS_DEFAULT_AOF_FILENAME)

    载入RDB文件时

1.如果服务器为master,那么会检查文件中的键的过期,已经过期的键就不会载入内存

2.额如果是slave,不检查键是否过期,全都载入。

复制: 当服务器运行在复制模式:

1.主服务器删除一个过期键,会向所有从服务器发送DEL命令

2.从服务器执行读命令时,即使碰到过期键也不删除,而是忽略过期,照常处理

3.只有从服务器收到主服务器的DEL时才删除过期键

通过由主服务器来控制删除过期键,保证主从的数据一致性,

当服务器以AOF持久化模式运行时,如果有某个键过期,且没有被惰性删除或者定期删除,那么AOF文件不会因为这个过期键而产生任何影响。

当过期键被删除,程序会想AOF文件追加一条DEL命令记录。

五 数据库通知

通过客户端的订阅,客户端可以得到键的被操作(键空间通知key-space notification)或者命令的执行(键事件通知key-event notification)的通知。

当服务器启动时,配置的 server.notify_keyspace_events决定了支持哪些通知,列表如下,如果配置为AKE,就是支持键空间通知和键事件通知

#define REDIS_NOTIFY_KEYSPACE (1<<0)    /* K */
#define REDIS_NOTIFY_KEYEVENT (1<<1) /* E */
#define REDIS_NOTIFY_GENERIC (1<<2) /* g */
#define REDIS_NOTIFY_STRING (1<<3) /* $ */
#define REDIS_NOTIFY_LIST (1<<4) /* l */
#define REDIS_NOTIFY_SET (1<<5) /* s */
#define REDIS_NOTIFY_HASH (1<<6) /* h */
#define REDIS_NOTIFY_ZSET (1<<7) /* z */
#define REDIS_NOTIFY_EXPIRED (1<<8) /* x */
#define REDIS_NOTIFY_EVICTED (1<<9) /* e */
#define REDIS_NOTIFY_ALL (REDIS_NOTIFY_GENERIC | REDIS_NOTIFY_STRING | REDIS_NOTIFY_LIST | REDIS_NOTIFY_SET | REDIS_NOTIFY_HASH | REDIS_NOTIFY_ZSET | REDIS_NOTIFY_EXPIRED | REDIS_NOTIFY_EVICTED) /* A */

1.键的操作通知的实现,在 void notifyKeyspaceEvent(int type, char *event, robj *key, int dbid);event是时间名称,keys是产生事件的键,以及产生时间的数据库号

    - 函数会先判断传入的第一个参数type是否包含在server.notify_keyspace_events,如果没有包含,就直接退出,不用通知。

    - 然后server.notify_keyspace_events定义了什么,就通知什么类型,比如REDIS_NOTIFY_KEYEVENT,先组建一个通知 __keyevent@dbid__:KEY(最终组成一个ROBJ结构),传给pubsubPublishMessage()发送

- pubsubPublishMessage()里,以上面的通知作为key,在字典server.pubsub_channels里查找到一个列表,这个列表存储了谁需要这种类型的通知,然后将通知加入REPLY列表进行发送。

      

[redis读书笔记] 第二部分 单机数据库 数据库实现的更多相关文章

  1. [redis读书笔记] 第二部分 单机数据库 RDB持久化

    内存中的rdb是会存为文件以做到RDB持久化的.RDB文件时一个二进制文件. 一 载入与存储 文件的载入是在server启动时进行的(rdbload()),因为AOF的更新频率比RDB高,所以如果AO ...

  2. [redis读书笔记] 第二部分 集群

    1. 一个集群会包含多个节点(一个节点就是一个reid是服务器),CLUST MEET <ip><port>可以添加一个node到集群,命令执行后,两个node之间就会进行握手 ...

  3. [redis读书笔记] 第二部分 sentinel

    1.sentinel的初始化,会制定master的IP和port,然后sentinel会创建向被监视主服务器的命令连接和订阅连接: -  命令连接是用来和主服务器之间进行命令通信的 - 订阅连接,用于 ...

  4. 《javascript权威指南》读书笔记——第二篇

    <javascript权威指南>读书笔记——第二篇 金刚 javascript js javascript权威指南 今天是今年的196天,分享今天的读书笔记. 第2章 词法结构 2.1 字 ...

  5. 【读书笔记】使用JMeter创建数据库(Mysql)测试

    读书笔记:<零成本实现Web性能测试>第4章 记得某天按照虫师博客的写的,折腾后成功了.今天又忘记了... 折腾后又成功了,赶紧记录下... 原文:http://www.cnblogs.c ...

  6. [redis读书笔记] 第一部分 数据结构与对象 简单动态字符串

    本读书笔记主要来自于<<redis设计与实现>> -- 黄键宏(huangz) redis主要设计了字符串,链表,字典,跳跃表,整数集合,压缩列表来做为基本的数据结构,实现键值 ...

  7. STL源码分析读书笔记--第二章--空间配置器(allocator)

    声明:侯捷先生的STL源码剖析第二章个人感觉讲得蛮乱的,而且跟第三章有关,建议看完第三章再看第二章,网上有人上传了一篇读书笔记,觉得这个读书笔记的内容和编排还不错,我的这篇总结基本就延续了该读书笔记的 ...

  8. Redis学习笔记二:单机数据库的实现

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

  9. [redis读书笔记] 第三部分 多机数据库的实现 复制

    另外一篇写的很好很深入的文章:http://www.tuicool.com/articles/fAnYFb : RDB持久化 http://www.tuicool.com/articles/F3Eri ...

随机推荐

  1. Java之Object类用法总结

    Object类概述: 1.Object类是所有Java类的根父类. 2.如果在类的声明中未使用extends关键字指明其父类, 则默认父类为java.lang.Object类. Object类主要结构 ...

  2. 键盘优雅弹出与ios光标乱飘解决方案

    前言 在移动开发中,会遇到这样的情况,比如说有一个输入框在最底部的时候,我们弹起输入框,输入框不会在输入键盘上. 说明白简单点就是,输入框被键盘挡住了.而且在原生中,输入框应该正好在输入键盘上,但是h ...

  3. 【UEFI】---关于BIOS,EIST和PState&CState和CPU主频变化得关系

    Intel处理器都支持Turbo和EIST,且一般情况下,各家厂商在BIOS中都会设置EIST和PState的开关,那么这些开关与CPU的频率的关系是什么呢?今天对此做个总结: 按照国际惯例,本次梳理 ...

  4. 利用Python进行博客图片压缩

    自己写博客的时候常常要插入一些手机拍的照片,都是几M的大小,每张手动压缩太费事了,于是根据自己博客的排版特点用Python写了一个简单的图片压缩脚本,功能是将博客图片生成缩略图,横屏的图片压缩为宽度最 ...

  5. 'NoneType' object has no attribute shape

    使用cv2读取图片时,输出图片形状大小时出现报错“ 'NoneType' object has no attribute shape”,后来排查发现读取图片的返回值image为None, 这就说明图片 ...

  6. Kotlin DSL for HTML实例解析

    Kotlin DSL for HTML实例解析 Kotlin DSL, 指用Kotlin写的Domain Specific Language. 本文通过解析官方的Kotlin DSL写html的例子, ...

  7. Docker基础内容之命令大全

    run(未补全) 说明:创建一个新的容器并运行一个命令 语法如下: docker run [OPTIONS] IMAGE [COMMAND] [ARG...] 选项说明: -a stdin: 指定标准 ...

  8. javaweb-codereview 学习记录-5

    1.关于URLConnection 应用程序利用url与远程通信的所有类的超类 jdk1.8中支持的协议包括以上这些,gopher在jdk8中取消了. java中默认对(http|https)做了一些 ...

  9. 虚拟机 ubuntu系统忘记密码如何进入

    重启 虚拟机 按住shift键 会出现下面的界面 按住‘e’进入下面的界面往下翻 更改红框勾到的字符串为:  rw init=/bin/bash 然后按F10进行引导 然后输入 :”passwd”  ...

  10. Intent传递实现Parcelable接口的对象

    Intent可以传递基本数据类型,在对象实现了Parcelable接口后,Intent也可以传递对象. 1. 使类ListVideo实现了Parcelable接口. package com.examp ...