個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證A Datomic-inspired triplestore in Rust on top of SlateDB
翻譯準備中
取自儲存庫 README
正在載入完整 README。 以下為已儲存的摘錄。
🚧 WARNING: Alpha Software 🚧
Triplox is alpha software. The index encoding has not yet stabilized. There will be bugs. There will be ingestion and congestion issues. Incremental queries will likely be slow.
Triplox is a Datomic-inspired general-purpose database on top of object storage. The backbone of the engine is SlateDB, a key-value store on top of object-storage. Datomic is the main inspiration and the data model, transaction semantics and query API closely follow Datomic.檢視完整 README ↗🚧 WARNING: Alpha Software 🚧 Triplox is alpha software. The index encoding has not yet stabilized. There will be bugs. There will be ingestion and congestion issues. Incremental queries will likely be slow.
Triplox is a Datomic-inspired general-purpose database on top of object storage. The backbone of the engine is SlateDB, a key-value store on top of object-storage. Datomic is the main inspiration and the data model, transaction semantics and query API closely follow Datomic.
The ideas of Triplox are roughly the following (in no particular order):
The easiest way to test Triplox is to just pull the docker image and start an in-memory or local node.
docker pull ghcr.io/fiv0/triplox:0.1.0-alpha.8
docker run -p 5490:5490 ghcr.io/fiv0/triplox:0.1.0-alpha.8
This will start a Triplox server with an in-memory DB to which you can connect at 5490. If you want an persistent local node, you start the image with
docker run -p 5490:5490 -e TRIPLOX_STORAGE=local -v triplox-data:/var/lib/triplox ghcr.io/fiv0/triplox:0.1.0-alpha.8
In case you are already convinced (which you shouldn't) and want to deploy Triplox in a distributed setting I suggest you have a look at the Operations section on the website.
There is also the option to run Triplox in dev mode which is particular useful for testing.
docker run -p 5490:5490 -e TRIPLOX_STORAGE=dev ghcr.io/fiv0/triplox:0.1.0-alpha.8
In this case a new in-memory DB is created on every connection.
Afterwards you connect with your favorite client.
(require '[xyz.triplox.api :as tc])
(def conn (tc/connect "localhost" 5490))
;; schema
(tc/transact conn [{:db/ident :name
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one}
{:db/ident :age
:db/valueType :db.type/long
:db/cardinality :db.cardinality/one}])
;; data
(tc/transact conn [{:name "alice" :age 30}
{:name "bob" :age 25}])
;; query
(def db (tc/db conn))
(tc/q db '{:find [?e ?name ?age]
:where [[?e :name ?name]
[?e :age ?age]]})
;; => [[8796093022209 "alice" 30] [8796093022208 "bob" 25]]
Triplox also supports incremental queries. If you want to understand or get a feeling for how Triplox deals with incremental queries you can have a look at the incremental tutorial.
If you would like to create another client there is a PROTOCOL design doc that should help. Currently the
HTTP/2 server only supports a custom MessagePack encoding scheme. We plan to add support for transit+json and transit+msgpack
in the future.
By making object storage the single source of truth, you get separation of storage and compute. SlateDB has a single writer and many readers architecture and that directly translates to Triplox. Triplox sits in the traditional client/server camp. Queries run on the server. For example limiting your query results would be done with :limit in a EDN Datalog query instead of doing it application code side.
The layout of the indices and also SlateDB's focus are OLTP queries. If you expect columnar layout performance for OLAP style queries, Triplox is not the right fit. This doesn't mean Triplox doesn't support aggregates, it will just not beat something like DuckDB on these types of queries. Also keep in mind that the architecture favors read heavy workloads. Triplox is currently single writer.
A typical setup for Triplox with 3 nodes (1 primary writer node + 2 readers nodes) would then roughly look like the diagram below. Transactions get send to the log to get a total-order and then indexed through the primary indexing node into SlateDB. Reads can then be served from the primary node immediately and form any reader node as soon as the reader nodes receive new WALs (Write-Ahead Logs) from Object Storage.
There are some design decisions that still are up for grabs. In particular the external log has been a thorn in my side and I would like to get rid of it. See Open Questions > Log on the website.
┌─────────────────────────────────────────────────────────────┐
│ Object Storage (S3) │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ SlateDB │ │ SlateDB │ │ SlateDB │ │
│ │ (Writer) │ │ (Reader 1) │ │ (Reader 2) │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
└─────────┼────────────────────┼────────────────────┼─────────┘
│ │ │
Queries/Indices ▲ read/write ▼ read ▼ read
│ │ │
┌────────────────────┴────────┐ ┌────────┴────────┐ ┌────────┴───────┐
│ Writer Node │ │ Reader Node 1 │ │ Reader Node 2 │
│ │ │ │ │ │
│ ┌──────────────┐ │ │ │ │ │
┌─────┼────▶│ Indexer │ │ │ │ │ │
│ │ └──────────────┘ │ │ │ │ │
│ │ │ │ │ │ │
│ └─────────────┬───────────────┘ └─────────────────┘ └────────────────┘
│ │
│ Transactions │ write
│ ▼
│ ┌──────────────────────────────────────────────────────────────────────┐
│ │ │
│ │ Log (Kafka, S2, WAL3, etc.) │
│ │ │
│ │ ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐ │
└─────┼────┤ tx0 │ tx1 │ tx2 │ tx3 │ tx4 │ tx5 │ tx6 │ ... │ │
read │ └─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘ │
│ │
└──────────────────────────────────────────────────────────────────────┘
This project is very much WIP and any help is appreciated. Discussions and feedback happen on Discord.
There is lots of things to work on. Feel free to open tickets for features, bugs or general ideas. If you are building something more involved it's likely better to discuss it first (either on Discord or in a ticket) and see if it fits the projects scope.
There are some more open questions that I tried to write down on the website
The primary inspiration is Datomic and you will see it's impact throughout the project. Mentat (from which the edn crate is copied) has been a great inspiration and help in designing the transaction pipeline of Triplox. The folks at Feldera have created the very clean and elegant DBSP theory without the incremental queries would not be possible.
The goal is not to have a 1-to-1 correspondence of features with Datomic. Datomic is the main inspiration and we'll strive to stay close to the Datomic APIs, but don't plan for feature parity nor identical behavior in all cases. The main differences will currently show up in the transaction pipeline. I am currently not dealing with schema updates. There might also be edge cases where the transaction pipeline semantics slightly differ. There are currently two separate query engines at play, one for standard queries and one for incremental queries (at some point in the future these might converge). It should generally be the case that the standard query engine supports a superset of queries the incremental engine supports.
Some of the ideas of this repository have been explored in hooray2, a simpler in-memory Datalog engine. Especially WCOJ (Worst-case optimal joins) and Datalog to DBSP compilation have been explored there. It often serves as a testbed of ideas for Triplox.
Triplox is licensed under the Apache License, Version 2.0.
The edn crate was orginally copied from mentat and is also licenced under Apache Licence, Version 2.0.