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

  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字典保存了数据库中键的过期时间,我们称之为过期字典。

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

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

三 过期键的删除策略:

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,就是支持键空间通知和键事件通知

  1. #define REDIS_NOTIFY_KEYSPACE (1<<0) /* K */
  2. #define REDIS_NOTIFY_KEYEVENT (1<<1) /* E */
  3. #define REDIS_NOTIFY_GENERIC (1<<2) /* g */
  4. #define REDIS_NOTIFY_STRING (1<<3) /* $ */
  5. #define REDIS_NOTIFY_LIST (1<<4) /* l */
  6. #define REDIS_NOTIFY_SET (1<<5) /* s */
  7. #define REDIS_NOTIFY_HASH (1<<6) /* h */
  8. #define REDIS_NOTIFY_ZSET (1<<7) /* z */
  9. #define REDIS_NOTIFY_EXPIRED (1<<8) /* x */
  10. #define REDIS_NOTIFY_EVICTED (1<<9) /* e */
  11. #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. 自定义实现的ArrayList以及自定义实现的Iterator迭代器

    ArrayList的底层是长度可动态变化的数组,其适用于查找多,修改少的情况,原因是数组的元素的增加删除元素会涉及大量元素的移动,效率比较低,ArrayList中的元素可以重复,与插入时的顺序相同,可 ...

  2. Appium自动化测试框架研究(2)——搭建IOS环境

    今天的文章讲iOS的Appium环境搭建. 对于iOS而言,只能在Mac笔记本上安装Appium,以及所需要的各种组件. 也许有人会问,能否在Windows系统上使用Appium测试iOS手机,这不就 ...

  3. scope为provided

    以下面dependency为例 1 <dependency> 2 <groupId>javax.servlet</groupId> 3 <artifactId ...

  4. ChoiceFiled MultipleChoiceField ModelChoiceField ModelMultipleChoiceField

    1.ChoiceFiled 单选 字段 2.MultipleChoiceField 多选 3.ModelChoiceField 单选 query_set 4.ModelMultipleChoiceFi ...

  5. C语言—期末小黄衫获奖感言

    小黄衫获奖感言 一,感谢环节 非常感谢邹欣,周筠老师给提供的小黄衫,我非常荣幸的能够获得这个奖项,我感到无比自豪.感谢两位老师对教学事业的大力支持,对我们学生的亲切关怀.同时感谢我的C语言老师彭琛(琛 ...

  6. HTML中CSS引用——选择器的使用

    一.元素选择器     1.书写格式:标记名{/*生命块*/}     2.所有与该标记匹配的元素,都将应用声明块中的规则 二.类选择器     1.书写格式:.类名{/*声明块*/}         ...

  7. CSS-14-浮动

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. ReactNative---android系统中Image组件无默认图片问题

    react native的Image组件通过网络地址加载图片的时候,若加载失败iOS有默认图片等属性,但安卓没有:但可以通过其他方式来实现: {Platform.OS == 'android'?< ...

  9. 连接redis出现错误:Cannot get Jedis connection

    错误信息: 错误描述:由于我的redis数据库没有设置密码,配置连接的时候我配置了密码为空,导致连接失败

  10. Mybatis基础(二)

    Mybatis连接池 Mybatis连接池提供了三种配置方式,配置的位置在SqlMapConfig.xml的dataSource标签中,其type属性就是配置连接池的种类.type的可取值 1.POO ...