键值数据库的设计实现总结(SDS)

写这个数据库也已经有段时间了,在我心中此项目的第一个版本算是完成了,所以做一下小结,更多的功能以后再继续迭代即可!

1. 引言

1.1 编写目的

学习搭建rpc框架,自己阅读了部分redis实现源码,想实现一个加深印象,将学习的网络方面的知识学以致用。等等…

1.2 项目概述

客户端和服务器协议:Google Protocol buffer
RPC部分实现的功能:序列化和反序列化,发送远程命令
项目服务器使用Reactor模式设计的框架,为每一个连接设置了相应的读回调,写回调,每个连接套接字设置了EPOLLIN+非阻塞模式。实现了string和hash两种操作,并实现了save和bgsave两种持久化操作,bgsave操作通过创建新进程实现。项目中添加了最大堆定时器,为每个客户端设置了保活时间。当客户端产生一次活动时,会自动为该客户端延长时间,对于一些一直不活动的客户端,服务器会定时检查连接队列,并剔除闲置客户端。定时器通过统一事件源触发。
客户端实现比较简单,使用readline进行命令行输入,并设置了检测命令的合法模块,检测客户端是否与服务器建立了连接,要是没建立连接,会尝试和服务器建立5次连接。直到建立连接成功。

1.3 术语定义
术语名称术语含义
GPBGoogle Protocol Buffer
Server服务器
Client客户端
1.4 引用文档
名称作者
Redis设计与实现黄建宏
Redis深度探险钱文品
Google Protocol BufferGoogle Protocol Buffer
高性能服务器游双

2. 设计决策

2.1 设计目标
2.1.1 运行环境

LInux Ubuntu18.10

2.1.2 开发环境及工具

vim+vimplus+gcc 编译器

2.1.3 技术限制

书读的有点少

2.2 设计原则

严格遵守需求规格说明书设计,使用一些面向对象语言中的一些设计模式例如工厂模式,减少代码的复用性。

3. 逻辑架构设计

3.1 设计决策

Server设计领域模型如下:

在这里插入图片描述
client设计:

在这里插入图片描述

3.2 软件单元
  • server端
    直接看.cpp文件吧,类中的成员比较多,不好陈述,所以选择每个.cpp文件中的相关方法,将整个项目的功能实现加以描述。

aeEventloop.cpp
在这里插入图片描述
第一个就不说了,见名知意!
addServerEvent主要功能就是初始化时创建监听套接字,并设置好相应的回调函数。
addTimerEvent该方法创建一个eventfd并设置好相应的回调函数。
aeEventloop构造方法,创建了时间堆,创建了epoll检测引擎
下面是析构函数
aeProcessEvent该方法处理不同的事件,当aeEventloop将事件收集到vecotor中,该方法就会将其中的各种方法进行分类处理。
initDataInfo初始化时间堆中的相关数据
kickClient处理不活跃的客户端
notifyToSave 通知保存
setCallBack 设置回调函数
start 开始启动服务例程

aeEpoll.cpp

在这里插入图片描述
很简单的操作,可以看懂!

rpc.cpp

在这里插入图片描述
反序列化,发送响应请求。

aeEvent.cpp

在这里插入图片描述
读回调,和写回调函数。

timerHeap.cpp

在这里插入图片描述
MyTimer 时间堆上的节点,TimerManager是时间堆管理器。
detect_timers检测到期时间,若有超时客户端,就执行回调函数处理。
其它函数太鸡肋,不解释了。

cmdProcess.cpp

在这里插入图片描述
findCmd在进行发序列化之后,判查找命令是否存在。
initCmdCb初始化命令回调函数,每个命令对应一个回调函数。
initRedis 初始化数据库(就是从文件中将已经持久化的数据读出来)
processMsg处理不同的命令请求
sendMsg发送消息

cmdSet.cpp
在这里插入图片描述

addObjectToDb添加对象到数据库。
append增加数据库
countRedis获取当前数据库的数量
expend扩大容纳数据库容器的容量
findCmd 查找命令
getDB获取指定数据库对象
initCmdCb初始化命令集合
initRedis初始化数据库
redisCommandProc 数据库各种命令处理函数,根据命令的不同回调在命令集中找相应的回调函数
cb 数据库各种命令对象对应的回调函数

redisDb.cpp和redisDb.h
因为是键值数据库,所以对于大部分对象而言操作比较相似,所以利用C++多态机制实现了工厂模式,父类为抽象类dbObject,设置了许多虚方法,对于strings和hashSet都是继承了dbObject,redisDb通过hashmap管理dbObject,如图。键值为请求的key对象,key对象,成员是要访问对象的键值,类型,以及数据库编号三元组唯一确定对象在数据库中的值。

在这里插入图片描述
在这里插入图片描述

  • redisDb.cpp
    在这里插入图片描述
    getValue
    getValues hash获取值,将以vector对象的形式返回。

该数据库管理对象的模型如下:

在这里插入图片描述

  • redisDb.h

在这里插入图片描述

目前实现了两种类型的操作。
在这里插入图片描述
抽象基类。
在这里插入图片描述

在这里插入图片描述
hash操作,setValue实现多参数设置。
在这里插入图片描述
strings对象,内部数据。
在这里插入图片描述
equalFunc和hashFunc设置hash函数。
factory工厂根据不同提示,返回不同对象。

在这里插入图片描述
rdb.cpp
持久化功能
下面是两大对象在文件中的存储格式:

  • hash
    在这里插入图片描述
  • string

在这里插入图片描述

ctp存的是类型编号,数字编号之类,在初始化数据库的时候,都会通过正则表达式辨别。然后其他解析之类的函数就不作解释了!可以看源代码。

在这里插入图片描述
recoverDb.cpp

恢复数据库,因为我将每个数据库单独存在一个文件中,0号数据存在.db_0文件,后面以此类推,其中或有一个redis_fileName文件,存放的是数据库文件名,在恢复的时候,先读取.redis_fileName,将所有数据库文件名存在vector中,然后遍历vector再通过mmap映射将文件内容映射到string中,然后解析string就行。

在这里插入图片描述
在这里插入图片描述

客户端设计比较简单,读者可自行研究!

3.3 处理流程

在这里插入图片描述

4 运行演示

在这里插入图片描述
源代码 感谢star或者fork!本代码仅供阅读参考学习,在个人平台上运行的话可能得安装配置google protocol buffer!并且要考虑系统兼容性!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值