Best Practices

A few options exist for storing JSON in Redis. The most basic form is to take a pre-serialized and simply store it at a specific key:

> SET car "{\"colour\":\"blue\",\"make\":\"saab\",\"model\":93,\"features\":[\"powerlocks\",\"moonroof\"]}"
OK
> GET car
"{\"colour\":\"blue\",\"make\":\"saab\",\"model\":93,\"features\":[\"powerlocks\",\"moonroof\"]}"

This, while seemingly simple, has some very real drawbacks:

  • The serialization takes client computational resources during read and write.
  • The JSON format adds size to the data
  • Redis has only indirect ways to manipulate the actual JSON data.

The first couple of points may be negligible on small amounts of data, but can definitely add up. Especially with multi-megabyte JSON stores. The third point is more critical, however.

Prior to Redis 4.0, the only method to work with JSON data inside of Redis was to use a Lua script through the cjson module. This partially solved the JSON problem although it still was a bottleneck and added the extra burden of learning Lua.

Worse yet, many applications would just GET the entire JSON string, deserialize it, manipulate it, re-serialize and SET it again at the application. This is an anti-pattern. There is a very real risk of losing data with this method. Take for example:

ANTI-PATTERN: DO NOT USE
Application Instance #1 Application Instance #2
1
> GET my-car
2
[deserialize, change colour to β€˜red’, and re-serialize]
> GET my-car
3
> SET my-car [new value from instance #1]
[deserialize, change model to β€˜95’, and re-serialize]
4
> SET my-car [new value from instance #2]
5
> GET my-car 
  ...

The results from line 5 would only show the update from instance #2 and setting the colour in instance #1 would be lost.

Redis 4.0+ have the ability to use modules. ReJSON is a module that provides a special datatype and direct manipulation commands. ReJSON stores the data in a binary format which removes the storage overhead from JSON, provides quicker access to elements without de-/re-serialization times.

To use ReJSON you need to install it in your Redis server or enable it in your Redis Enterprise database.

Taking our previous example, using ReJSON instead of storing JSON as a string would look like this:

 

Application Instance #1 Application Instance #2
1
> JSON.SET car2 . '{"colour":"blue", "make":"saab", "model":93, "features" :[ "powerlocks", "moonroof" ]}'
2
> JSON.SET car2 colour '"red"'
3
> JSON.SET car2 model '95'
4
> JSON.GET car2 . 

"{ \"colour\":\"blue\", \"make\":\"saab\", \"model\":95, \"features\": [\"powerlocks\", \"moonroof\"]}"

ReJSON provides a generally safer, faster, and more intuitive way of manipulating JSON in your datastore, especially where sub-element atomic manipulation is needed.