English | 中文
This is rotom, a high performance, low latency tiny Redis Server written in Go. It replicates the core event loop mechanism AeLoop in Redis based on I/O multiplexing.
- Implements the AeLoop single-threaded event loop from Redis using the epoll network model.
- Excellent optimization, achieving native Redis performance.
- Compatible with the Redis RESP protocol, allowing any Redis client to connected.
- Implements data structures String, Hash, Set, List, ZSet.
- Supports RDB & AOF.
- Supports 20+ commonly used commands.
AeLoop (Async Event Loop) is the core asynchronous event-driven mechanism in Redis, which mainly includes:
- FileEvent: Uses I/O multiplexing to handle read and write events on network sockets, categorized into
READABLEandWRITABLE. - TimeEvent: Handles tasks that need to be executed after a delay or periodically, such as expiring items every
100ms. - When events are ready, they are processed by callback functions bound to those events.
In rotom, the AeLoop event loop mechanism in Redis is replicated, specifically:
- When a new TCP connection arrives, the
AcceptHandlerobtains the socket fd and adds it to the event loop, registering a read event. - When the read event is ready,
ReadQueryFromClientreads buffered data intoqueryBuf. ProcessQueryBufparses and executes the corresponding commands fromqueryBuf.- The command execution result is saved, and the socket fd's write event is registered.
- When the write event is ready,
SendReplyToClientwrites all results back to the client. A write event may return multiple read event results at once. - Resources are released, and the process continues until the service is shut down.
Rotom has made several optimizations in data structures:
- dict: Rotom uses
stdmapas the db hash table, with built-in progressive rehashing. - hash: Based on
zipmapwith higher memory efficiency. - set: Uses
zipsetwhen the set is small andmapsetwhen it is large. - list: Uses a
quicklistbased onlistpackfor a doubly linked list. - zset: Uses
zipzsetwhen small andhash+skiplistwhen it is large.
Notably, zipmap and zipset are space-efficient data structures based on listpack, which is a new compressed list proposed by Redis to replace ziplist, supporting both forward and reverse traversal and solving the cascading update issue in ziplist.
The test will run rotom on the same machine with appendonly disabled, and use redis-benchmark tool to test the latency of different commands.
goos: linux
goarch: amd64
pkg: github.com/xgzlucario/rotom
cpu: 13th Gen Intel(R) Core(TM) i5-13600KF
- Support for LRU cache and memory eviction.
- Gradually rehashing in dict.
- RDB and AOF Rewrite.
Running Locally
First, clone the project to your local machine:
git clone https://github.com/xgzlucario/rotomEnsure your local Go environment is >= 1.22. In the project directory, run go run . to start the service, which listens on port 6379 by default:
$ go run .
2024-07-18 23:37:13 DBG
________ _____
___ __ \_______ /_____________ ___ Rotom 64 bit (amd64/linux)
__ /_/ / __ \ __/ __ \_ __ '__ \ Port: 6379, Pid: 15817
_ _, _// /_/ / /_ / /_/ / / / / / / Build:
/_/ |_| \____/\__/ \____//_/ /_/ /_/
2024-07-18 23:37:13 INF read config file config=config.json
2024-07-18 23:37:13 INF rotom server is ready to accept.
Running in a Container
Alternatively, you can run it in a container. First, build the Docker image by running make build-docker:
REPOSITORY TAG IMAGE ID CREATED SIZE
rotom latest 0cd91943967a 5 seconds ago 20.9MB
Then, start the container:
docker run --rm -p 6379:6379 --name rotom rotom:latest