PumpkinDB

不可变的有序键值数据库引擎。「Immutable Ordered Key-Value Database Engine」

Github stars Tracking Chart

PumpkinDB

PumpkinDB是一个不可改变的有序键值数据库引擎,其特点是:

  • ACID 事务
  • 永久性存储
  • 一种嵌入式编程语言(PumpkinScript)。
  • 二进制键和值(允许使用任何编码:JSON、XML、Protobuf、Cap'n Proto等)。
  • 独立和嵌入式方案

为什么是不可更改的?

简单地说,被替换的数据就是被删除的数据,因此,是一种不安全的数据管理方式。错误、误解、改变范围和需求等因素都可能影响数据(尤其是过去的数据)的意义和如何使用。

通过保证 key 的值一旦被设置就不可改变,PumpkinDB 迫使用户从时间的角度来考虑他们的数据。

这种方法对于实现事件源和类似类型的架构非常有利。

什么是 PumpkinDB?

PumpkinDB 本质上是一个数据库编程环境,主要是受 MUMPS 背后的核心思想启发。它没有采用 M,而是采用了一种受 Forth 启发的基于堆栈的语言--PumpkinScript。它没有分层键,而是有一个扁平的键名空间,并且一旦设置了值,就不允许覆盖。不变性的核心动机是,随着存储成本的下降,擦除数据实际上是一种战略错误。

虽然它的目的不是为了通用编程,但其主要目的是为了方便构建专门的特定应用和通用数据库,特别是注重不可变性,并尽可能接近存储地处理数据,尽可能少地招致通信惩罚。

应用程序通过网络接口发送小型 PumpkinScript 程序与 PumpkinDB 进行通信(当使用 PumpkinDB 作为嵌入式解决方案时,则通过 API 进行通信)。

PumpkinDB 为并发、存储、日志、索引和其他常见的构建模块提供了大量的基元。

为什么说它是一个数据库引擎?

PumpkinDB 背后的核心思想源于所谓的 懒惰事件来源(lazy event sourcing) 方法,它基于存储和索引事件,同时尽可能地延迟域绑定的时间。也就是说,这个数据库的意图是成为不同类型架构的构件,无论是经典的事件源(将其作为事件存储),还是懒惰的事件源(使用索引)或其他任何方式。也可以在一个数据库中针对不同的部分实现不同的方法。

与其设计自定义的协议与 PumpkinDB 对话,不如将通信协议变成一条通往脚本执行器的管道。这为我们提供了巨大的扩展和灵活性能力。

外部应用可以通过网络连接与 PumpkinDB 对话,而 PumpkinDB 的引擎本身是可嵌入的,可以直接使用。目前,它只适用于 Rust 应用,但有一天可能会扩展到所有能与 C 语言接口的语言。

客户端库

Language Library Status
Rust pumpkindb_client Early release (0.2.0)
Java pumpkindb-client Pre-release

试试吧

你可以 从 GitHub 上下载 PumpkinDB 版本。

Docker

你可以通过 docker 映像来试用最新的 PumpkinDB HEAD 版本。

$ docker pull pumpkindb/pumpkindb

或者,你也可以自己建立映像:

$ docker build . -t pumpkindb/pumpkindb

运行服务器:

$ docker run -p 9981:9981 -ti pumpkindb/pumpkindb
2017-04-12T02:52:47.440873517+00:00 WARN pumpkindb - No logging configuration specified, switching to console logging
2017-04-12T02:52:47.440983318+00:00 INFO pumpkindb - Starting up
2017-04-12T02:52:47.441122740+00:00 INFO pumpkindb_engine::storage - Available disk space is approx. 56Gb, setting database map size to it
2017-04-12T02:52:47.441460231+00:00 INFO pumpkindb - Starting 4 schedulers
2017-04-12T02:52:47.442375937+00:00 INFO pumpkindb - Listening on 0.0.0.0:9981

最后,使用 pumpkindb-term 连接到服务器:

$ docker run -ti pumpkindb/pumpkindb pumpkindb-term 172.17.0.1:9981 # replace IP with the docker host IP

从源代码构建

也欢迎你克隆仓库并自己构建。你将需要 Rust Nightly 来做这件事。最简单的方法是使用 rustup

$ rustup install nightly
$ rustup override set nightly # in PumpkinDB directory

这之后,您可以以这种方式运行 PumpkinDB 服务器:

$ cargo build --all
$ ./target/debug/pumpkindb
2017-04-03T10:43:49.667667-07:00 WARN pumpkindb - No logging configuration specified, switching to console logging
2017-04-03T10:43:49.668660-07:00 INFO pumpkindb - Starting up
2017-04-03T10:43:49.674139-07:00 INFO pumpkindb_engine::storage - Available disk space is approx. 7Gb, setting database map size to it
2017-04-03T10:43:49.675759-07:00 INFO pumpkindb - Starting 8 schedulers
2017-04-03T10:43:49.676113-07:00 INFO pumpkindb - Listening on 0.0.0.0:9981

你可以使用 pumpkindb-term 连接到服务器:

$ ./target/debug/pumpkindb-term
Connected to PumpkinDB at 0.0.0.0:9981
To send an expression, end it with `.`
Type \h for help.
PumpkinDB> ["Name" HLC CONCAT "Jopn Doe" ASSOC COMMIT] WRITE.
PumpkinDB> ["Name" HLC CONCAT "John Doe" ASSOC COMMIT] WRITE.
PumpkinDB> [CURSOR DUP "Name" CURSOR/SEEKLAST DROP CURSOR/VAL] READ (Get last value).
"John Doe"
PumpkinDB> [CURSOR DUP "Name" CURSOR/SEEKLAST DROP DUP CURSOR/PREV DROP CURSOR/VAL] READ (Get previous value).
"Jopn Doe"
(The above example shows how one can query and navigate for values submitted at a different time, using low level primitives).

你可以通过创建 pumpkindb.toml 来改变服务器的参数:

[storage]
path = "path/to/db"
# By default, mapsize will equal to the size of
# available space on the disk, except on Windows,
# where default would be 1Gb.
# `mapsize` is a theoretical limit the database can
# grow to. However, on Windows, this also means that
# the database file will take that space.
# This parameter allows to specify the mapsize
# in megabytes.
# mapsize = 2048
[server]
port = 9981

组件

PumpkinDB 项目被分割成几个独立的组件(crate):

  • pumpkinscript — PumpkinScript 解析器。允许将 PumpkinScript 文本转换成二进制形式。
  • pumpkindb_engine — PumpkinDB 核心库。提供 PumpkinScript 调度器和一个标准的指令库。
  • pumpkindb_mio_server — 基于异步 MIO 的 PumpkinDB 服务器库。用于构建自定义的 PumpkinProtocol 兼容的服务器。
  • pumpkindb_client — PumpkinProtocol 客户端库。
  • pumpkindb_server — Stock PumpkinDB服务器。建立在 pumpkindb_mio_server 之上。
  • pumpkindb_term — 基于控制台的 PumpkinDB 服务器客户端。
  • doctests — 用于运行指令测试的小工具。

贡献者

这个项目还处于非常早期的阶段,我们将永远欢迎贡献者。

我们的目标是鼓励对项目无阻力的贡献。为了实现这个目标,我们使用了 Unprotocols C4 流程。请阅读它,它会回答很多问题。我们的目标是尽快合并拉取请求,并定期发布新的稳定版本。

简而言之,这意味着

  • 我们快速合并拉取请求(尝试!)。
  • 我们对不同的想法持开放态度
  • 我们更喜欢现在的代码,而不是以后的共识

要了解更多信息,请阅读我们的贡献指南

我们还保留了一份 问题清单,我们认为这些问题对于新的贡献者来说是很好的开始。

支持者

通过每月捐款支持我们,帮助我们继续开展活动。[成为支持者]

贊助商

成为赞助商,并在 Github 上的 README 上获得你的标志和你的网站链接。[成为赞助商]


(The first version translated by vz on 2020.10.10)

Overview

Name With OwnerPumpkinDB/PumpkinDB
Primary LanguageRust
Program languageRust (Language Count: 3)
PlatformDocker, Linux, Mac, Windows
License:Mozilla Public License 2.0
Release Count2
Last Release Namev0.2.0 (Posted on )
First Release Namev0.1.0 (Posted on )
Created At2017-02-01 18:09:04
Pushed At2020-03-21 18:48:37
Last Commit At2017-08-14 08:26:23
Stargazers Count1.4k
Watchers Count43
Fork Count59
Commits Count576
Has Issues Enabled
Issues Count133
Issue Open Count39
Pull Requests Count206
Pull Requests Open Count1
Pull Requests Close Count12
Has Wiki Enabled
Is Archived
Is Fork
Is Locked
Is Mirror
Is Private

PumpkinDB

Gitter chat
Code Triagers
OpenCollective
OpenCollective

Build status (Linux) Build Status
Build status (Windows) Windows Build status
Project status Usable, between alpha and beta
Production-readiness Depends on your risk tolerance

PumpkinDB is an immutable ordered key-value database engine, featuring:

  • ACID transactions
  • Persistent storage
  • An embedded programming language (PumpkinScript)
  • Binary keys and values (allows any encoding to be used: JSON, XML, Protobuf, Cap'n Proto, etc.)
  • Standalone and embedded scenarios

Why immutable?

Simply put, the data replaced is data deleted and is therefore, an unsafe way to manage data. Bugs,
misunderstanding, changing scope and requirements and other factors might influence what data (and
especially past data) means and how can it be used.

By guaranteeing the immutability of key's value once it is set, PumpkinDB forces its users
to think of their data through a temporal perspective.

This approach is highly beneficial for implementing event sourcing and similar types of architectures.

What is PumpkinDB?

PumpkinDB is essentially a database programming environment, largely inspired by core ideas behind MUMPS. Instead of M,
it has a Forth-inspired stack-based language, PumpkinScript. Instead of hierarchical keys, it has a flat key namespace and doesn't allow overriding values once they are set. Core motivation for immutability was that with the cost of storage declining, erasing data is effectively a strategical mistake.

While not intended for general purpose programming, its main objective is to facilitate building specialized application-specific and generic databases with a particular focus on immutability and processing data as close to storage as possible, incurring as little communication penalty as possible.

Applications communicate with PumpkinDB by sending small PumpkinScript programs
over a network interface (or API when using PumpkinDB as an embedded solution).

PumpkinDB offers a wide array of primitives for concurrency, storage, journalling, indexing and other common building blocks.

Why is it a database engine?

The core ideas behind PumpkinDB stem from the so called
lazy event sourcing
approach which is based on storing and indexing events while delaying domain
binding for as long as possible. That said, the intention of this database is to
be a building block for different kinds of architectures, be it
classic event sourcing (using it as an event store), lazy event sourcing (using
indices) or anything else. It's also possible to implement different approaches within
a single database for different parts of the domain.

Instead of devising custom protocols for talking to PumpkinDB, the protocol of
communication has become a pipeline to a script executor. This offers us enormous extension
and flexibility capabilities.

While an external application can talk to PumpkinDB over a network connection, PumpkinDB's
engine itself is embeddable and can be used directly. Currenly, it is available for Rust
applications only, but this may one day extend to all languages that can interface with C.

Client libraries

Language Library Status
Rust pumpkindb_client Early release (0.2.0)
Java pumpkindb-client Pre-release

Trying it out

You can download PumpkinDB releases from GitHub.

Docker

You can try out latest PumpkinDB HEAD revision by using a docker image:

$ docker pull pumpkindb/pumpkindb

Alternatively, you can build the image yourself:

$ docker build . -t pumpkindb/pumpkindb

Run the server:

$ docker run -p 9981:9981 -ti pumpkindb/pumpkindb
2017-04-12T02:52:47.440873517+00:00 WARN pumpkindb - No logging configuration specified, switching to console logging
2017-04-12T02:52:47.440983318+00:00 INFO pumpkindb - Starting up
2017-04-12T02:52:47.441122740+00:00 INFO pumpkindb_engine::storage - Available disk space is approx. 56Gb, setting database map size to it
2017-04-12T02:52:47.441460231+00:00 INFO pumpkindb - Starting 4 schedulers
2017-04-12T02:52:47.442375937+00:00 INFO pumpkindb - Listening on 0.0.0.0:9981

Finally, connect to it using pumpkindb-term:

$ docker run -ti pumpkindb/pumpkindb pumpkindb-term 172.17.0.1:9981 # replace IP with the docker host IP

Building from the source code

You are also welcome to clone the repository and build
it yourself. You will need Rust Nightly to do this. The easiest way to get it is to use
rustup

$ rustup install nightly
$ rustup override set nightly # in PumpkinDB directory

After that, you can run PumpkinDB server this way:

$ cargo build --all
$ ./target/debug/pumpkindb
2017-04-03T10:43:49.667667-07:00 WARN pumpkindb - No logging configuration specified, switching to console logging
2017-04-03T10:43:49.668660-07:00 INFO pumpkindb - Starting up
2017-04-03T10:43:49.674139-07:00 INFO pumpkindb_engine::storage - Available disk space is approx. 7Gb, setting database map size to it
2017-04-03T10:43:49.675759-07:00 INFO pumpkindb - Starting 8 schedulers
2017-04-03T10:43:49.676113-07:00 INFO pumpkindb - Listening on 0.0.0.0:9981

You can connect to it using pumpkindb-term:

$ ./target/debug/pumpkindb-term
Connected to PumpkinDB at 0.0.0.0:9981
To send an expression, end it with `.`
Type \h for help.
PumpkinDB> ["Name" HLC CONCAT "Jopn Doe" ASSOC COMMIT] WRITE.

PumpkinDB> ["Name" HLC CONCAT "John Doe" ASSOC COMMIT] WRITE.

PumpkinDB> [CURSOR DUP "Name" CURSOR/SEEKLAST DROP CURSOR/VAL] READ (Get last value).
"John Doe"
PumpkinDB> [CURSOR DUP "Name" CURSOR/SEEKLAST DROP DUP CURSOR/PREV DROP CURSOR/VAL] READ (Get previous value).
"Jopn Doe"

(The above example shows how one can query and navigate for values submitted at a different time, using low level primitives).

You can change some of the server's parameters by creating pumpkindb.toml:

[storage]
path = "path/to/db"
# By default, mapsize will equal to the size of
# available space on the disk, except on Windows,
# where default would be 1Gb.
# `mapsize` is a theoretical limit the database can
# grow to. However, on Windows, this also means that
# the database file will take that space.
# This parameter allows to specify the mapsize
# in megabytes.
# mapsize = 2048

[server]
port = 9981

Components

PumpkinDB project is split into a couple of separate components (crates):

  • pumpkinscript — PumpkinScript parser. Allows to convert text PumpkinScript form into binary one.
  • pumpkindb_engine — Core PumpkinDB library. Provides PumpkinScript scheduler, and a standard library of instructions
  • pumpkindb_mio_server — Async MIO-based PumpkinDB server library. Useful for building custom PumpkinProtocol-compatible servers.
  • pumpkindb_client — PumpkinProtocol client library.
  • pumpkindb_server — Stock PumpkinDB server. Built on top of pumpkindb_mio_server.
  • pumpkindb_term — console-based PumpkinDB server client.
  • doctests — a small utility to run instructions doctests.

Contributing

This project is in its very early days and we will always be welcoming
contributors.

Our goal is to encourage frictionless contributions to the project. In order to
achieve that, we use Unprotocols C4 process.
Please read it, it will answer a lot of questions. Our goal is to merge pull requests
as quickly as possible and make new stable releases regularly.

In a nutshell, this means:

  • We merge pull requests rapidly (try!)
  • We are open to diverse ideas
  • We prefer code now over consensus later

To learn more, read our contribution guidelines

We also maintain a list of issues that we think are good starters for new
contributors.

Backers

Support us with a monthly donation and help us continue our activities. [Become a backer]






























Sponsors

Become a sponsor and get your logo on our README on Github with a link to your site. [Become a sponsor]






























To the top