The Swiss Army Knife and the Cookbook Part 1— My Favorite Tool in My Engineering Utility Belt

How Redis Helps With Application Database, Cache, and Message Broker Needs

Why I ❤️ Redis

I’ve wanted to write these two articles for a while because Redis is a tool I use over and over again. As a software engineer with over 20 years experience I’ve used Redis continually since 2011, you could consider me a fanboy, if you will.

What is Redis? Per the Redis documentation, Redis is an “open source in-memory data structure store, used as a database, cache and message broker”.

Redis’ popularity has skyrocketed in the past few years. Amazon Web Services (AWS) offers Redis as one of the technologies provided as AWS’ “Elasticache Redis” and Azure’s “Azure Cache”. It’s becoming ubiquitous whenever developers need a data store that’s hyper fast, which means you should know about it!

Want to read about Redis in my article: Caches are Key to Scaling? That article speaks to one use of Redis, the ‘cache’ concept which I go into more detail below. Continue to read THIS article to see different ways I’ve used Redis so you can understand where my “true believer” status comes from!

I first discovered Redis while building a cybersecurity product for a startup. The founder/CTO and I were both seasoned developers with different backgrounds and used different approaches and programming languages for the tools we were building. I leaned towards ‘higher level’ applications like APIs and web apps, he leaned towards backend services that were super fast and written in C. We stumbled on an early version of Redis and were able to easily use it for shared state and interprocess communication. Over time, we ended up adding dozens of small applications to our product, all centered around the power of Redis.

From the description of Redis above we can pull out three different capabilities:

Database Cache Message Broker

Those capabilities can show up in uses cases such as:

Throttling Counter

State Management

Component Configuration

Those are really generic descriptions of the capabilities, so let’s first start by breaking them down.

1. Database

Redis stores data and therefore can be called a database. Don’t get Redis confused with a traditional relational database management system (RDBMS) because Redis is very different. It is a “NoSQL” key-value database. In this technology approach, keys are the unique identifier that allows access to a value. The value associated with each key can be one of the following data types:

String (string, binary value, pseudo-integer, etc)

Lists (queue, stack, etc)

Sets (bags, intersections, etc)

Hashes (sub keys and values)

Sorted Sets (ranking)

Bitmaps and HyperLogLogs

2. Cache

Since Redis is an ‘in-memory’ database, it allows for incredibly fast access to data within the system, typically with sub-millisecond responses. Additionally, data is persisted to disk on a regular period by deltas making the cache durable. By limiting the size of the values in the key-value pair, Redis is able to store a ton of data in-memory. A natural use of readily available speed is to build a cache, like the “cache-aside” pattern. This style of cache allows for fast access to data by remembering the results of a database call instead of executing repeat queries against a persistent database, such as with Postgresql or Oracle. EHCache is a common method to cache calls in web APIs that uses the cache-aside/memoizing pattern in Java.

3. Message Broker

Redis provides a publish-subscribe capability allowing developers to use it as a language agnostic message broker! Ten years ago, when I was working at the startup I mentioned earlier, we built a highly specialized network security solution for capturing network data in PCAP format. Redis pub-sub gave us a message broker platform that allowed us to have C, Python, etc. build with very loose coupling.

The publish-subscribe pattern allowed each application to be ignorant of the other systems in the appliance; they only had to focus on Redis and know how to communicate over the pub-sub channels.

The Speed of Light

Redis is primarily known for its speed. Remember the chart that every developer needs to know? The one that shows how crazy fast memory access is compared to reading data off spinning media?

Image taken from Latency Numbers Every Programmer Should Know by Jonas Bonér — https://gist.github.com/jboner/2841832

This chart shows the astounding difference in pulling data from memory (250k ns) vs from disk (20ms, which is 80x longer than from in memory). This is the main cause for the incredible throughput for keys in Redis. Since all data is stored in memory, access is incredibly fast. If access is 80x faster than disk based storage, you can imagine that any operations here will be 80x faster.

Some of the most commonly used commands such as set , get , del , etc are amongst the fastest operations available in the system. These commands find one key in memory and operate on it. For computer science nerds like me this is O(1), meaning regardless of the size of the data set in Redis there will be a ‘fixed’ amount of work (1 unit) to perform these operations. Not all operations are O(1), but the most common ones are. Commands like keys are O(n), meaning the commands take more operations directly, and linearly, related to the number of items in the data set.

Redis has published a wide set of performance numbers here that I recommend you check out: https://redis.io/topics/benchmarks

Using the redis-benchmark tools, that article has an example that shows 72k transactions per second with 99.76% of transactions being sub-millisecond!

$ redis-benchmark -t set -r 100000 -n 1000000

====== SET ======

1000000 requests completed in 13.86 seconds

50 parallel clients

3 bytes payload

keep alive: 1 99.76% `<=` 1 milliseconds

99.98% `<=` 2 milliseconds

100.00% `<=` 3 milliseconds

100.00% `<=` 3 milliseconds

72144.87 requests per second

The reference point I regularly use is approximately 80,000 transactions per second. That’s amazing! Which means as a developer, I rarely worry about the latency of Redis (as long as I avoid scanning functions).

Loss of Memory

They say elephants never forget things. Redis shouldn’t forget things either, except when things go wrong. When using an in memory database, always make sure to follow best practices for staying safe.

What would happen if someone tripped over a power plug when all your data is only in memory? Exactly, it would go away and not come back. Can your application handle that? If you’re building a cache, then sure, expect some temporary slowness in your application, but it’ll come back as data gets reloaded! However, if you’re building a shared database for user transactions, you’re going to have a bunch of support calls if all the users lose their work before they’re able to checkout.

Thankfully Redis is able to persist its state to disk. Redis has an RDB (Redis Database) file format that can be used to periodically save data to permanent storage.

First, in the configuration file, you can make a setting like this in the redis.conf file:

save 900 1

save 300 10

save 60 10000

This tells Redis to save the database to disk if the following scenarios are met:

If after 900 seconds and 1 key has changed, save to disk.

If after 300 seconds and at least 10 keys are changed, save to disk.

If after 60 seconds 10,000 keys have changed, save to disk.

Choose the numbers correctly. Depending on the total size of your database and how ‘up to date’ it needs to be, you can change these configurations.

Alternatively, Redis exposes two commands to allow a forced persistence — save and bgsave are synchronous/asynchronous commands to fork the process (if async) and write the keys to disk. Know your data, you’ll need to determine comfort level on how much data can be lost if an emergency happens.

Redis the Swiss Army Knife

Once you realize the benefits and potential pitfalls of Redis, you’ll most likely come to the same conclusion that I have: Redis is a tool you need to understand. My goal in this love letter is to convince you to give Redis a try, hopefully you’ll soon realize how versatile and stable it can be.

The Swiss Army Knife is the common symbol of a universal tool; I continually rely on Redis in the same way for many of the applications that I build or architect. The interfaces are simple and the implementation is so stable; I know it’s not going to be an architectural component I have to worry about. In the next post I’m going to build some recipes — cookbook style — to show common patterns or uses that I’ve leveraged in my work with Redis. Stay tuned for Part 2: The Redis Cookbook — Recipes for Common Redis Patterns.

Links

Redis: https://redis.io

Python Redis: https://pypi.org/project/redis/

AWS Elasticache: https://aws.amazon.com/elasticache/redis/

Azure Cache: https://azure.microsoft.com/en-us/services/cache/

EHCache: https://www.ehcache.org/