Redis Basics

Here are my notes on Redis.

Installation, Start, and Shutdown

I installed WSL and then installed Redis using sudo.

  • To start Redis, cd to /usr/bin and run sudo ./redis-server
  • To connect to Redis, cd to /usr/bin and run sudo ./redis-cli
  • To shutdown Redis, run shutdown in the redis-cli, and Redis will save an RDB snapshot before exiting
  • To check whether Redis is running, run ps -ef | grep redis
  • To kill the process, run kill -9 <pid>

Commands

  • keys * returns all keys. This command also supports regex patterns
  • dbsize returns the number of keys
  • expire key sets the TTL of the key in seconds
    • pexpire sets the TTL in milliseconds
    • expireat sets the absolute time when the key will expire
  • ttl key returns the remaining time of the key
    • -1 means it won’t expire
    • -2 means it has already expired
    • Non-negative values show the countdown in seconds
  • set key value
    • setnx key value only sets the value when a key does not exist
    • mset k1 v1 k2 v2 k3 v3 ... sets multiple key-value pairs
    • This can save network bandwidth!
  • get key
    • mget k1 k2 k3 gets multiple keys
  • rename old_key new_key renames the old key to the new key
    • Use renamenx for safer operation, so it won’t override existing keys

Naming Convention

Naming convention for keys is very important.

namespace:entity:id:attribute

Here we use : as the separator.

Types

String

  • Size limit: 512MB
  • incr and decr can operate on strings!
    • Only when the string can be parsed into a numeric value. For example, "9" can be incremented but "9hello" cannot
    • incrby key increment increases the value of the key by the increment
    • incrbyfloat key increment performs the same operation for float types
    • append key string appends a string to the existing string

Hash

The hash here is essentially a hashmap. The structure is key-field-value. Syntax: hset name f1 v1 [field value]

Other operations:

  • hset: set field-value pair for a key
  • hget: get the value of a key-field
  • hdel: delete a field
  • hlen: returns the number of fields in the hashmap
  • hkeys: returns all the fields in the hashmap
  • hvals: returns all the values in the hashmap
  • hmget key f1 f2 ...: get multiple fields from the hashmap

Note: String vs Hashmap

For example, to store information like:

[
  { "id": 1, "name": "john", "age": 30 },
  { "id": 2, "name": "jane", "age": 25 }
]

If we use strings to store the data:

set user:1:name john
set user:1:age 30
set user:2:name jane
set user:2:age 25

This creates too many keys and makes it hard to join all the data for a specific user.

A better approach:

hset user:1 name john age 30
hset user:2 name jane age 25

This implementation is much better.

List

List is an ordered array of elements. It can hold up to 2^32 - 1 elements.

You can insert elements into the head or tail of the linked list.

  • lpush: adds a new element to the head of the list. It returns the length of the list
  • rpush: adds a new element to the tail of the list
    • push commands support pushing multiple elements into a list, for example: rpush mylist 0 1 2 3 4
  • lpop and rpop: remove and return the element from the head (and tail) of the list
    • blpop is the blocking version of lpop
    • blpop key timeout is the syntax
    • When timeout is zero and the list is empty, the Redis engine will wait until the list becomes non-empty, then remove the element
    • the push commands do not have blocking behavior
  • lrange mylist 0 -1: returns all elements in the list. 0 is the start index and -1 is the end index
    • here, l simply means “list”, not “left”
  • lset key index element: sets the value of the element at a specific index

With lists, you can implement:

  • A queue with lpush and rpop
  • A blocking queue with blpush and brpop
  • A stack with lpush and lpop

Set

Set is an unordered collection of unique elements. It can hold up to 2^32 - 1 elements. It supports set operations like intersection and union.

  • sadd key v1 v2 ...: adds elements
  • smembers key: returns all elements in a set
  • srem key v1 v2 ...: removes elements
  • sismember key v1: checks if an element is in the set. 0 means false while 1 means true
  • sinter k1 k2 ...: returns the intersection
    • sinterstore destination key [key ...]: calculates the intersection and stores the result in the destination key
  • sunion k1 k2 ...: returns the union
  • sdiff k1 k2 ...: returns the difference of two sets

ZSet

ZSet is ordered collection of unique elements. This data structure is very critical for implementing leaderboard.

TL;DR: to return the top k users in the leaderboard:

ZADD scores 100 user:1
ZADD scores 30 user:2 10 user:3
ZINCRBY scores 10 user:3
ZADD scores 10 user:4 15 user:5 6 user:6
ZINCRBY scores 60 user:6
ZINCRBY scores -72 user:1
ZREVRANGE scores 0 4 WITHSCORES # top 5 users
  • zadd key score member [score member ...]: for each member, there’s a score
  • zadd also comes with options like NX and XX
  • zcard key returns the number of elements in the zset
  • zscore key member returns the score of a member
  • zrank key member returns the ranking. ranking is sorted by score asc
    • zrevrank returns the ranking by score in descending order
  • zrem remove a member from the set
  • zincrby key increment member: increase the score by increment! Useful for real-time game score updates
  • zrange key start stop: returns the members within the range of [start, stop]
    • [REV]: for descending order
    • [WITHSCORES]: for showing the score
    • [BYSCORE]: you can do a range query by scores! For example, I want to find all the users whose scores are between [90, 100]