Redis , Replace Keys with HSET?

Bill Inkoom
Hubtel Engineering
Published in
3 min readNov 30, 2020

--

Sometime after Redis came to the rescue (https://bit.ly/3mrGSdu), another chapter was opened in this journey of Redis. There was a need to store a key with an associated value which by definition resembles a simple set operation.


SET key value [EX seconds|PX milliseconds|KEEPTTL] [NX|XX] [GET]
Available since 1.0.0.Time complexity: O(1)Set key to hold the string value. If key already holds a value, it is overwritten, regardless of its type. Any previous time to live associated with the key is discarded on successful SET operation.https://redis.io/commands/set

Creating “top-level” keys comes with these advantages

  1. Redis does not support nested types in keys, which implies only a top-level key has the privilege of storing a data-type apart from string.
  2. Expirations are only defined on top level keys

This is as of the Redis version (5.0.0), maybe this might change in the future, however thats unlikely.This thread sheds more light on why this is so.

https://github.com/redis/redis/issues/242#issuecomment-3512819

However our request was simple, all we need is to store a key with an associate value, which implies HSET should be able to do this with ease.


HSET key field value [field value ...]
Available since 2.0.0.Time complexity: O(1) for each field/value pair added, so O(N) to add N field/value pairs when the command is called with multiple field/value pairs.Sets field in the hash stored at key to value. If key does not exist, a new key holding a hash is created. If field already exists in the hash, it is overwritten.As of Redis 4.0.0, HSET is variadic and allows for multiple field/value pairs.

In essence fields within HSET behave just like top-level keys, except they do not have the advantages discussed above (No expiration, only strings).


HGET key field
Available since 2.0.0.Time complexity: O(1)Returns the value associated with field in the hash stored at key.

Retrieving a field from an HSET has the same time complexity as retrieval with “top-level” key.

So whats the point here?

In an environment where the same Redis store is shared by multiple applications, if keys are not prefixed properly, you could have clashes which leads to the situation where other apps could overwrite data created by other applications. The remedy to this is obvious, prefix keys properly, to reduce this occurrence.

However instead of creating multiple keys for each value we wanted to store, why not just create one HSET to store all values for that application (thats if and only if all you doing is mapping keys to string/number values). That way you don’t fill up your key-space faster than you need to.

Because?

Redis can handle up to 2 ³² keys (4 billion), and was tested in practice to handle at least 250 million keys per instance.

Every hash, list, set, and sorted set, can hold 2 ³² elements (4 billion).

In other words your limit is likely the available memory in your system.

https://bit.ly/33vtddJ

Lets say you had a Redis instance with 10 applications sharing that same instance. For some reason these 10 applications needed to store key with associated values as discussed above. If they all went ahead to create keys (25 million each). That minimum threshold stated will be reached easily. However those 10 applications could just create 10 HSETS (1 for each) and store their 25 million keys in their respective HSETS. Since an HSET could handle 4 billion records, it should be easy to deal with the 25 million.

In Summary

Redis has powerful data-structures, when used appropriately enormous gains can be made. If you find yourself just setting string values to keys, then maybe you could use an HSET for that.

Thanks for making it here, feedback would be awesome!

--

--

Bill Inkoom
Hubtel Engineering

Software Engineer with great love for Mathematics especially Abstract Mathematics.