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.
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:
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:
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 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 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 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
Finally, if you want to remove all the keys, run the
Earlier you saw how you can run a simple key-value pair from inside
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:
Let's go through the other 4.
LSETto set the value of an item in the list from the left.
LRANGEto return the items in the list from the left to the right.
RPUSHto push a value to the right end of the list.
RPOPto 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
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"
(integer) 2, etc. Redis returns the size of the hellolist list.
LRANGE hellolist 0 -1is useful to display the entire list. 0 is the first index of the list and -1 is the last index of the list.
RPOPmutates the list by removing the right-most element on the list. It also returns the removed element.
LSETin this context mutates the nth index of the list.
LSET hellolist 1 helloNewmutates the item in index 1 (2nd item of the list) to the new value "helloNew".
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:
SADDto add an item.
SMEMBERSto return the items.
SREMto remove an item.
SCARDto return the number of items.
SISMEMBERto check if an item is found.
Let's play around using
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
SADDto add items into a new set.
SMEMBERS(much more concise syntax than
LRANGE) and to view the number of elements inside the set, use
SISMEMBER. If it returns 1, it is true. If it returns 0, it is false.
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:
HSETto set a hash key-value pair.
HGETto get a value using a key.
HDELto remove a key.
HLENto return then umber of key-value pairs in that hash.
HGETALLto 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"
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:
ZADDto add a new item to a zset.
ZRANGEto display items positionally.
ZRANGEBYSCOREto display items based on their scores.
ZREMto 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"
lrange hellolist 0 -1vs
zrange 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.
WITHSCOREcommand in the end.
ZRANGEBYSCORE hellozset 0 450 WITHSCORESdisplays all items in hellozset with scores between 0 to 450, effectively excluding the "first" item.
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:
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.
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 a
userId 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
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:
Love this? Find me on twitter!