Building a Simple Redis‑Like Service with RocksDB and RestExpress (kedis)

This tutorial demonstrates how to use Facebook’s RocksDB storage engine together with the Netty‑based RestExpress HTTP container to create a lightweight Redis‑style key/value service called kedis, covering project setup, core API implementation, route configuration, building, launching, and basic curl interactions.

Architect's Tech Stack
Architect's Tech Stack
Architect's Tech Stack
Building a Simple Redis‑Like Service with RocksDB and RestExpress (kedis)

In this article the author introduces two open‑source projects—Facebook’s RocksDB and the Netty‑based HTTP container RestExpress—and shows how to combine them to build a simple Redis‑like key/value service named “kedis”.

RocksDB is a high‑performance embedded key/value storage engine written in C++ with a Java wrapper (RocksJava). It supports various storage media, offers configurable compression, and is used in MyRocks, TiKV, and other systems.

RestExpress is a lightweight Java HTTP server built on Netty that provides non‑blocking I/O and easy routing for RESTful APIs.

The implementation creates a Java main class that loads RocksDB, defines a KedisCore class to wrap basic put/get operations, and configures RestExpress routes for /put and /get endpoints.

<ol><li><p><span style="color: rgb(74, 74, 74); display: block; line-height: 22px; font-size: 14px !important"><span style="line-height: 22px; display: block"><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important"><span style="color: rgb(153, 153, 153); line-height: 20px; font-size: 13px !important">/**</span></code></span></span></p></li><li><p><span style="color: rgb(74, 74, 74); display: block; line-height: 22px; font-size: 14px !important"><span style="line-height: 22px; display: block"><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important"><span style="color: rgb(153, 153, 153); line-height: 20px; font-size: 13px !important"> * @author: kl @kailing.pub</span></code></span></span></p></li><li><p><span style="color: rgb(74, 74, 74); display: block; line-height: 22px; font-size: 14px !important"><span style="line-height: 22px; display: block"><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important"><span style="color: rgb(153, 153, 153); line-height: 20px; font-size: 13px !important"> * @date: 2019/4/12</span></code></span></span></p></li><li><p><span style="color: rgb(74, 74, 74); display: block; line-height: 22px; font-size: 14px !important"><span style="line-height: 22px; display: block"><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important"><span style="color: rgb(153, 153, 153); line-height: 20px; font-size: 13px !important"> */</span></code></span></span></p></li><li><p><span style="color: rgb(74, 74, 74); display: block; line-height: 22px; font-size: 14px !important"><span style="line-height: 22px; display: block"><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important"><span style="color: rgb(204, 153, 204); line-height: 20px; font-size: 13px !important">public</span><span style="color: rgb(204, 153, 204); line-height: 20px; font-size: 13px !important">class</span><span style="color: rgb(102, 153, 204); line-height: 20px; font-size: 13px !important">Main</span><span style="color: rgb(204, 204, 204); line-height: 20px; font-size: 13px !important">{</span></code></span></span></p></li><li><p><br/></p></li><li><p><span style="color: rgb(74, 74, 74); display: block; line-height: 22px; font-size: 14px !important"><span style="line-height: 22px; display: block"><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important"><span style="color: rgb(204, 153, 204); line-height: 20px; font-size: 13px !important">public</span><span style="color: rgb(204, 153, 204); line-height: 20px; font-size: 13px !important">static</span><span style="color: rgb(204, 153, 204); line-height: 20px; font-size: 13px !important">void</span><span style="color: rgb(204, 204, 204); line-height: 20px; font-size: 13px !important"> main</span><span style="color: rgb(204, 204, 204); line-height: 20px; font-size: 13px !important"> (</span><span style="color: rgb(102, 153, 204); line-height: 20px; font-size: 13px !important">String</span><span style="color: rgb(204, 204, 204); line-height: 20px; font-size: 13px !important">[] args</span><span style="color: rgb(204, 204, 204); line-height: 20px; font-size: 13px !important">) {</span></code></span></span></p></li><li><p><span style="color: rgb(74, 74, 74); display: block; line-height: 22px; font-size: 14px !important"><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important"><span style="color: rgb(204, 153, 204); line-height: 20px; font-size: 13px !important">Configs</span> configs = <span style="color: rgb(204, 153, 204); line-height: 20px; font-size: 13px !important">new</span> Configs();</code></span></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">configs.fromArgs(args);</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">RestExpress server = <span style="color: rgb(204, 153, 204); line-height: 20px; font-size: 13px !important">new</span> RestExpress();</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">server.setName("kedis-server");</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">server.setBaseUrl("http://localhost:" + configs.getPort());</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">KedisCore core = <span style="color: rgb(204, 153, 204); line-height: 20px; font-size: 13px !important">new</span> KedisCore(configs.getDbPath());</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">Routes.define(server, core);</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">server.bind(configs.getPort());</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">server.awaitShutdown();</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">}</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">}</code></p></li></ol>
<ol><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">public class KedisCore {</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">private RocksDB db;</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">public KedisCore(String path) {</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">RocksDB.loadLibrary();</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">Options options = new Options().setCreateIfMissing(true);</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">this.db = RocksDB.open(options, path);</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">} catch (RocksDBException ex) { ex.printStackTrace(); }</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">public String put(Request request, Response response) throws Exception {</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">Map<String,String> map = request.getQueryStringMap();</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">String key = map.get("key");</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">String value = map.get("value");</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">db.put(key.getBytes(), value.getBytes());</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">return "ok";</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">}</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">public String get(Request request, Response response) throws Exception {</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">Map<String,String> map = request.getQueryStringMap();</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">String key = map.get("key");</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">byte[] values = db.get(key.getBytes());</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">if (values != null) { return new String(values, "utf-8"); } else { return null; }</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">}</code></p></li></ol>
<ol><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">public abstract class Routes {</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">public static void define(RestExpress server, KedisCore core) {</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">server.uri("/put", core).action("put", HttpMethod.GET).noSerialization();</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">server.uri("/get", core).action("get", HttpMethod.GET).noSerialization();</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">}</code></p></li><li><p><code style="display: flex; line-height: 12px; font-size: 10px; font-family: inherit !important">}</code></p></li></ol>

After building the project with Maven, start the service with java -jar kedis-1.0.jar --port 8081. Insert a key/value pair using curl http://localhost:8081/put?key=name&value=ckl and retrieve it with curl http://localhost:8081/get?key=name.

The author highlights RocksDB’s tiny footprint (around 10 MB) and powerful features that make it suitable as an embedded storage engine, while RestExpress offers a full‑featured yet lightweight HTTP layer ideal for small tools.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Backend DevelopmentRocksDBkey-value storeRestExpress
Architect's Tech Stack
Written by

Architect's Tech Stack

Java backend, microservices, distributed systems, containerized programming, and more.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.