About data structures in Redis Databases 12.08.2015

Redis is a very fast non-relational database that stores a mapping of keys to five different types of values (strings, lists, sets, hashes, sorted sets). Redis supports in-memory persistent storage on disk, replication to scale read performance, and client-side sharding 1 to scale write performance.

Redis has two different forms of persistence available for writing in-memory data to disk in a compact format. The first method is a point-in-time dump either when certain conditions are met (a number of writes in a given period) or when one of the two dump-to-disk commands is called. The other method uses an append-only file that writes every command that alters data in Redis to disk as it happens.

To support higher rates of read performance (along with handling failover if the server that Redis is running on crashes), Redis supports master/slave replication where slaves connect to the master and receive an initial copy of the full database.

Structure type What it contains Structure read/write ability
STRING Strings, integers, or floating-point values Operate on the whole string, parts, increment/decrement the integers and floats
LIST Linked list of strings Push or pop items from both ends, trim based on offsets, read individual or multiple items, find or remove items by value
SET Unordered collection of unique strings Add, fetch, or remove individual items, check membership, intersect, union, difference, fetch random items
HASH Unordered hash table of keys to values Add, fetch, or remove individual items, fetch the whole hash
ZSET (sorted set) Ordered mapping of string members to floating-point scores, ordered by score Add, fetch, or remove individual values, fetch items based on score ranges or member value

Strings

Strings are the simplest data type in redis and are simple key value entries. They are used to store three types of values:

  • Byte string values
  • Integer values
  • Floating-point values

Strings use simple SET and GET commands to save and fetch data.

SET 'movie:1' 'The Godfather'
SET 'movie:2' 'Pulp Fiction'

GET 'movie:1'

Using the MSET command, we can do multiple key value pairs in a row where the arguments will be MSET key value [key value ...].

MSET 'movie:3' 'movie:4' 'Forrest Gump' 'Inception'
MGET 'movie:3' 'movie:4'

Using the SETNX and MSETNX commands will say "set these values only if the key does not exist".

SETNX 'movie:3' 'Forrest Gump'
MSETNX 'movie:3' 'movie:4' 'Forrest Gump' 'Inception'

With SETEX command we can set an expiration in seconds and when that passes, the key and value is deleted.

The INCR and INCRBY command increment an integer value. With INCR, we increase by 1. With INCRBY, we can define the increment amount. Also, we have the opposite with DECR and DECRBY commands to go the opposite way.

Other commands

  • APPEND key value - concatenates the provided value to the string already stored at the given key.
  • GETRANGE key start end - fetches the substring, including all characters from the start offset to the end offset, inclusive.
  • SETRANGE key offset value - sets the substring starting at the provided offset to the given value.

Lists

LISTs allow you to push and pop items from both ends of a ordered sequence, fetch individual items, and perform a variety of other operations that are expected of lists.

We use the LPUSH command to prepend a value onto a list and RPUSH to append to it. Lists allow duplicates so we will always be able to add values without worrying. To see our entire list, we can use the LRANGE command to get a set of values based on start and end indices.

LPUSH list 1
LPUSH list 2
LPUSH list 3
LPUSH list 4
RPUSH list 0
LRANGE list 0 -1

We use the LPOP and RPOP much like their counterpart PUSH commands to remove items from the beginning and end of lists.

LPOP list
RPOP list
LRANGE list 0 -1

Indices will allow us to use the LINDEX command to get the value based on an index. We can also insert values BEFORE and AFTER indices with the LINSERT command. One thing to note about the LINSERT command is that we actually reference the value and not the index.

LINDEX list 0
LINSERT list BEFORE 3 4
LINSERT list AFTER 1 0
LRANGE list 0 -1

We can get the length of our list with the LLEN command. If we want to trim our list to a specific subset of it, we can use the LTRIM command to make the new list based on indices.

Other cool commands are

  • RPOPLPUSH source-list dest-list - pops the rightmost item from the source and LPUSH the item to the destination, also returning the item to the user.
  • BRPOPLPUSH source-list dest-list timeout - pops the rightmost item from the source and LPUSH the item to the destination, also returning the item to the user, and waiting up to the timeout if the source is empty.
LLEN list
LTRIM list 0 3
LRANGE list 0 -1
RPOPLPUSH list new_list
LRANGE list 0 -1
LRANGE new_list 0 -1

If you forget the commands, run HELP @list.

Sets

Like lists, sets are unordered. Unlike lists, each member of a set must be unique.

We use the SADD command to add members to our set and the SMEMBERS command to view everything in our set.

SADD girls 'Sophia'
SADD girls 'Emma'
SADD girls 'Olivia'
SADD girls 'Ava'
SMEMBERS girls

Using the SREM command will allow us to select the item we want to remove. If we want to remove a random member though, we can use the SPOP command which returns the randomly removed member.

SREM girls 'Ava'
SPOP girls

Use the SCARD command to get the length of the set and the SISMEMBER command to check if a member value belongs to the set.

SRANDMEMBER key-name [count] returns one or more random items from the SET. When count is positive, Redis will return count distinct randomly chosen items, and when count is negative, Redis will return count randomly chosen items that may not be distinct.

SCARD girls
SISMEMBER girls 'Sophia'
SRANDMEMBER girls

These are all cool, but what really sets a set apart is that you can do set arithmetic on them.

The SDIFF command will subtract one set from another. When we want to find the members that exist in both sets, we use the SINTER command. When we want all of the unique members from multiple sets then we can use the SUNION command.

SDIFF girls women
SDIFF girls women
SINTER girls women
SUNION girls women

By adding the STORE keyword to the end of the other commands, we say that we want to persist the data. Our command now looks like SINTERSTORE new_set old_set1 old_set2. These are very useful if you want to save the state of the calculation to use later.

Sorted Sets

While sets are unordered, a sorted set is ordered based on scores that you give to the members. These mappings allow us to manipulate the numeric scores, and fetch and scan over both members and scores based on the sorted order of the scores.

We add members to a zset with the ZADD command which expects an integer score and then the member itself. When view a zset, we use the ZRANGE command much like lists.

ZADD movies 9.2 'The Shawshank Redemption'
ZADD movies 9.2 'The Godfather'
ZADD movies 9.0 'The Godfather: Part II'
ZADD movies 8.9 'The Dark Knight'
ZRANGE movies 0 -1
ZRANGE movies 0 -1 WITHSCORES

We can use the ZRANGEBYSCORE command to get a range of items based on their score rather than their indices. With that, we have additional options that we can use with these commands.

ZRANGEBYSCORE movies 7 9 WITHSCORES

When we want to get the order of members from highest to lowest, we can use the ZREVRANGE command. With that, we also have access to a ZREVRANGEBYSCORE command which will get the highest to lowest members based on their scores.

When we want to get the size of our zset, we use the ZCARD command. As well, if we want to get the number of members in the zset between a certain score range, we use the ZCOUNT command. The ZRANK command will get the index based on a member while the ZSCORE will return the score for the member.

ZCARD movies
ZCOUNT movies 7 9
ZRANK movies 'The Dark Knight'
ZSCORE movies 'The Dark Knight'

When we want to select a specific member to remove from a set, we can use the ZREM command. When we want to remove a range of members based on index, we can use the ZREMRANGEBYRANK command. When we want to remove that range based on the score, we can use the ZREMRANGEBYSCORE command.

ZREM movies 'The Dark Knight'
ZREMRANGEBYRANK movies 0 1
ZREMRANGEBYSCORE movies 7 8

We use the ZINCRBY command to increase our score by a specific amount.

ZINCRBY movies 0.2 'The Godfather'

If you need a reference, run HELP @sorted_set to see the commands available.

Hashes

Hashes allow us to store multiple key-value pairs within a single key. They are unordered by nature.

We can set a single entry in the hash with HSET and we can set multiple values at once with HMSET. If we want to get all of the keys in our hash we use the HKEYS command and when we just want the values we can use the HVALS command. We can get all of our keys and values with the HGETALL command.

HSET cars 'Ford Model T' 1908
HMSET cars 'Volkswagen Beetle' 1938 'Toyota Corolla' 1966
HKEYS cars
HVALS cars
HGETALL cars

The HGET command will fetch a single value while the HMGET command will fetch multiple values based on keys.

HGET cars 'Toyota Corolla'
HMGET cars 'Volkswagen Beetle' 'Toyota Corolla'

We can check existence directly with the HEXISTS command. If we only want to add an entry if it doesn't exist though, we can use the HSETNX command.

HEXISTS cars 'Toyota Corolla'
HSETNX cars 'VAZ-2101' 1970
HGETALL cars

We delete entries with the HDEL command. When we have integer values in our hash, we can use the HINCRBY command to increment them programattically. Finally, we can use the HLEN command to find out the length of our hash.

HDEL cars 'VAZ-2101'
HINCRBY cars 'Volkswagen Beetle' 4

If you need a reference, run HELP @hash to see the commands available.

Other commands

  • PERSIST key - removes the expiration from a key.
  • TTL key - returns the amount of time remaining before a key will expire.
  • EXPIRE key seconds - sets the key to expire in the given number of seconds.
  • EXPIREAT key timestamp - sets the expiration time as the given Unix timestamp.
  • SORT source-key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]] [ASC|DESC] [ALPHA] [STORE dest-key] - sorts the input LIST, SET, or ZSET according to the options provided, and returns or stores the result.