Redis设计与实现阅读总结(二)单机数据库
书的重点内容逐渐到了,我们的写作方式也该换一下了,不会像(一)一样流水账式了的解释几种数据结构了

在第一篇文章中,我简略的解释下有关的数据结构,现在我们开始想想如何实现

先提几个问题

如何实现多数据库
redis数据是存在内存中的,但是这样数据存在丢失的风险,那我们怎样化解决这个问题
redis服务器和多个客户端的交互是怎样实现的呢

在我看来,该书第二部分<单机数据库的实现>就是围绕上面的几个问题,来用列举式行文写下相应部分知识点的。

服务器中的多数据库

看到这个多字,其实我们很容易就想到用链表的方式去储存

一个服务器,先假设是一个简单的struct结构来维护的,我们想在其中实现多数据库,自然想到,在其中添加一个键值对,而这个值我们使用一个链表

这个链表中存放一个又一个的指针,每个指针指向一个struct结构(维护着数据库结构的struct)

好,这样,我们就简单的实现这个多。

然后我们再去实现单数据库

服务器中的多数据库

每个数据库中那有该如何存放数据呢

由于redis是kv数据库,数据都是以kv形式存在的,那我们完全就可以用字典去实现

键值对中的值可以是(一)中的多种形式,那么,

下图的形式就能得出了

到了这里后,书上将过期问题在后续进行了说明。

过期问题

书籍主要是解释了 列举式解释了相关命令

我觉得比较重要是redis的过期键删除策略

一个经典的问题是:如果一个键过期了,那么它什么时候会被删除呢?

这个问题有三种可能的答案,它们分别代表了三种不同的删除策略:

定时删除:在设置键的过期时间的同时,创建一个定时器(timer),让定时器在键的过期时间来临时,立即执行对键的删除操作。
优点:对内存是最友好的:通过使用定时器,定时删除策略可以保证过期键会尽可能快地被删除,并释放过期键所占用的内存。
缺点:它对CPU时间是最不友好的:在过期键比较多的情况下,删除过期键这一行为可能会占用相当一部分CPU时间 | 创建一个定时器需要用到Redis服务器中的时间事件,而当前时间事件的实现方式——无序链表,查找一个事件的时间复杂度为O(N)
惰性删除:放任键过期不管,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键;如果没有过期,就返回该键。
对CPU时间来说是最友好的。 这个策略不会在删除其他无关的过期键上花费任何CPU时间
它对内存是最不友好的:如果一个键已经过期,而这个键又仍然保留在数据库中,那么只要这个过期键不被删除,它所占用的内存就不会释放
定期删除:每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键。至于要删除多少过期键,以及要检查多少个数据库,则由算法决定
定期删除策略是前两种策略的一种整合和折中
定期删除策略的难点是确定删除操作执行的时长和频率。

上面大概性的介绍了数据库的存储实现,但是现在数据仍然保持在内存中的,但是这样数据存在丢失的风险,这个时候我们应该设计持久化的策略了。

Redis的持久化

Redis 分别提供了 RDB 和 AOF 两种持久化机制:

RDB 将数据库的快照(snapshot)以二进制的方式保存到磁盘中。

AOF 则以协议文本的方式,将所有对数据库进行过写入的命令(及其参数)记录到 AOF 文件,以此达到记录数据库状态的目的

我们继续想第三个问题,客户端和服务器是如何交互的?

Redis客户端和服务器的交互

关于这一点,书上用了三个章节来讲解。

分别是 服务器事件,客户端,服务器

Redis的事件处理器是单线程的,但并不意味着Redis就是单线程的!

I/O多路服用程序

Redis的事件处理机制是I/O多路复用的。多个文件事件可能并发的出现,但是I/O多路复用程序会将所有的产生的套接字放到一个队列里。

以有序,同步的方式,I/O多路复用程序向文件事件分派器传送套接字,当一个套接字处理完,才会传送下一个。

I/O多路复用程序底层有多种实现可以选择,epoll,select,evport,kqueue.

文件事件处理器

连接应答处理器
为了对连接服务器的客户端进行应答,服务器为套接字连接进行应答的处理器
命令处理器
命令回复处理器

后面主要就是 服务器和客户端的通信协议部分,这部分我不准备讲解,也不是什么特别重要和难点的部分,就略过了

06-22 08:45