Treds is a Radix Trie based data structure server that stores keys in sorted order, ensuring fast and efficient retrieval. A scan operation returns keys in their sorted sequence.
- Keys at root level having a common prefix can be queried optimally
SCANKEYS/SCANKVS/KEYS/KVS
commands returns the results in sorted order- Unlike Redis KEYS, Treds
KEYS
has cursor and matches any valid regex expression also it returns count number of data if data is there - Unlike Redis SCAN, Treds
SCAN
always returns count number of data if data is there. TredsSCAN
works on prefix only. - Unlike Redis ZRANGEBYLEX, Treds
ZRANGELEX
always returns data irrespective of score, basically data across different scores are returned - It has Sorted Maps instead of Sorted Sets. So we can create a Sorted Key/Value pair with associated with a score
- New command -
DELPREFIX
- Deletes all keys having a common prefix and returns number of keys deleted - New command -
LNGPREFIX
- Returns the key value pair in which key is the longest prefix of given string - Currently, it only has Key/Value store, Sorted Maps store, List store, Set store and Hash store and only supports strings/number as values
It is single threaded and has event loop. Implemented using modified Radix trees where leaf nodes are connected by Doubly Linked List in Radix Trie to facilitate the quick lookup of keys/values in sorted order. Doubly Linked List of leaf nodes are updated at the time of create/delete and update of keys optimally. This structure is similar to Prefix Hash Tree, but for Radix Tree and without converting keys to binary. Tree Map used to store score maps also are connected internally using Doubly Linked List using similar logic. For more details - check out the medium article
Both Treds and Redis are filled with 10 Million Keys in KeyValue Store and 10 Million Keys in a Sorted Map/Set respectively
Each key is of format user:%d
, so every key has prefix user:
The commands are run in Golang program and redirecting the output to a file go run main.go > out
.
For Redis setup see - Redis Prefix Bench Repo.
For Etcd setup see - Etcd Prefix Bench Repo
Treds Command -
scankeys 0 prefix 100000000000
Redis Command -
scan 0 match prefix count 100000000000
This graph shows the performance comparison between Treds - ScanKeys and Redis - Scan:
Treds Command -
scankvs 0 prefix 1000
Redis Command -
FT.SEARCH idx:user prefix SORTBY name LIMIT 0 1000
Prefix for redis command can be replaced by "User*", "User1*", "User10*" ... etc
This graph shows the performance comparison between Treds - ScanKVS and Redis FT.Search:
Treds Command -
zrangescorekeys key 0 max 0 100000000000 false
Redis Command -
zrangebyscore key 0 max
This graph shows the performance comparison between Treds - ZRangeScoreKeys and Redis - ZRangeByScore:
Treds Command -
scankeys 0 prefix 100000000000
Etcd Command -
etcdctl get prefix --prefix --keys-only
This graph shows the performance comparison between Treds - ScanKeys and Etcd get --prefix command:
PING
- Replies with aPONG
SET key value
- Sets a key value pairGET key
- Get a value for a keyDEL key
- Delete a keyMSET key1 value1 [key2 value2 key3 value3 ....]
- Set values for multiple keysMGET key1 [key2 key3 ....]
- Get values for multiple keysDELPREFIX prefix
- Delete all keys having a common prefix. Returns number of keys deletedLNGPREFIX string
- Returns the key value pair in which key is the longest prefix of given stringDBSIZE
- Get number of keys in the dbSCANKEYS cursor prefix count
- Returns the count number of keys matching prefix starting from an index in lex order only present in Key/Value Store. Last element is the next cursorSCANKVS cursor prefix count
- Returns the count number of keys/value pair in which keys match prefix starting from an index in lex order only present in Key/Value Store. Last element is the next cursorKEYS cursor regex count
- Returns count number of keys matching a regex in lex order starting with cursor. Count is optional. Last element is the next cursorKVS cursor regex count
- Returns count number of keys/values in which keys match a regex in lex order starting with cursor. Count is optional. Last element is the next cursorZADD key score member_key member_value [score member_key member_value ....]
- Add member_key with member value with score to a sorted map in keyZREM key member [member ...]
- Removes a member from sorted map in keyZCARD key
- Returns the count of key/value pairs in sorted map in keyZSCORE key member
- Returns the score of a member in sorted map in keyZRANGELEXKEYS key offset count withscore min max
- Returns the count number of keys are >= min and <= max starting from an index in a sorted map in lex order. WithScore can be true or falseZRANGELEXKVS key offset count withscore min max
- Returns the count number of key/value pair in which keys are >= min and <= max starting from an index in a sorted map in lex order. WithScore can be true or falseZRANGESCOREKEYS key min max offset count withscore
- Returns the count number of keys with the score between min/max in sorted order of score. WithScore can be true or falseZRANGESCOREKVS key min max offset count withscore
- Returns the count number of key/value pair with the score between min/max in sorted order of score. WithScore can be true or falseZREVRANGELEXKEYS key offset count withscore min max
- Returns the count number of keys are >= min and <= max starting from an index in a sorted map in reverse lex order. WithScore can be true or falseZREVRANGELEXKVS key offset count withscore min max
- Returns the count number of key/value pair in which keys are >= min and <= max starting from an index in a sorted map in reverse lex order. WithScore can be true or falseZREVRANGESCOREKEYS key min max offset count withscore
- Returns the count number of keys with the score between min/max in reverser sorted order of score. WithScore can be true or falseZREVRANGESCOREKVS key min max offset count withscore
- Returns the count number of key/value pair with the score between min/max in reverse sorted order of score. WithScore can be true or falseLPUSH key element [element ...]
- Adds elements to the left of list with keyRPUSH key element [element ...]
- Adds elements to the right of list with keyLPOP key count
- Removes count elements from left of list with key and returns the popped elementsRPOP key count
- Removes count elements from right of list with key and returns the popped elementsLREM key index
- Removes element at index of list with keyLSET key index element
- Sets an element at an index of a list with keyLRANGE key start stop
- Returns the elements from start index to stop index in the list with keyLLEN key
- Returns the length of list with keyLINDEX key index
- Returns the element at index of list with keySADD key member [member ...]
- Adds the members to a set with keySREM key member [member ...]
- Removes the members from a set with keySMEMBERS key
- Returns all members of a set with keySISMEMBER key member
- Return 1 if member is present in set with key, 0 otherwiseSCARD key
- Returns the size of the set with keySUNION key [key ...]
- Returns the union of sets with the give keysSINTER key [key ...]
- Returns the intersection of sets with the given keysSDIFF key [key ...]
- Returns the difference between the first set and all the successive sets.HSET key field value [field value ...]
- Sets field value pairs in the hash with keyHGET key field
- Returns the value present at field inside the hash at keyHGETALL key
- Returns all field value pairs inside the hash at the keyHLEN key
- Returns the size of hash at the keyHDEL key field [field ...]
- Deletes the fields present inside the hash at the keyHEXISTS key field
- Returns a true or false based on field is present in hash at key or notHKEYS key
- Returns all field present in the hash at keyHVALS key
- Returns all values present in the hash at keyFLUSHALL
- Deletes all keysEXPIRE key seconds
- Expire key after given secondsTTL key
- Returns the time in seconds remaining before key expires. -1 if key has no expiry, -2 if key is not present.SNAPSHOT
- Persist the Key Value Store data on disk immediately.RESTORE folder_path
- Restore the persisted snapshot on disk immediately.MULTI
- Starts a transactionEXEC
- Execute all commands in the transaction and close the transactionDISCARD
- Discard all commands in the transaction and close the transaction
To run server run the following command on repository root
export TREDS_PORT=7997
go run main.go -port 7997
Using docker
docker run -p 7997:7997 absolutelightning/treds
For CLI run the following command in the client
folder in the repo
cd ./client
export TREDS_PORT=7997
go run main.go -port 7997
Default Port of Treds is 7997
If port is set in env variable as well as flag, flag takes the precedence.
To build the binary for the treds server, run following command in repo root -
Binary named treds
will be generated in repo root.
make build
GOOS=linux GOARCH=arm64 make build
To build the binary for the treds cli, run following command in repo root -
Binary named treds-cli
will be generated in repo root.
make build-cli
GOOS=linux GOARCH=arm64 make build-cli
It is advised to run Treds cluster on production. To bootstrap a 3 node cluster, lets say we have 3 servers
Sever 1, Server 2 and Server 3
On Server 1 run
./treds -bind 0.0.0.0 -advertise ip-server-1 -servers 'uuid-server-2:ip-server-2:8300,uuid-server-3:ip-server-3:8300' -id uuid-server-1
On Server 2 run
./treds -bind 0.0.0.0 -advertise ip-server-2 -servers 'uuid-server-1:ip-server-1:8300,uuid-server-3:ip-server-3:8300' -id uuid-server-2
On Server 3 run
./treds -bind 0.0.0.0 -advertise ip-server-3 -servers 'uuid-server-1:ip-server-1:8300,uuid-server-2:ip-server-2:8300' -id uuid-server-3
- Currently only KV Store gets persisted in Snapshot, add support for other store.
- Authentication.
- Add RESP support.
- More Commands ...