How to get the most out of your Keys in Redis

Redis is sometimes a misunderstood tool, simply because it hides an amazing powerhouse of features behind the premise of in-memory key-value store.

At a first glance, based on that description, Redis is nothing more than a glorified hashmap (or dictionary, depending on your choice of language) in memory, and if you don’t really have a need for one of those, you’re not going to give it a second thought.

But what if I told you, there are some very interesting hidden gems in that tool? In this article I want to cover a few techniques that I’ve used in the past get the most out of my Redis.

The power of a good name

I think this is probably the simplest tip and yet, the most powerful of the ones I’m going to be covering. You could even say this trick is hiding in plain sight, since it’s all about the way you name your keys.

You see, this amazing “in-memory dictionary” is incredibly optimized to deal with keys, in the sense that it can access them and even set them using O(1) operations, and it can even list them with wildcard support in O(N) time. That alone gives you a very interesting set of possibilities when picking your key’s names, let me explain:

Saving your user’s last login time

This is a classic example where using your SQL database to update such a volatile value is a bit of an overkill, specially if you have Redis at hand.

You can create a single key per user, called: [USERID]_last_login and that alone will let you access and set the value in O(1) time!

You can set it simply with a SET [USERID]_last_login "2018-06-28 13:41:22" which will set the key if it already exists and create it if it doesn’t in constant time. And you can get it with a simple GET [USERID]_last_login in the same amount of time.

Bonus note: What if for some reason, in your platform users tend to not login often? How do you get rid of the clutter all these single-keys cause? You can set a TTL (Time-To-Live) for your keys and Redis will take care of removing them for you! Simply do: EXPIRE YOUR_KEY_NAME YOUR_TTL_IN_SECONDS, for example: EXPIRE 23099273_last_login 3600 and you’re making sure the key is auto-removed if there is no activity for over an hour, otherwise setting the key will reset the expire, so you’re good there too!

The power of wildcards

Let’s say that you’re saving the last-login time for your users like I showed you, and that you have a TTL on those keys of 1 hour, you can simply get the list of logged-in users with a single KEYS call.

For example: KEYS *_last_login will return the list of all keys (hence, all active users in the last hour) in O(N) time. Given a high enough number of keys in your database, using KEYS might not be the best solution, but there are alternatives in Redis’ docs that are just as good or even better. This one is simply a quick one that drives amazing results, specially if you’re not dealing with too many records.

Using Redis for relational data

What? Yeah well, you obviously need to be careful with this one, but if you happen to have different sets of information that are of a volatile nature (or put another way, there is no problem if you happen to lose it) and can be related to a single entity, you could play the relational game in Redis too, by correctly naming your keys.

For example: let’s add the amount of likes user profiles have on your system, to Redis, that way we’re now dealing with the last login time and the new piece of information: an integer value that can potentially change quickly (so storing it and retrieving it from Redis makes sense). Mixing the above two examples you get that:

  • Naming your keys as [USERID]_last_login and [USERID]_profile_likes gives you the ability to link those two sets of data and keep the O(1) time for the SET and GET commands.

  • For a given user, you can simply do a KEYS [USERID]* to discover all the information that you have on him/her.

Using Redis to schedule recurrent tasks

How many times did you have a recurrent task inside the data-flow of your platform that you ended-up turning into a Cron Job? Be honest with me here, it’s just between you and me, I won’t tell anyone…

That is a classical solution that most of us have relied on at one point of our careers, and honestly, I hate it, because you end-up breaking you platform’s internal logic and workflow to add support for this recurrent task that needs to be done every X amount of minutes (or hours, or seconds, you name it). You usually end-up creating a script that’ll run your code, and setting up a Cron Job (or some other fancy version of it) to execute it.

What if, you could simply add a bit of logic to your system, to simply stay waiting for a notification telling it to run? Redis can help!

Keyspace notifications is one of my favorite features in Redis, this allows you to listen for changes in specific keys, you simply register your callbacks to get notified once something happens and then you decide what to do with that information. So you can use this concept and the TTL I described above to react every time a key is auto-deleted.

By setting your keys with a TTL equal to the interval of execution, you can react to their “deaths” by creating them again (so the loop continues), and executing your recurring code. That’s it, you keep your internal logic inside your application, and gain a higher level of control over when and how to execute the code.

Using Shadow Keys

This is a fancy name for a very simple trick, you see, building on top of what I’ve covered so far, expired key notifications carry the name of the key being removed, but not their value, and since it was just removed when you get notified you can’t really access that data.

Let’s say you want to save into your SQL database the updated number of likes for your user’s profile (again, building on top of the examples given so far), but only once the user has been out of the system for about an hour, you can’t do it by simply adding a TTL of 1 hour to your [USERID]_profile_likes key, because once that key expires, you’re done.

So what you do, is you create a “shadow key” that basically expires instead of your key, giving you the opportunity to grab the actual data you need, and then decide to delete the real key or not.

That’s about it for this list of tips, I hope at least one of them was useful for you and if you had ignored this wonderful NoSQL storage in the past, that you can reconsider it and give it a chance. It’s amazingly versatile, powerful and has clients in all major programming languages.

That’s about it for this list of tips, I hope at least one of them was useful for you and if you had ignored this wonderful NoSQL storage in the past, that you can reconsider it and give it a chance. It’s amazingly versatile, powerful and has clients in all major programming languages.