A minimal Redis-compatible TCP server written in Go.
make masterThe server listens on port 6379 by default. Override PORT to select
another port:
make master PORT=6380REDIS_ADDR may also set the listening address. When both are supplied,
PORT overrides the port in REDIS_ADDR.
Append-only persistence is disabled by default. Enable it with Redis-compatible startup flags:
go run ./cmd/api \
--appendonly yes \
--dir ./data \
--appenddirname appendonlydir \
--appendfilename appendonly.aof \
--appendfsync alwaysWhen enabled, the server creates the append-only directory, a manifest named
appendonly.aof.manifest, and an active incremental file. Successful write
commands are appended in RESP format before they are replicated or acknowledged
to the client. --appendfsync always synchronizes every append before the
command completes; the default policy is everysec. On restart, the server
reads the manifest-selected incremental file and replays every complete RESP
command in order before serving clients.
The available AOF settings are:
| Flag | Default | Purpose |
|---|---|---|
--dir |
current working directory | Parent directory for persistence data. |
--appendonly |
no |
Enables AOF when set to yes. |
--appenddirname |
appendonlydir |
Directory containing multipart AOF files. |
--appendfilename |
appendonly.aof |
Base name used for the manifest and initial incremental file. |
--appendfsync |
everysec |
Uses synchronous writes when set to always. |
Current AOF support does not rotate or rewrite files, or run a periodic
everysec sync.
In another terminal, run:
make clientThen try:
PING
ECHO hey
You should get:
PONG
hey
This server currently supports the following RESP2 commands. Command names are case-insensitive.
| Command | Syntax | Notes |
|---|---|---|
PING |
PING |
Returns PONG. |
ECHO |
ECHO message |
Returns message as a bulk string. |
INFO |
INFO [replication] |
Returns the server role, replication ID, and replication offset. |
REPLCONF |
REPLCONF option value |
Supports replication handshake and acknowledgement messages. |
PSYNC |
PSYNC replication-id offset |
Starts a full resynchronization and transfers an empty RDB snapshot. |
CONFIG |
CONFIG GET option |
Returns dir and AOF-related startup settings. |
SET |
SET key value [PX milliseconds] |
Stores a string value; PX sets an expiry. |
GET |
GET key |
Returns the string value or a null bulk string. |
TYPE |
TYPE key |
Returns the stored value type, or none for missing or expired keys. |
HSET |
HSET key field value [field value ...] |
Creates or updates hash fields; returns the number of newly added fields. |
HGET |
HGET key field |
Returns the field value or a null bulk string. |
HGETALL |
HGETALL key |
Returns all fields and values as a flat RESP array. |
LPUSH |
LPUSH key value [value ...] |
Prepends values to a list and returns its length. |
RPUSH |
RPUSH key value [value ...] |
Appends values to a list and returns its length. |
LLEN |
LLEN key |
Returns the list length. |
LPOP |
LPOP key [count] |
Removes and returns one value, or an array when count is supplied. |
LRANGE |
LRANGE key start stop |
Returns the inclusive list range. |
BLPOP |
BLPOP key timeout |
Blocks for one list key until a value is available or the timeout expires. |
XADD |
XADD stream-key id field value [field value ...] |
Appends an entry to a stream and returns its resolved ID. |
XREAD |
XREAD [BLOCK milliseconds] STREAMS stream-key [stream-key ...] id [id ...] |
Returns entries newer than the corresponding IDs, optionally waiting for them. |
XRANGE |
XRANGE stream-key start-id end-id |
Returns stream entries in the inclusive ID range. |
WAIT |
WAIT replicas timeout-milliseconds |
Waits for the requested number of replicas to acknowledge the latest write, or returns the acknowledged count when the timeout expires. |
Commands return a WRONGTYPE error when an existing key holds a value of a
different supported type. Expiry is checked lazily whenever a key is accessed.
Start a master on the default port:
make masterThen start one or more replicas on different ports:
make replica
make replica PORT=6381The replica port defaults to 6380, and replicas connect to
127.0.0.1:6379 by default. Override either address when needed:
make replica PORT=6380 MASTER_HOST=192.0.2.10 MASTER_PORT=6379At startup, a replica connects to its master, completes the Redis replication
handshake, consumes the full-resynchronization payload, and then applies
propagated write commands through the same serialized command event loop used
for client requests. A master broadcasts successful SET, XADD, HSET,
LPUSH, RPUSH, and LPOP commands to every connected replica.
Inspect the master's role and replication metadata:
make replication-infoCount replicas that respond to an acknowledgement request:
make replica-countWith the two replicas above, make replica-count prints 2. WAIT_TIMEOUT
controls how long the check waits in milliseconds and defaults to 100.
To send commands interactively, open a client connected to the master:
make clientAfter a write, WAIT requests acknowledgements from connected replicas. It
returns as soon as the requested replica count has processed the write, or
returns the count reached when the timeout expires:
SET greeting hello
WAIT 2 1000
A timeout of 0 waits indefinitely when acknowledgements are required.
- Full synchronization currently transfers an embedded empty RDB snapshot; it does not copy data that existed on the master before the replica connected.
- Replicas do not reconnect automatically when the master connection closes.
- Partial resynchronization and replication backlogs are not implemented.
XADD accepts explicit IDs in milliseconds-sequence form, such as 0-1,
and requires each new ID to be greater than the stream's current last ID. It
also supports milliseconds-* to generate the sequence number and * to
generate both components from the current Unix time in milliseconds. Generated
IDs remain strictly increasing when multiple entries share a millisecond or
when the system clock moves backward.
XRANGE returns matching stream entries in stream order. Each entry is a RESP
array containing its ID followed by an array of field-value pairs in their
original order.
Both bounds accept milliseconds-sequence IDs. The sequence may be omitted:
the start bound defaults to sequence 0, while the end bound defaults to the
largest sequence value. Use - for the beginning of the stream and + for
the end.
XRANGE stream-key - +
XRANGE stream-key 1526985054069 1526985054079
XRANGE stream-key 0-2 +
Missing streams and ranges without matching entries return an empty RESP array.
XREAD reads one or more streams after the supplied IDs. Its IDs are
exclusive: an entry is returned only when its ID is greater than the
corresponding ID in the command. Supply all stream keys first, followed by one
ID for each key.
XREAD STREAMS stream-key other-stream 0-1 0-2
The response contains one [stream-key, entries] array for each stream with
new entries, in the same order as the stream keys in the command. Each entry
uses the same [id, field-value-pairs] structure as XRANGE.
Add BLOCK milliseconds to wait only when no requested stream has newer
entries. If data is already available, XREAD returns immediately. A positive
timeout returns a RESP null array when it expires; BLOCK 0 waits
indefinitely until a matching XADD adds a new entry.
XREAD BLOCK 1000 STREAMS stream-key 0-1
XREAD BLOCK 0 STREAMS stream-key $
Use $ only for a blocking read's initial position. It resolves to the
stream's current last ID when the command is received, so the response
contains only entries appended afterwards. Subsequent reads should use the
last returned entry ID to avoid missing entries.