Redis Use Cases

What can you do with Redis?

  • Cache

  • Message Brokers/Queues

  • User Sessions

  • Real-time Recommendation Engine

  • Leaderboards

  • … and much more

webarch
Figure 1. Modern Web App
webarch redis
Figure 2. Modern Web App with Redis

Simple Cache

The Problem

Multiple database calls create impossibly slow web page response times

Why Redis Rocks

  • Strings store text or binary

  • SET lets you store any payload

  • GET to retrieve values

  • Optional expiration

  • Listen for changes on keys and expirations

  • Multiple eviction policies supported

SET user:1 8754  (1)
GET user:1  (2)
  1. Set string user:1 to 8754

  2. Get value of string user:1

EXPIRE user:1 60  (1)
DEL user:1  (2)
SETEX user:2 120 4510  (3)
  1. Set expiration for user:1 to 60 sec

  2. Delete string user:1

  3. Set user:2 to 4510 and expiration to 120 sec

Strings in Jedis

jedis.set("user:1", "8754");
jedis.get("user:1");
jedis.expire("user:1", 60);
jedis.del("user:1");

User Session

The problem

  • Maintain session state across multiple servers

  • Multiple session variables

  • High speed/low latency required

Why Redis rocks

  • Hashes store session variables as key/value pairs

  • HMSET to store key/value pairs

  • HMGET to retrieve values

  • HINCRBY to increment a field within the hash

  • HDEL to delete one key/value

HMSET session:1 user 8754 name dave ip 10:20:104:31 hits 1
HMGET session:1 user name ip hits
+------+--------------+
| user |     8754     |
+------+--------------+
| name |     dave     |
+------+--------------+
|  ip  | 10.20.104.31 |
+------+--------------+
| hits |      1       |
+------+--------------+
HINCRBY session:1 hits 1
+------+--------------+
| user |     8754     |
+------+--------------+
| name |     dave     |
+------+--------------+
|  ip  | 10.20.104.31 |
+------+--------------+
| hits |      2       |
+------+--------------+
HSET session:1 last home
+------+--------------+
| user |     8754     |
+------+--------------+
| name |     dave     |
+------+--------------+
|  ip  | 10.20.104.31 |
+------+--------------+
| hits |      2       |
+------+--------------+
| last |     home     |
+------+--------------+
HGET session:1 lastpage  (1)
HDEL session:1 lastpage  (2)
DEL session:1  (3)
  1. Get lastpage field from hash

  2. Delete lastpage entry from hash

  3. Delete the whole hash

Hashes in Jedis

Map<String, String> session = new HashMap<>(); (1)
session.put("userid", "8754");
session.put("name", "dave");
session.put("ip", "10:20:104:31");
session.put("hits", "1");
jedis.hmset("session:1", session); (2)
jedis.hmget("session:1", "userid", "name", "ip", "hits"); (3)
jedis.hincrBy("session:1", "hits", 1);
jedis.hset("session:1", "lastpage", "home");
jedis.hget("session:1", "lastpage");
jedis.hdel("session:1", "lastpage");
  1. Create a hash map to store the session

  2. Store map under session:1 hash

  3. Retrieve the session

Work Queues

The problem

  • Tasks need to be worked on asynchronously

  • Lots of items to be worked on

  • Assign items to worker and remove from queue

  • Similar to buffering high speed data-ingestion

  • High speed/low latency required

Why Redis rocks

  • Lists are perfect for this!

  • LPUSH/RPUSH add values at head or tail

  • RPOPLPUSH: pop from queue, push to another

LPUSH queue:1 red
       +-------------+-------------+-------------+-------------+-------------+
queue∶1|cRED red     |             |             |             |             |
       +-------------+-------------+-------------+-------------+-------------+
LPUSH queue:1 green
       +-------------+-------------+-------------+-------------+-------------+
queue∶1|cGREgreen    |cRED red     |             |             |             |
       +-------------+-------------+-------------+-------------+-------------+
RPUSH queue:1 blue
       +-------------+-------------+-------------+-------------+-------------+
queue∶1|cGREgreen    |cRED red     |             |             |cBLU blue    |
       +-------------+-------------+-------------+-------------+-------------+
RPOPLPUSH queue:1 queue:2
       +-------------+-------------+-------------+-------------+-------------+
queue∶1|cGREgreen    |cRED red     |             |             |             |
       +-------------+-------------+-------------+-------------+-------------+
                                                                      |
               +------------------------------------------------------+
               |
               v
       +-------------+-------------+-------------+-------------+-------------+
queue∶2|cBLU blue    |             |             |             |             |
       +-------------+-------------+-------------+-------------+-------------+

Lists in Jedis

jedis.lpush("queue:1", "red");
jedis.lpush("queue:1", "green");
jedis.rpush("queue:1", "blue");
jedis.rpoplpush("queue:1", "queue:2");

Recommendation Engine

The problem

  • People who like this also like that

  • Want real time not data mining

  • Recommending similar purchases

  • Identifying fraud

Why Redis rocks

  • SETS: unique collections of strings

  • SADD adds tags to each article

  • SISMEMBER checks if an article has a given tag

  • SMEMBERS: all tags for an article

  • SINTER: find similar articles with the same tags

SADD tag:1 article:3 article:1
SADD tag:2 article:22 article:14 article:3
SADD tag:3 article:9 article:3 article:2
SMEMBERS tag:3
      +---------------+---------------+---------------+---------------+
tag∶1 |     art∶1     |     art∶3     |               |               |
      +---------------+---------------+---------------+---------------+

      +---------------+---------------+---------------+---------------+
tag∶2 |     art∶3     |     art∶4     |     art∶7     |               |
      +---------------+---------------+---------------+---------------+

      +---------------+---------------+---------------+---------------+
tag∶3 |     art∶2     |     art∶3     |     art∶9     |               |
      +---------------+---------------+---------------+---------------+

Set Intersection

SINTER tag:1 tag:2 tag:3
1) "art:3"
      +---------------+---------------+---------------+---------------+
tag∶1 |     art∶1     |cRED art∶3     |               |               |
      +---------------+---------------+---------------+---------------+

      +---------------+---------------+---------------+---------------+
tag∶2 |cRED art∶3     |     art∶4     |     art∶7     |               |
      +---------------+---------------+---------------+---------------+

      +---------------+---------------+---------------+---------------+
tag∶3 |     art∶2     |cRED art∶3     |     art∶9     |               |
      +---------------+---------------+---------------+---------------+

Leaderboard

The problem

  • Many users playing a game or collecting points

  • Display real-time leaderboard

  • Who is your nearest competition

  • Disk-based DB is too slow

Why Redis rocks

  • Sorted sets automatically keep sorted list of users

  • ZADD to add/update

  • ZRANGE, ZREVRANGE to get user

  • ZRANK will get any user’s rank instantaneously

ZADD game:1 10000 id:1
ZADD game:1 21000 id:2
ZADD game:1 34000 id:3
ZADD game:1 35000 id:4
+------+-------+
| id∶4 | 35000 |
+------+-------+
| id∶3 | 34000 |
+------+-------+
| id∶2 | 21000 |
+------+-------+
| id∶1 | 10000 |
+------+-------+
ZINCRBY game:1 10000 id:3
+------+-------+
| id∶3 | 44000 |<-+
+------+-------+  |
| id∶4 | 35000 |--+
+------+-------+
| id∶2 | 21000 |
+------+-------+
| id∶1 | 10000 |
+------+-------+

Leaderboard

ZREVRANGE game:1 0 0  (1)
ZREVRANGE game:1 0 3 WITHSCORES  (2)
  1. Get the top player

  2. Get the top 3 players with their scores

Search by Location

The problem

Find stores in a 2-mile radius

How far am I from a hospital?

Why Redis rocks

  • Geo sets store geo locations

  • GEOADD to add a location

  • GEODIST to get distance

  • GEORADIUS to get locations within radius

Count Unique Visitors

The problem

  • Count unique daily visitors to the site

  • How many unique users have clicked on an ad

Why Redis rocks

  • HyperLogLog keeps count of each unique element

  • PFADD to add an element

  • PFCOUNT to get count

Event streaming

The problem

  • IoT device sending sensor information to multiple services

  • App sending out messages about activities to multiple users

Why Redis rocks

  • Pub/Sub is a lightweight way of distributing messages

  • No polling, it waits for messages

  • PUBLISH to send messages

  • SUBSCRIBE to get messages

pubsub
Figure 3. Pub/Sub

Streams

Traditional Approaches

  • Pub/Sub

  • Lists

  • Sorted Sets

streams scenario1
Figure 4. Scenario 1
streams scenario2
Figure 5. Scenario 2
streams scenario3
Figure 6. Scenario 3
streams scenario4
Figure 7. Scenario 4