如何设计一个简单的KV数据库
下面的内容仅供设计一个简单的KV数据库。如果想要实现一个功能更强的KV数据库的话,还需要考虑:更加丰富的数据类型、数据压缩、过期机制、数据淘汰策略、集群化、高可用等功能,另外还可以增加统计模块、通知模块、调试模块、元数据查询等辅助功能。
数据模型
对于KV数据库而言,其基本的数据模型是KV模型,K一般是String类型,V可以是多种类型,比如String、Hash、List等等。像Memcached的V只能是String类型,Redis的V支持String、Hash、List、Set等。一般来说,支持的V类型越多,他的应用场景就越广泛。
操作接口
对于KV数据库而言,PUT、GET、DELETE、SCAN
是他的基本操作集合。如果我们的业务还要求KV数据库具备更多的功能,那么我们还可以在此基础上增加新的操作接口。比如一个比较高频的需求是根据用户id判断用户是否存在,那么我们可以在增加一个EXIST
操作接口。
当然,当一个KV数据库的V类型多样化时,就需要包含相应的操作接口。例如,Redis 的V有List类型,因此它的接口就要包括对List的V的操作。
KV的保存位置
一般考虑的位置无非就是内存和外存。
- 保存在内存的好处是读写很快,毕竟内存的访问速度一般都在百 ns 级别。但是潜在的风险是一旦掉电,所有的数据都会丢失。
- 保存在外存,虽然可以避免数据丢失,但是受限于磁盘的慢速读写(通常在几 ms 级别),KV数据库的整体性能会被拉低。
因此,如何进行设计选择,我们通常需要考虑键值数据库的主要应用场景。比如,缓存场景下的数据需要能快速访问但允许丢失,那么,用于此场景的KV数据库通常采用内存保存KV数据。
大体来说,一个KV数据库包括了访问框架、索引模块、操作模块和存储模块
四部分:
访问框架设计 → 访问模式:
访问模式通常有两种:
- 通过函数库调用的方式供外部应用使用。比如上图中的 libsimplekv.so,就是以动态链接库的形式链接到我们自己的程序中,提供键值存储功能。
- 通过网络框架以 Socket 通信的形式对外提供键值对操作。这种形式可以提供广泛的键值存储服务。网络框架中包括 Socket Server 和协议解析。不同的键值数据库服务器和客户端交互的协议并不相同,我们在对键值数据库进行二次开发、新增功能时,必须要了解和掌握键值数据库的通信协议,这样才能开发出兼容的客户端。通过网络框架提供键值存储服务,一方面扩大了键值数据库的受用面,但另一方面,也给键值数据库的性能、运行模型提供了不同的设计选择,带来了一些潜在的问题。
RocksDB 以动态链接库的形式使用,Memcached 和 Redis 则是通过网络框架访问。
索引模块设计 → KV对定位:
索引的类型有很多,常见的有Hash、B+树、字典树
等。不同的索引结构在性能、空间消耗、并发控制等方面具有不同的特征。例如,Memcached 和 Redis 采用哈希表作为 key-value 索引,而 RocksDB 则采用跳表作为内存中 key-value 的索引。
一般而言,内存键值数据库(例如 Redis)采用哈希表作为索引,很大一部分原因在于,其KV数据基本都是保存在内存中的,而内存的高性能随机访问特性可以很好地与哈希表 O(1) 的操作复杂度相匹配。
需要注意的是,如果KV数据库的V支持不同类型,那么当我们通过K定位到V后还需要在V这个数据结构中做进一步查询。
存储模块设计(分配器)→ 如何分配内存:
在C中常用的内存分配器有 glibc 的 malloc 和 free,因此一般KV数据库并不需要特别考虑内存空间的管理问题。但是KV数据库的键值对通常大小不一,glibc的分配器在处理随机的大小内存块分配时,表现并不好。一旦保存的键值对数据规模过大,就可能会造成较严重的内存碎片问题。因此,分配器是键值数据库中的一个关键因素。
存储模块设计(持久化) → 如何做到重启后快速提供服务:
因为磁盘管理要比内存管理复杂,简单的KV数据库可以直接采用了文件形式,将键值数据通过调用本地文件系统的操作接口保存在磁盘上。那么此时就只需要考虑何时将内存中的键值数据保存到文件中就可以了。
一种方式是,对于每一个键值对都对其进行落盘保存,这虽然让数据更加可靠,但是,因为每次都要写盘,数据库的性能会受到很大影响。
另一种方式是,只是周期性地把内存中的键值数据保存到文件中,这样可以避免频繁写盘操作的性能影响。但一个潜在的代价是数据仍然有丢失的风险。
参考:蒋德钧老师《Redis核心技术与实战》极客时间专栏,强烈推荐!
如何设计一个简单的KV数据库相关推荐
- 计划实现一个开源的KV数据库——Simple DB
实现一个开源KV数据库的想法来源于对目前项目中所使用的K-V数据库使用情况的不满意. 先介绍一下我们的目前项目,作为本文的背景: 较为底层的分布式运行平台,使用C/C++实现的Actor模型(异步消息 ...
- 设计一个简单的购物页面(html+css+php)
水平有限,精力有限,很多东西写得可能不那么详细,有不懂可以留言提问,懂的尽量解答 首先讲一下,购物页面肯定会涉及到数据库部分的,我这篇文章数据库方面不会详细讲,就简单给个思路.购物需要用到cookie ...
- JAVA同时输入用户名和密码_用java模拟设计一个简单的“用户注册”程序。当用户输入用户名和密码时,单击“注...
用java模拟设计一个简单的"用户注册"程序.当用户输入用户名和密码时,单击"注 2020 - 9 - 26 TAG : 所有功能均已实现,如有不满意的地方我再修改imp ...
- python界面设计-手把手教你用Python设计一个简单的命令行界面
原标题:手把手教你用Python设计一个简单的命令行界面 对 Python 程序来说,完备的命令行界面可以提升团队的工作效率,减少调用时可能碰到的困扰.今天,我们就来教大家如何设计功能完整的 Pyth ...
- 设计一个简单分页存储管理系统_【系统架构】如何设计一个简单灵活的收银系统?看这里!(1)...
在电商项目中,收银系统是一个不可或缺的功能,因为你不仅要通过它来进行收款.退款,而且也要通过它进行财务的对账.报税等.因此,如何设计一个简单灵活的收银系统,对于开发电商项目来说非常重要. 那如何设计一 ...
- java完成一个学生信息调查程序_利用Java设计一个简单的学生信息管理程序
利用Java设计一个简单的控制台学生信息管理程序 此程序可作为课设的参考,其中信息存储于文件中. 创建了学生类Student,用于存储学号等的信息.创建StudentFunction类,用于实现诸如学 ...
- 大学慕课MOOC设计一个简单的计算工具
题目: 编程题: 设计一个简单的四则运算工具,有一个标题为"计算"的窗口,窗口布局为FlowLayout.设计四个按钮,分别命名为"加"."减&q ...
- 如何设计一个简单的网页
设计一个简单的网页 1.按住文件新建文本(Ctrl+N),设计一个网页标题,点击创建 2.在<body>内部加入所需要的标签 如图中需要标题标签,水平线标签,段落标签 3.保存(Ctrl+ ...
- linux logo程序设计,教你在线设计一个简单美观的LOGO
当你配置好Linux服务器并上传网站程序到服务器上,直到架设网站成功,你可能需要一个美观的LOGO,如果你对LOGO的要求不高,可以在线自己设计一个,因为网站发展初期,你没有什么资金,请不了专业的美化 ...
最新文章
- 2018-3-7 HDFS架构
- Android开发学习之路--Camera之初体验
- 如何在Eclipse里显示BPMN格式的流程图
- Spring Cloud —— 消息队列与 RocketMQ
- 面试问题:Spring实现AOP的方式
- UI设计需要学习什么软件?
- Linux后台进程(和jobs、bg、fg)
- php 变量传给另外一个函数,将在一个函数中创建的PHP变量传递给另一个
- paip.c++ bcb 字符串String分割split 为 TStringList 不对的的问题解决..
- Python手动安装Jieba库(Win11)
- 常见电容器图片_电容的电路符号及图片识别
- 【无机纳米材料科研制图——OriginLab 0206】Origin绘制X射线衍射XRD堆叠图
- 烟台移动dns网关_如何设置移动宽带DNS和IP地址
- python 简单易懂的验证码识别
- krita windows编译源码
- 使用nginx做负载均衡
- iconfont在ie8下不显示图标问题
- KCL:蚂蚁自研的配置策略语言
- 【Python】实现csv文件转json文件
- 计算机专业选i5八代还是i7八代,八代i5真的比七代i7更好?看看玩家的测试就知道!...
热门文章
- validator校验注解
- 内网穿透+ssh登录打造私人云服务器
- Zookeeper 服务器端和客户端扩大节点数据1M大小限制
- RFID反向不归零编码(NRZ)
- R语言glm函数构建二分类logistic回归模型、epiDisplay包logistic.display函数获取模型汇总统计信息(自变量初始和调整后的优势比及置信区间,回归系数的Wald检验的p值
- coco训练集darknet_darknet-yolov3训练自己的数据集
- java搭建安卓服务器_无框架完整搭建安卓app及其服务端(一)
- 校招季--献给前端求职路上的你们(H5+C3)
- shell数组目录遍寻循环输出
- 原问题与对偶问题的定义和关系