Nowadays you probably have heard of Redis. If you have never used it, it's good to know about it.
So what is Redis? It is an in-memory NoSQL database.
It is done in memory; because of this, Redis queries are much faster than SQL queries.
It is a database because it stores data (although by default it is not persistent).
It is a NoSQL database because it is not relational but instead uses key-value pairs.
So Redis is similar to a relational database in a sense that they are both databases. However, Redis is not an alternative to a relational database. You don't want to give up MySQL/PostgreSQL completely in exchange for Redis. They are different tools for different tasks. Use Redis for time-critical, non-persistent queries. Use MySQL/PostgreSQL for durability, SQL queries, and security.
Redis is NOT an alternative to DB. It's not like you have to give up MySQL/ PostgreSQL and switch to Redis. It's a different tool to do different tasks that MySQL is not good at. On the other hand, you use MySQL to do things that Redis isn't good at. Don't use Redis for durability, to make SQL queries, or security. Use PostgreSQL.
Using Redis For The First Time
Redis is available almost everywhere. To install Redis, check out the official download page here.
If you have a mac, you can install Redis via homebrew:
brew install redis
Once installed, to run the Redis server, run:
redis-server
I personally like to run it on the background. To do that, you can run:
redis-server --daemonize yes
Let's get the feel for it. You can either use your choice language's Redis library (they should have one) or access it directly with Redis CLI. In this case, I will use the latter. Run:
redis-cli
As mentioned earlier, Redis is a NoSQL database. At its core, it stores key-value pairs. To set a new key-value pair, use the SET
command.
SET hello redis
# OK
That's it! You just set a key "hello" with a value "redis". To get that value, you can run the GET
command:
GET hello
# "redis"
If you try to get a nonexistent key, Redis will not return anything
GET dontexist
# (nil)
To delete a key-value pair, use DEL
:
DEL hello
# (integer) 1
GET hello
# (nil)
Notice that when you run DEL hello
the first time, it returns (integer) 1
. This is because Redis is returning the number of affected items. In this case, you only deleted a pair, so it returns 1.
To quit Redis cli, type the command EXIT
or press Ctrl-C
. To actually shut down the Redis server, from inside the cli, run SHUTDOWN
.
Finally, if you want to remove all the keys, run the FLUSHALL
command.
Redis Data Types
Earlier you saw how you can run a simple key-value pair from inside redis-cli
with:
SET hello redis
# OK
GET hello
# "redis"
Redis actually has 5 different data types. What you just did above was setting a key-value pair for a string data type. The 5 data types are:
- String
- List
- Set
- Hash
- Zset
Let's go through the other 4.
List
Redis has a list data type. It is similar to Python's list or Javascript array. A list is a sequence of characters. Some commonly used commands are:
LSET
to set the value of an item in the list from the left.LRANGE
to return the items in the list from the left to the right.RPUSH
to push a value to the right end of the list.RPOP
to remove and return the rightmost item.
Note that they are all prefixed with either L
(left) or R
(right). For each L
command, there is a R
counterpart and vice-versa.
Let's try them out. With redis-server
running, open the CLI with the redis-cli
command.
RPUSH hellolist hello1
# (integer) 1
RPUSH hellolist hello2
# (integer) 2
RPUSH hellolist hello3
# (integer) 3
LRANGE hellolist 0 -1
# 1) "hello1"
# 2) "hello2"
# 3) "hello3"
RPOP hellolist
# "hello3"
LRANGE hellolist 0 -1
# 1) "hello1"
# 2) "hello2"
LSET hellolist 1 helloNew
# OK
LRANGE hellolist 0 -1
# 1) "hello1"
# 2) "helloNew"
- Note that each time you add to hellolist, Redis returns an increasing integer value
(integer) 1
,(integer) 2
, etc. Redis returns the size of the hellolist list. - The command
LRANGE hellolist 0 -1
is useful to display the entire list. 0 is the first index of the list and -1 is the last index of the list. RPOP
mutates the list by removing the right-most element on the list. It also returns the removed element.LSET
in this context mutates the nth index of the list.LSET hellolist 1 helloNew
mutates the item in index 1 (2nd item of the list) to the new value "helloNew".
Set
Redis has a set data type. If you are familiar with Python, Redis' set is similar to Python's set. It is a collection of unique items. Some commonly used commands are:
SADD
to add an item.SMEMBERS
to return the items.SREM
to remove an item.SCARD
to return the number of items.SISMEMBER
to check if an item is found.
Let's play around using redis-cli
:
SADD helloset chocodonut
# (integer) 1
SADD helloset sugardonut
# (integer) 1
SADD helloset glazeddonut
# (integer) 1
SADD helloset sugardonut
# (integer) 0
SMEMBERS helloset
# 1) "chocodonut"
# 2) "glazeddonut"
# 3) "sugardonut"
SREM helloset sugardonut
# (integer) 1
SMEMBERS helloset
# 1) "chocodonut"
# 2) "glazeddonut"
SCARD helloset
# (integer) 2
SISMEMBER helloset chocodonut
# (integer) 1
- To create a set, use
SADD
to add items into a new set. - To view a set, use
SMEMBERS
(much more concise syntax thanLRANGE
) and to view the number of elements inside the set, useSCARD
. - To check whether an item exists in a set, use
SISMEMBER
. If it returns 1, it is true. If it returns 0, it is false.
Hash
Hash in Redis is similar to Python's dictionaries. They hold unique key-value pairs. Technically Redis itself is a collection of key-value pairs. So a hash data type is like a mini Redis. Some commonly used operations:
HSET
to set a hash key-value pair.HGET
to get a value using a key.HDEL
to remove a key.HLEN
to return then umber of key-value pairs in that hash.HGETALL
to return all key-value pairs.
Let's try it out on the CLI:
HSET hellohash key1 value1
# (integer) 1
HSET hellohash key2 value2
# (integer) 1
HSET hellohash key3 value3
# (integer) 1
HGET hellohash key1
# "value1"
HGETALL hellohash
# 1) "key1"
# 2) "value1"
# 3) "key2"
# 4) "value2"
# 5) "key3"
# 6) "value3"
HLEN hellohash
# (integer) 3
HDEL hellohash key2
# (integer) 1
HGETALL hellohash
# 1) "key1"
# 2) "value1"
# 3) "key3"
# 4) "value3"
Zset
A zset (sorted-set) is a data type unique to Redis. It is similar to the set data type because it contains a collection of unique items. It is also similar to a hash because each item is assigned to a score (float numbers), just like a hash's key is assigned to a value. The big idea of zset is to make it easy to sort items based on their assigned scores (hence the name sorted-set). Some common commands:
ZADD
to add a new item to a zset.ZRANGE
to display items positionally.ZRANGEBYSCORE
to display items based on their scores.ZREM
to remove an item.
It was harder for me to grasp zset because I haven't really seen anything like it, so the best way is to create one and see it yourself!
ZADD hellozset 500 first
# (integer) 1
ZADD hellozset 300 second
# (integer) 1
ZADD hellozset 400 third
# (integer) 1
ZRANGE hellozset 0 -1
# 1) "second"
# 2) "third"
# 3) "first"
ZRANGE hellozset 0 -1 WITHSCORES
# 1) "second"
# 2) "300"
# 3) "third"
# 4) "400"
# 5) "first"
# 6) "500"
ZRANGEBYSCORE hellozset 0 450
# 1) "second"
# 2) "third"
ZRANGEBYSCORE hellozset 0 450 WITHSCORES
# 1) "second"
# 2) "300"
# 3) "third"
# 4) "400"
ZREM hellozset second
# (integer) 1
ZRANGE hellozset 0 -1 WITHSCORES
# 1) "third"
# 2) "400"
# 3) "first"
# 4) "500"
- There are three items in the zset: "first", "second", and "third". Each item is associated with the scores of 500, 300, and 400 respectively. The "first" item has a score of 500, the "second" item 300, and the "third" item 400.
- You may notice that the command to display all items in a zset is similar to list:
lrange hellolist 0 -1
vszrange hellozset 0 -1
. However, note that when you do that on a zset, the items are sorted by their scores. Note how the item "first" was listed last because it has the largest score. - Zset lets you to call the range and display the scores. All you need to do is add the
WITHSCORE
command in the end. - Zset also lets you to set the upper and lower limit of the score range.
ZRANGEBYSCORE hellozset 0 450 WITHSCORES
displays all items in hellozset with scores between 0 to 450, effectively excluding the "first" item.
Redis Pub/Sub
You can use the pub/sub (publish/subscribe) pattern in Redis to send and receive messages. The idea is to have one or more entities subscribe to a channel. Then a publisher sends messages to that channel. All subscribers will then receive it.
Here's a very basic version of it. Inside a redis-cli
interface, let's subscribe to a channel:
SUBSCRIBE donuts
Now run a new redis-cli
. This one will act like a publisher. Run:
PUBLISH donuts yummy
Pay attention to the first CLI (the subscriber). It will receive the "yummy" event. With pub/sub, you can subscribe to a channel (or multiple channels at the same time) and wait for a new published event.
What do we use Redis for?
Redis is an in-memory database with very low latency compared to a relational database like PostgreSQL. The important question is, "what do we use Redis for?"
You can use Redis for what a relational database cannot do best. You use relational database for what Redis cannot do best.
-
Use Redis for a session cache. If you want to store a user session information outside of your server but don't want to store the entire session data in the Session Storage or cookies, you can use Redis. In a Redis server, create a hash object
login_users:
(you can call it anything) to store the login informations that can be called with auserId
token from your cookie. -
Use Redis for a value cache. If you have a computationally intensive function, after running it once, save the result in the cache. The next time someone requested to run that function with the same parameters again, check if the cache value is already in Redis before requesting your main server to compute it.
-
Use Redis to implement an expiration date. Suppose you want to keep the last 1,000,000 session information in the Redis server. Redis has a zset (sorted set) for these sort of tasks. When creating a new session information, assign a time score (Unix time stamp is perfect) to each session added. Have a daemon process to periodically check this zset and only keep the most recent 1,000,000 users with
ZRANGE
. -
Use Redis to cache HTML pages. Pages like
/support
pages are mostly static. Cache them with Redis instead so the server doesn't have to provide the page, freeing it to do more important stuff. -
Use Redis to keep track of votes like Stackoverflow upvotes. Again, zset is a good data type for this task. To display the top 50 most popular articles, run
ZREVRANGE popularArticles: 0 49
.
There are many other usages for Redis. Check out:
- What are the best use cases for Redis?
- How to take advantage of Redis just adding it to your stack
- Redis and its many uses
- Redis in action
Love this? Find me on twitter!