{"id":29482714,"url":"https://github.com/kronotop/kronotop","last_synced_at":"2025-07-15T02:02:14.144Z","repository":{"id":170748015,"uuid":"622856821","full_name":"kronotop/kronotop","owner":"kronotop","description":"Kronotop is a distributed, transactional document database designed for horizontal scalability. ","archived":false,"fork":false,"pushed_at":"2025-07-13T17:13:58.000Z","size":3107,"stargazers_count":273,"open_issues_count":0,"forks_count":9,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-07-13T17:29:29.056Z","etag":null,"topics":["database","distributed-database","distributed-systems","foundationdb","redis","transactional-database"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kronotop.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"buraksezer","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2023-04-03T07:52:04.000Z","updated_at":"2025-07-13T10:14:43.000Z","dependencies_parsed_at":"2024-05-01T17:30:47.832Z","dependency_job_id":"f19f85b2-c185-41a3-8a5f-77da8d4070f5","html_url":"https://github.com/kronotop/kronotop","commit_stats":null,"previous_names":["kronotop/kronotop"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/kronotop/kronotop","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kronotop%2Fkronotop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kronotop%2Fkronotop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kronotop%2Fkronotop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kronotop%2Fkronotop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kronotop","download_url":"https://codeload.github.com/kronotop/kronotop/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kronotop%2Fkronotop/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265386079,"owners_count":23756747,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database","distributed-database","distributed-systems","foundationdb","redis","transactional-database"],"created_at":"2025-07-15T02:01:31.207Z","updated_at":"2025-07-15T02:02:14.120Z","avatar_url":"https://github.com/kronotop.png","language":"Java","funding_links":["https://github.com/sponsors/buraksezer"],"categories":["数据库","Java"],"sub_categories":[],"readme":"# Kronotop\n\n**The Distributed Document Database with ACID Integrity**\n\nKronotop is a distributed, transactional document database designed for horizontal scalability. It provides a robust\nfoundation for applications needing to manage large volumes of documents while ensuring strong consistency guarantees\nfor critical metadata operations. By leveraging FoundationDB as its transactional backend for metadata and indexes,\nKronotop delivers [ACID](https://apple.github.io/foundationdb/developer-guide.html#transaction-basics) integrity,\noffering reliability often sought in demanding environments.\n\nKronotop features an [MQL-like query language](https://www.mongodb.com/docs/manual/reference/operator/) and uses\nthe [RESP3](https://redis.io/docs/latest/develop/reference/protocol-spec/) wire protocol, ensuring broad compatibility\nwith\nthe Redis client ecosystem. It implements core Redis in-memory data structures like Strings and Hashes, alongside its\nown specialized\nstructures: ZMap (an ordered key-value store acting as a RESP proxy for FoundationDB) and Bucket (designed for storing\nJSON-like documents). While document bodies are stored directly on local filesystems, Kronotop uses BSON as the default\ndata format to organize and store within Buckets, with JSON also available.\n\n*Kronotop is built for developers seeking the flexibility of a document model combined with the transactional safety and\nscalability powered by FoundationDB.*\n\n**Warning**: Kronotop is in its early stages of development. The API is unstable and likely to change in future\nreleases.\n\nSee [Getting started](#getting-started) section.\n\nJoin the [Discord channel](https://discord.gg/Nyy4Afpr) to discuss.\n\n## At a Glance\n\n- **RESP3 Wire Protocol Compatibility:**  \n  Kronotop communicates over the [RESP3](https://redis.io/docs/latest/develop/reference/protocol-spec/) protocol,\n  ensuring seamless interoperability with the vast ecosystem of Redis clients across different programming languages.\n\n- **Built for Horizontal Scalability:**  \n  The system is natively designed for sharding and horizontal scaling, making it ideal for growing workloads without\n  compromising performance or reliability.\n\n- **Flexible Deployment Topologies:**  \n  Supports both **single-master** and **multi-master** cluster configurations, enabling diverse deployment strategies to\n  suit varying consistency and availability needs.\n\n- **Partial Redis Cluster Specification Support:**  \n  Implements key aspects of the Redis Cluster protocol, providing familiarity for teams migrating from Redis or building\n  distributed applications.\n\n- **ACID Transactions:**  \n  Relies on **FoundationDB** as a transactional metadata and indexing store, offering ACID guarantees critical for\n  consistency in cluster operations and data structures.\n\n- **Native Document-Oriented Storage:**  \n  Introduces **Bucket** — a specialized structure for storing JSON-like documents, backed by FoundationDB's\n  transactional core.\n\n- **Efficient Binary Data Handling:**  \n  Uses **BSON** as the default storage format for structured documents, with optional JSON support for broader\n  interoperability.\n\n- **In-Memory and Durable Data Structures:**  \n  Combines Redis-like in-memory structures (Strings, Hashes) with persistent, FoundationDB-backed storage layers like\n  ZMap and Buckets.\n\n- **Implemented in Java (JDK 21+ Required):**  \n  Written in modern Java, leveraging Virtual Threads and Project Loom features for high concurrency and low-overhead\n  task management.\n\n- **Developer-Focused Design:**  \n  Built for developers who need the flexibility of a document model combined with strong transactional integrity, high\n  performance, and operational simplicity.\n\n## What We Have\n\nKronotop is in its early development stage, but it already provides a robust foundation with several essential features:\n\n- **ZMap – FoundationDB-Powered Ordered Key-Value Store:**  \n  A high-performance, ordered key-value store built on top of FoundationDB.  \n  ZMap acts as a Redis protocol proxy, bridging the RESP interface with FoundationDB’s transactional API.\n\n- **Namespaces – Logical Isolation for ZMaps and Buckets:**  \n  Namespaces enable multi-tenancy and logical separation across data structures.  \n  Internally, it's a lightweight abstraction over FoundationDB’s Directory Layer.\n\n- **Volume – Storage Engine with Replication:**  \n  A storage engine designed to support **primary-standby replication**, allowing for durability and high availability of\n  persistent components like Buckets.\n\n- **Clustering – Flexible Deployment Topologies:**  \n  Native support for clustering in both **single-master** and **multi-master** modes, making Kronotop suitable for a\n  range of distributed system architectures.\n\n- **Partial Redis Data Structure Compatibility:**  \n  Initial support for Redis-style in-memory data structures, currently including **String** and **Hash** types, with\n  RESP2/RESP3 compatibility.\n\n## Plans for the foreseeable future\n\n* Design and implement a data structure called **Bucket** to store JSON-like documents,\n* **Bucket** data structure will support\n  an [MQL-like query language](https://www.mongodb.com/docs/manual/reference/operator/) and transactions backed by\n  FoundationDB,\n* Provide the most common Redis data structures such as String, Hash, Sorted Sets, etc.\n\n## Table of Contents\n\n* [Getting started](#getting-started)\n    * [Initializing a Kronotop cluster](#initializing-a-kronotop-cluster)\n* [Redis compatibility](#redis-compatibility)\n* [Support](#support)\n* [Features](#features)\n    * [Transaction management](#transaction-management)\n        * [BEGIN](#begin)\n        * [COMMIT](#commit)\n        * [ROLLBACK](#rollback)\n        * [GETAPPROXIMATESIZE](#getapproximatesize)\n        * [GETREADVERSION](#getreadversion)\n        * [SNAPSHOTREAD](#snapshotread)\n    * [ZMap](#zmap--ordered-key-value-store-backed-by-foundationdb)\n        * [ZSET](#zset)\n        * [ZGET](#zget)\n        * [ZGETKEY](#zgetkey)\n        * [ZGETRANGE](#zgetrange)\n        * [ZGETRANGESIZE](#zgetrangesize)\n        * [ZMUTATE](#zmutate)\n        * [ZDEL](#zdel)\n        * [ZDELRANGE](#zdelrange)\n    * [Namespaces](#namespaces)\n        * [NAMESPACE CREATE](#namespace-create)\n        * [NAMESPACE REMOVE](#namespace-remove)\n        * [NAMESPACE CURRENT](#namespace-current)\n        * [NAMESPACE USE](#namespace-use)\n        * [NAMESPACE EXISTS](#namespace-exists)\n        * [NAMESPACE LIST](#namespace-list)\n        * [NAMESPACE MOVE](#namespace-move)\n    * [Management](#management)\n        * [Session](#session)\n* [Documentation](#documentation)\n* [License](#license)\n\n## Getting started\n\nIt's easy to try Kronotop with Docker Compose:\n\n```bash\ncurl -o kronotop-demo.yaml https://raw.githubusercontent.com/kronotop/kronotop/refs/heads/main/docker/kronotop-demo.yaml\n```\n\nThen, you can run the following command to create a single-member Kronotop cluster for demonstration purposes:\n\n```bash\ndocker compose -f kronotop-demo.yaml up \n```\n\nIf everything goes okay, you should be able to connect to the primary node via `redis-cli`:\n\n```\nredis-cli -p 3320 -c\n127.0.0.1:3320\u003e PING\nPONG\n```\n\nA cluster member serves from two ports:\n\n* *5484* for the client communication,\n* *3320* for the internal traffic and administrative commands.\n\n### Initializing a Kronotop cluster\n\nBefore using Kronotop in your project, you first need to initialize the cluster. `KR.ADMIN INITIALIZE-CLUSTER` command\ncreates\nthe cluster's layout on the FoundationDB and initializes the cluster:\n\n```\n127.0.0.1:3320\u003e KR.ADMIN INITIALIZE-CLUSTER\nOK\n```\n\nThen, we must set the shard's primary ownership and make the shards operable. Currently, we only have a running Kronotop\ninstance in the cluster. It's good enough for demonstration purposes. We can assign all shards to this member.\n\nFirst, we should run `KR.ADMIN DESCRIBE-MEMBER` command to learn id of the current member:\n\n```\n127.0.0.1:3320\u003e KR.ADMIN DESCRIBE-MEMBER\n1# member_id =\u003e a0dc14d811a285834c187ddc20549de7c1c1a381\n2# status =\u003e RUNNING\n3# process_id =\u003e AAAOz0CfYCoAAAAA\n4# external_host =\u003e 127.0.0.1\n5# external_port =\u003e (integer) 5484\n6# internal_host =\u003e 127.0.0.1\n7# internal_port =\u003e (integer) 3320\n8# latest_heartbeat =\u003e (integer) 8227\n```\n\nWe need `member_id` from this response. The following command sets the primary owner of all Redis shards;\n\n```\n127.0.0.1:3320\u003e KR.ADMIN ROUTE SET PRIMARY REDIS * a0dc14d811a285834c187ddc20549de7c1c1a381\nOK\n```\n\nNow we are ready to make our all Redis shards writable:\n\n```\n127.0.0.1:3320\u003e KR.ADMIN SET-SHARD-STATUS REDIS * READWRITE\nOK\n```\n\nIf everything is okay, we can start using the newly formed Kronotop cluster:\n\n```\nredis-cli -p 5484 -c\n127.0.0.1:5484\u003e SET mykey \"Hello\"\nOK\n127.0.0.1:5484\u003e GET mykey\n\"Hello\"\n```\n\nAll in-memory data will be persisted and replicated by the storage engine. See [Storage Engine](#storage-engine) section\nfor the details.\n\n## Redis compatibility\n\nKronotop uses RESP3 as the client protocol. The reasoning behind this is simple: there are many high-quality Redis\nclient implementations\nin all languages, and almost everyone has some experience with Redis.\n\nDespite the main focus on building a transactional document database using FoundationDB as a metadata store,\nimplementing\nthe most common Redis data structures is on the roadmap. Currently, Kronotop has already partial support for *String*\nand *Hash*\ndata structures.\n\n## Support\n\nPlease join [Discord channel](https://discord.gg/Nyy4Afpr) for instant chat or create an Issue or Discussion on GitHub.\n\nFor invoiced sponsoring/support contracts, please contact us at *burak {dot} sezer {at} kronotop {dot} com*.\n\n## Features\n\n### Transaction management\n\nKronotop exposes the FoundationDB API to Redis clients. This section explains transaction management commands.\n\n*Note that not all parts of the FoundationDB API are implemented yet.*\n\n#### BEGIN\n\n`BEGIN` creates a new transaction and set it to the current session.\n\n**Example:**\n\n```\n127.0.0.1:5484\u003e BEGIN\nOK\n```\n\nIf there is another transaction in progress in the current session, it returns a `TRANSACTION` error message.\n\n```\n127.0.0.1:5484\u003e BEGIN\n(error) TRANSACTION there is already a transaction in progress.\n```\n\n#### COMMIT\n\n`COMMIT` commits changes to the database.\n\n**Example:**\n\n```\n127.0.0.1:5484\u003e COMMIT\nOK\n```\n\nFoundationDB currently does not support transactions running for over five seconds. If the transaction is too old,\nit returns `TRANSACTIONOLD` error.\n\n```\n127.0.0.1:5484\u003e COMMIT\n(error) TRANSACTIONOLD transaction is too old to perform reads or be committed\n```\n\nIf there is no transaction in progress in the current session, it returns `TRANSACTION` error.\n\n```\n127.0.0.1:5484\u003e COMMIT\n(error) TRANSACTION there is no transaction in progress.\n```\n\n#### ROLLBACK\n\n`ROLLBACK` cancels the current session's in-progress transaction.\n\n**Example:**\n\n```\n127.0.0.1:5484\u003e ROLLBACK\nOK\n```\n\nIf no transaction is in progress in the current session, it returns a `TRANSACTION` error message.\n\n```\n127.0.0.1:5484\u003e ROLLBACK\n(error) TRANSACTION there is no transaction in progress.\n```\n\n#### GETAPPROXIMATESIZE\n\n`GETAPPROXIMATESIZE` returns the approximated size of the commit, which is the summation of mutations, read conflict\nranges,\nand write conflict ranges. This can be called multiple times before a transaction commit.\n\n```\n127.0.0.1:5484\u003e GETAPPROXIMATESIZE\n(integer) 619\n```\n\n#### GETREADVERSION\n\n`GETREADVERSION` returns the version at which the reads for the in-progress transaction will access the database.\n\n```\n127.0.0.1:5484\u003e GETREADVERSION\n16275608010704\n```\n\n#### SNAPSHOTREAD\n\n`SNAPSHOTREAD ON|OFF` enables or disables snapshot reads for the in-progess transaction.\n\nIn the FoundationDB context, snapshots a special-purpose, read-only view of the database. Reads done through this\ninterface\nare known as \"snapshot reads.\" Snapshot reads selectively relax FoundationDB's isolation property, reducing [Transaction\nconflicts](https://apple.github.io/foundationdb/developer-guide.html#conflict-ranges) but making reasoning about\nconcurrency harder. For more information about how to use snapshot reads correctly,\nsee Using [snapshot reads](https://apple.github.io/foundationdb/developer-guide.html#snapshot-reads).\n\n**Example:**\n\n```\n127.0.0.1:5484\u003e SNAPSHOTREAD ON\nOK\n```\n\n### ZMap – Ordered Key-Value Store Backed by FoundationDB\n\nKronotop introduces a novel data structure called **ZMap**, which serves as a Redis-compatible proxy over *\n*FoundationDB’s\ntransactional key-value API**.\n\nUnder the hood, ZMap leverages **FoundationDB’s core data model** — a highly reliable, ordered key-value store.  \nAlso referred to as an **ordered associative array** or dictionary, this structure is composed of unique keys arranged\nin\nlexicographical order, each mapped to a corresponding value.\n\nBy exposing this powerful model through the familiar **RESP protocol**, ZMap allows developers to interact with\nFoundationDB\nin a simple, efficient, and idiomatic way — without requiring deep knowledge of FoundationDB's lower-level API.\n\nZMap forms the foundation for building richer abstractions and serves as a building block for higher-level features\nlike **namespaces**, **Buckets**, and transactional queries through **MQL**.\n\nSee the [Data Modeling](https://apple.github.io/foundationdb/data-modeling.html) section on FoundationDB documents.\n\n**One-Off Transactions**\n\nKronotop will create a new transaction and automatically commit changes to the database for the ad-hoc commands.\n\nIn other terms, you do not need to do this for every command:\n\n```\n127.0.0.1:5484\u003e BEGIN\nOK\n127.0.0.1:5484\u003e ZSET mykey \"Hello\"\nOK\n127.0.0.1:5484\u003e COMMIT\nOK\n```\n\nOne-off transaction feature is especially useful for running commands in CLI.\n\n**ZMap and Namespaces**\n\nA namespace prefixes all data stored in a ZMap. The current namespace can be inspected by running the following command:\n\n```\n127.0.0.1:5484\u003e NAMESPACE CURRENT\nglobal\n```\n\n`global` is the default namespace. Namespaces create isolation between data structures. This is how it works for ZMap\n\n```\n127.0.0.1:5484\u003e NAMESPACE CURRENT\nglobal\n127.0.0.1:5484\u003e ZSET mykey \"Hello\"\nOK\n127.0.0.1:5484\u003e ZGET mykey\n\"Hello\"\n127.0.0.1:5484\u003e NAMESPACE CREATE global.child-namespace\nOK\n127.0.0.1:5484\u003e NAMESPACE USE global.child-namespace\nOK\n127.0.0.1:5484\u003e ZGET mykey\n(nil)\n```\n\nSee [Namespaces](#namespaces) section for further information.\n\n#### ZSET\n\n`ZSET` sets the value for a given key. This will not affect the database until `COMMIT` is called.\n\n**Example:**\n\n```\n127.0.0.1:5484\u003e ZSET mykey \"Hello\"\nOK\n```\n\n#### ZGET\n\n`ZGET` gets a value from the database. The call will return `nil` if the key is not present in the database.\n\n**Example:**\n\n```\n127.0.0.1:5484\u003e ZGET mykey\n\"Hello\"\n```\n\n#### ZGETKEY\n\n`ZGETKEY` returns the key referenced by the specified `KeySelector`.\n\nThe default key selector is `FIRST_GREATER_OR_EQUAL`, `KEY_SELECTOR` portion of the command is optional.\n\nAvailable key selectors:\n\n* `FIRST_GREATER_OR_EQUAL`,\n* `FIRST_GREATER_THAN`,\n* `LAST_LESS_THAN`,\n* `LAST_LESS_OR_EQUAL`\n\n**Example:**\n\n```\n127.0.0.1:5484\u003e zset key-0 value-0\nOK\n127.0.0.1:5484\u003e zset key-1 value-1\nOK\n127.0.0.1:5484\u003e zset key-2 value-2\nOK\n127.0.0.1:5484\u003e zset key-3 value-3\nOK\n127.0.0.1:5484\u003e ZGETKEY key-0 KEY_SELECTOR FIRST_GREATER_THAN\n\"key-1\"\n```\n\n#### ZGETRANGE\n\n`ZGETRANGE` gets an ordered range of keys and values from the database. The *begin* and *end* keys can be specified by\nkey selectors, with the begin `BEGIN_KEY_SELECTOR` inclusive and the end `END_KEY_SELECTOR` exclusive.\n\nThe default `BEGIN_KEY_SELECTOR` is `FIRST_GREATER_OR_EQUAL`.\nThe default `END_KEY_SELECTOR` is `FIRST_GREATER_THAN`.\n\nAvailable key selectors:\n\n* FIRST_GREATER_OR_EQUAL,\n* FIRST_GREATER_THAN,\n* LAST_LESS_THAN,\n* LAST_LESS_OR_EQUAL\n\nThe key selector section of this command is optional.\n\n**Example:***\n\n```\n127.0.0.1:5484\u003e ZGETRANGE key-0 key-3\n1) 1) \"key-0\"\n   2) \"value-0\"\n2) 1) \"key-1\"\n   2) \"value-1\"\n3) 1) \"key-2\"\n   2) \"value-2\"\n```\n\nWith `LIMIT` parameter:\n\n```\n127.0.0.1:5484\u003e ZGETRANGE key-0 key-5 LIMIT 3\n1) 1) \"key-0\"\n   2) \"value-0\"\n2) 1) \"key-1\"\n   2) \"value-1\"\n3) 1) \"key-2\"\n   2) \"value-2\"\n```\n\nWith `LIMIT` and `REVERSE` parameters:\n\n```\n127.0.0.1:5484\u003e ZGETRANGE key-0 key-5 LIMIT 3 REVERSE\n1) 1) \"key-4\"\n   2) \"value-4\"\n2) 1) \"key-3\"\n   2) \"value-3\"\n3) 1) \"key-2\"\n   2) \"value-2\"\n```\n\nRange from beginning to end, get an ordered set or key/value pairs:\n\n```\n127.0.0.1:5484\u003e ZGETRANGE * *\n1) 1) \"key-0\"\n   2) \"value-0\"\n2) 1) \"key-1\"\n   2) \"value-1\"\n3) 1) \"key-2\"\n   2) \"value-2\"\n4) 1) \"key-3\"\n   2) \"value-3\"\n5) 1) \"key-4\"\n   2) \"value-4\"\n6) 1) \"key-5\"\n   2) \"value-5\"\n7) 1) \"key-6\"\n   2) \"value-6\"\n```\n\nExplicitly using key selectors, please note that you can use the key selectors individually.\n\n```\n127.0.0.1:5484\u003e ZGETRANGE key-2 key-5 BEGIN_KEY_SELECTOR FIRST_GREATER_THAN\n1) 1) \"key-3\"\n   2) \"value-3\"\n2) 1) \"key-4\"\n   2) \"value-4\"\n```\n\n#### ZGETRANGESIZE\n\n`ZGETRANGESIZE` gets an estimate for the number of bytes stored in the given range.\n\n```\n127.0.0.1:5484\u003e zgetrangesize key-0 key-9\n(integer) 0\n```\n\n_FoundationDB says:_\n\n\u003e Note: the estimated size is calculated based on the sampling done by FDB server. The sampling algorithm works roughly\n\u003e in\n\u003e this way: the larger the key-value pair is, the more likely it would be sampled and the more accurate its sampled size\n\u003e would be.\n\u003e And due to that reason, it is recommended to use this API to query against large ranges for accuracy considerations.\n\u003e For a rough reference, if the returned size is larger than 3MB, one can consider the size to be accurate.\n\n#### ZMUTATE\n\n`ZMUTATE` runs an atomic operation on the given key.\n\nAvailable mutation types:\n\n* `ADD`: Performs an addition of little-endian integers.\n* `APPEND_IF_FITS`: Appends param to the end of the existing value already in the database at the given key (or creates\n  the key and sets the value to param if the key is empty).\n* `BIT_AND`: Performs a bitwise and operation.\n* `BIT_OR`: Performs a bitwise or operation.\n* `BIT_XOR`: Performs a bitwise xor operation.\n* `BYTE_MAX`: Performs lexicographic comparison of byte strings.\n* `BYTE_MIN`: Performs lexicographic comparison of byte strings.\n* `COMPARE_AND_CLEAR`: Performs an atomic compare and clear operation.\n* `MAX`: Performs a little-endian comparison of byte strings.\n* `MIN`: Performs a little-endian comparison of byte strings.\n* `SET_VERSIONSTAMPED_KEY`: Transforms key using a versionstamp for the transaction.\n* `SET_VERSIONSTAMPED_VALUE`: Transforms param using a versionstamp for the transaction.\n\n**Example:**\n\n```\n127.0.0.1:5484\u003e ZSET key-0 value-0\nOK\n127.0.0.1:5484\u003e ZMUTATE key-0 value COMPARE_AND_CLEAR\nOK\n127.0.0.1:5484\u003e ZGET key-0\n\"value-0\"\n127.0.0.1:5484\u003e ZMUTATE key-0 value-0 COMPARE_AND_CLEAR\nOK\n127.0.0.1:5484\u003e ZGET key-0\n(nil)\n```\n\n#### ZDEL\n\n`ZDEL` clears a given key from the database. This will not affect the database until `COMMIT` is called.\n\n**Example:**\n\n```\n127.0.0.1:5484\u003e ZDEL mykey\nOK\n```\n\n#### ZDELRANGE\n\n`ZDELRANGE` clears the keys in the given range. The *begin* is inclusive, *end* is exclusive.\n\n**Example:**\n\n```\n127.0.0.1:5484\u003e ZDELRANGE key-1 key-4\nOK\n127.0.0.1:5484\u003e ZGETRANGE * *\n1) 1) \"key-0\"\n   2) \"value-0\"\n2) 1) \"key-4\"\n   2) \"value-4\"\n3) 1) \"key-5\"\n   2) \"value-5\"\n4) 1) \"key-6\"\n   2) \"value-6\"\n```\n\nUsing `*` asterisk character to set a boundary:\n\nWipe out all keys in the current namespace:\n\n```\n127.0.0.1:5484\u003e ZDELRANGE * *\nOK\n127.0.0.1:5484\u003e ZGETRANGE * *\n(empty array)\n```\n\nClear all keys from the beginning to `key-3`:\n\n```\n127.0.0.1:5484\u003e ZDELRANGE * key-3\nOK\n127.0.0.1:5484\u003e ZGETRANGE * *\n1) 1) \"key-3\"\n   2) \"value-3\"\n2) 1) \"key-4\"\n   2) \"value-4\"\n3) 1) \"key-5\"\n   2) \"value-5\"\n```\n\nClear all keys from `key-3` to end of the range:\n\n```\n127.0.0.1:5484\u003e ZDELRANGE key-3 *\nOK\n127.0.0.1:5484\u003e ZGETRANGE * *\n1) 1) \"key-0\"\n   2) \"value-0\"\n2) 1) \"key-1\"\n   2) \"value-1\"\n3) 1) \"key-2\"\n   2) \"value-2\"\n```\n\n### Namespaces\n\nNamespace is a thin layer around FoundationDB's\npowerful [directory](https://apple.github.io/foundationdb/developer-guide.html#directories) concept. Namespaces are a\nrecommended approach for administering applications.\nEach application should create or open at least one directory to manage its subspaces. Namespaces are identified by\nhierarchical paths analogous to the paths in a Unix-like file system.\n\nThe hierarchy between directories is denoted by joining them with dot character. Let's assume that you have different\nmicroservices and want to isolate their databases. You can create a namespace for each microservice under the\n`production` namespace.\n\nIf you have three microservices named `users`, `orders` and `products`, your namespace hierarchy might look like the\nfollowing:\n\n* `production.users`\n* `production.orders`\n* `production.products`\n\nAll data structures used by these namespaces will be isolated.\n\n**Note:** Redis data structures are not stored under namespaces. Currently, namespaces cover only ZMap data structure.\n\n#### NAMESPACE CREATE\n\n`NAMESPACE CREATE` creates a new namespace with the given hierarchy.\n\n**Example:**\n\n```\n127.0.0.1:5484\u003e NAMESPACE CREATE global.users \n```\n\n#### NAMESPACE REMOVE\n\n`NAMESPACE REMOVE` removes the given namespace hierarchy. It's the equivalent of `DROP DATABASE` command in other\ndatabases.\nSo you should be careful when start typing this command. The result is irreversible.\n\n**Example:**\n\n```\n127.0.0.1:5484\u003e NAMESPACE REMOVE global.users\nOK \n```\n\nYou cannot remove the default namespace:\n\n```\n127.0.0.1:5484\u003e NAMESPACE REMOVE global\n(error) ERR Cannot remove the default namespace: 'global'\n```\n\n#### NAMESPACE CURRENT\n\n`NAMESPACE CURRENT` command returns the current namespace in use for the session. The default namespace is in use if the\nclient doesn't set a different namespace by calling `NAMESPACE USE` command.\n\n**Example:**\n\n```\n127.0.0.1:5484\u003e NAMESPACE CURRENT\nglobal \n```\n\n#### NAMESPACE USE\n\n`NAMESPACE USE` sets an existing namespace to be used by the session.\n\n**Example:**\n\n```\n127.0.0.1:5484\u003e NAMESPACE USE global.users\nOK \n```\n\nIt returns `NOSUCHNAMESPACE` error if the namespace doesn't exist:\n\n```\n127.0.0.1:5484\u003e namespace use global.clients\n(error) NOSUCHNAMESPACE No such namespace: global.clients\n```\n\n#### NAMESPACE EXISTS\n\n`NAMESPACE EXISTS` checks a namespace whether exists or not.\n\n**Example:**\n\n```\n127.0.0.1:5484\u003e NAMESPACE EXISTS global.users\n(integer) 1\n```\n\nIt returns `1` for existing namespaces and `0` for non-existing ones.\n\n#### NAMESPACE LIST\n\n`NAMESPACE LIST` lists the namespaces under the given hierarchy.\n\n**Example:**\n\n```\n127.0.0.1:5484\u003e NAMESPACE LIST\n1) global\n```\n\nIt can take an optional parameter of namespace hierarchy.\n\n```\n127.0.0.1:5484\u003e NAMESPACE LIST global\n1) users\n```\n\nIt returns `NOSUCHNAMESPACE` error if the given hierarchy is invalid:\n\n```\n127.0.0.1:5484\u003e NAMESPACE LIST global.clients\n(error) NOSUCHNAMESPACE No such namespace: global.clients\n```\n\n#### NAMESPACE MOVE\n\n`NAMESPACE MOVE` moves the rightmost namespace to another location in the given hierarchy.\n\n**Example:**\n\n```\n127.0.0.1:5484\u003e NAMESPACE MOVE global.users staging.users\nOK\n```\n\nLet's check the result:\n\n```\n127.0.0.1:5484\u003e NAMESPACE LIST global\n(empty array)\n127.0.0.1:5484\u003e NAMESPACE LIST staging\n1) users\n```\n\n## Management\n\nThis section defines commands to manage a Kronotop cluster and database sessions.\n\n### Session\n\nKronotop provides a bunch of commands to manage database sessions. The following attributes are set by default:\n\n| attribute        | type    | scope  | description                                                              | default | available values |\n|------------------|---------|--------|--------------------------------------------------------------------------|---------|------------------|\n| reply_type       | enum    | Bucket | Data interchange format for the replies                                  | BSON    | BSON, JSON       |\n| input_type       | enum    | Bucket | Data interchange format for the inputs                                   | BSON    | BSON, JSON       |\n| limit            | integer | Bucket | Maximum entries returned per query response                              | 100     |                  |\n| pin_read_version | boolean | Bucket | Reuse the initial read version for all subsequent `BUCKET.ADVANCE` calls | true    | true, false      |\n\n#### SESSION.ATTRIBUTE LIST\n\n`SESSION.ATTRIBUTE LIST` lists all attributes with their current values used by the session.\n\n```\n127.0.0.1:5484\u003e SESSION.ATTRIBUTE LIST\n1# reply_type =\u003e bson\n2# input_type =\u003e bson\n3# limit =\u003e (integer) 100\n4# pin_read_version =\u003e (true)\n```\n\n#### SESSION.ATTRIBUTE SET\n\n`SESSION.ATTRIBUTE SET` sets a value to an attribute.\n\n```\n127.0.0.1:5484\u003e SESSION.ATTRIBUTE SET reply_type JSON\nOK\n```\n\nA random value cannot be set to an attribute, if its type is `enum`.\n\n```\n127.0.0.1:5484\u003e SESSION.ATTRIBUTE SET reply_type some-value\n(error) ERR Invalid reply type: some-value\n```\n\nIt's not possible to set an attribute if it's not defined by Kronotop:\n\n```\n127.0.0.1:5484\u003e SESSION.ATTRIBUTE set some-attribute value\n(error) ERR Invalid session attribute: 'some-attribute'\n```\n\n## Documentation\n\n* [Storage Engine](docs/volume/volume.md)\n* [Why Kronotop Runs on the Java Platform](docs/why-java-platform.md)\n\n## License\n\nKronotop is mostly licensed under the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0), which is a \npermissive and OSI-approved open source license.\n\nHowever, one of Kronotop’s core components — the **Bucket** package — is licensed under the [Business Source License 1.1](kronotop/src/main/java/com/kronotop/bucket/LICENSE.txt).\nThis license allows full access to the source code and free usage for development and testing. After a **five-year change date**, \nthe Bucket module will automatically be re-licensed under Apache 2.0.\n\n### Why BSL?\n\nWe love open source, and we want Kronotop to be widely used and improved by the community. But we also want to ensure \nthat **cloud providers and hosting platforms can't repackage Kronotop as a managed database service without contributing back**.\n\nTo protect the long-term sustainability of the project, the Bucket package includes a restriction: **It cannot be used to offer a \nDatabase-as-a-Service (DBaaS) or similar hosted product** without a separate commercial agreement.\n\nThis restriction only applies to **offering Kronotop itself as a database service to third parties**.  \nYou are free to use Kronotop (including the Bucket module) in your own apps, internal systems, and commercial products.\n\nFor more details, see our [additional use grant](kronotop/src/main/java/com/kronotop/bucket/LICENSE.txt) or contact us at\n*burak {dot} sezer {at} kronotop {dot} com* if you have questions or commercial use cases in mind.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkronotop%2Fkronotop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkronotop%2Fkronotop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkronotop%2Fkronotop/lists"}