作者:poppindouble
记得在读书的时候,教授和我们说计算机没有什么神奇的地方,计算机领域不外乎就是如何存储数据以及如何处理数据两个问题。其实这两个问题是密不可分的,数据的存储方式是直接影响到数据的处理方式的。好的数据存储模式可以让系统的响应更快、业务逻辑更简单、运行起来更稳定;不好的数据存储模式不利于以后系统的扩展,甚至可能要把之前所有的代码库推翻重写。那么什么是“好”的数据存储方式呢?这个问题当然需要看系统的业务需求,但是我们希望能给大家提供另一种角度来审视数据,ImmuxDB就是一款从历史角度来看数据的数据库,其灵感来自于区块链、源码控制、以及前端的React和Redux技术。
数据本该如此
计算机的体系结构是叠床架式的,在最底层是硬件,也就是CPU和硬盘等等,然后是编译器和操作系统,再往上走才是存储引擎等等的软件。其实在不同的层面,都有一些设计是体现了从历史角度来审视软件的想法的。我举几个例子:
1、在文件系统,有ZFS,其核心思想是写入时复制事物(Copy-on-write),这样的好处是在写新数据的时候断电或者系统崩溃了,那么原数据会被保留下来,在修复系统的时候不需要再运行fsck来检查和修复文件系统,文件系统不会因为一些外在的原因而处在一个不正常的状态。也是因为这种特性,使得快照功能变得更简单以及自然,在恢复文件系统的时候也更为简单。
2、在操作系统层面,有Timeshift这样的软件,在OSX上应该是叫Time Machine。Unix类的操作系统都会将所有一切视为文件,上面提到的这类软件其核心想法就是将某一个时刻该系统的所有的文件状态记录下来,在恢复的时候直接将之前记录下来的文件拷贝到对应的系统路径即可。
3、前端有React和Redux,Redux也提供了time traveling这样的功能,单向的数据流使得前端开发更为简便,更容易debug,这也使得React这几年成为非常火热的前端框架。
4、再往宏观上看,就是区块链技术,其历史不变性才使得数字货币的出现成为了可能。
ImmuxDB的出现也是受到了上面技术的启发,从历史的角度来审视我们的数据。现在主流的数据库产品并没有从这个角度来看数据,在设计数据库的时候,数据都是允许被覆盖的,其实也就是允许用户覆盖历史数据,历史并没有被保留下来。而ImmuxDB,正如其名字所示,所有的数据是不可变的,写进去的数据就是曾经的历史,如果再要写新的数据,那么新的数据将会是原来数据的一个复制,也正是这样的设计初衷,使得ImmuxDB具有主流数据库所不具备的特性,比如可以回溯到数据库历史上某一个版本,查看某个键所有的历史数据,所有的数据是可以通过历史来解释的。
基于日志文件的设计
从技术角度来说,数据库是一个很模糊的词。同为Database,比如LevelDB和MySQL是完全不同的两个软件,做的事情也有很多不同的地方。在这里我想给出一个比较明确的定义,以便后面的阅读。
数据库和存储引擎是两个不同层面的东西,面向的使用者也不一样。数据库是提供给后端工程师,业务逻辑开发人员等等使用的,数据库提供了丰富的类型,提供了较强的data manipulation language (DML),甚至数据库会集成不同的网络请求的接口,有自己的网络报文格式等等,而对于使用者,具体后面是分布式的存储还是单机版的存储,这并不重要,使用者只需要会对应的DML,便可以开始最基本的使用了。而存储引擎是数据库的核心,存储引擎没有丰富的类型,存储引擎通用的类型只有byte,没有丰富的DML,一个存储引擎最基本的“DML”可能是KV的方式查询的。对于现阶段的ImmuxDB,它包含了存储引擎的功能,也有一部分数据库的功能,我们支持相对丰富的类型,支持较为简单的Tcp报文协议,支持RESTful API,也有较为简单的DML。
我们主要聊聊存储引擎的设计,存储引擎其实最主要就是处理两方面的问题,第一是内存,第二是硬盘。一个数据的读写,都会在这两个物理硬件上停留,如何协同这两个硬件,使得读写的速度更快,就是一个存储引擎应该要处理的问题。ImmuxDB是一个很有特色的数据库,特色的地方就在于对历史数据的保留,这和日志文件(Log File)的设计是非常吻合的。在设计一款存储引擎之前,作为开发人员,我觉得最重要的是先搞清楚这个引擎要用在哪里,这个引擎应该会有的特性,比如LevelDB以及RocksDB,这两款存储引擎的设计就是为了提高写入的性能而牺牲掉一部分读取的性能,那是因为这两款存储引擎存在的目的就是为了让爬虫尽可能快的写入数据。ImmuxDB的存在就是为了保护好历史数据,读写的性能反而求其次,因此我参考了两款基于日志文件的存储引擎,Sled以及Bitcask. Sled是一款用无锁编程技术写的存储引擎,Bitcask是作为Riak的存储引擎,两者的核心思想类似,内存都是一个Hash Table,而实际的数据是按日志顺序存储在硬盘上的。ImmuxDB的设计灵感也是源自于这两款存储引擎,通过在内存维护Hash Table来对日志文件进行检索,而历史数据都记录日志里面,如果有任何系统崩坏等情况发生,通过日志也可以使得存储引擎恢复到崩坏前的健康状态。
未来的路
现在的ImmuxDB基本的接口已经稳定,在事物(Transaction)上还有更高级别的独立性需要实现,性能上也还有很大的上升空间,比如内存的数据结构可以通过无锁编程实现,对于硬盘的写入,io_uring的日渐成熟似乎非常值得我们去尝试,在硬件层面,19年Intel的persistent memory的出现也是非常有潜力的。我们的软件都是开源的,我本人主要负责ImmuxDB的开发工作,有想法的小伙伴欢迎来提PR,来交流。
下面是我们的Github: