Redis Beginner Guide

Redis Beginner Guide

Scalable System

·

35 min read

Table of contents

If you want to see more of my work, you can follow me on LinkedIn, GitHub, Dev , Hashnode I post regularly about web development, data fetching, and other topics. 🚀

Covered Topics

  • What is Redis?

  • How to set up Redis with docker? (redis-stack and redis-client)

  • CLI commands for Redis

  • Redis with Node.js

  • Data Types

    • String Operations (cli and node.js)set name, get name, setnx, MSET, MGET, INCR, INCRBY, GETRANGE, SETRANGE, GETRANGE, STRLEN, APPEND, SETEX, SETNX, MSETNX, SETRANGE, GETRANGE, STRLEN, DECR, DECRBY, PSETEX

    • List Operations (cli and node.js)LPUSH (Stack & Queue Concept), RPUSH (Stack & Queue Concept), LPOP, RPOP, LLEN, LRANGE, LINDEX, LINSERT, LSET, LTRIM, LREM, RPOPLPUSH, BLPOP, BRPOP, BRPOPLPUSH

    • Set Operations (cli and node.js)SADD, SREM, SISMEMBER, SMEMBERS, SPOP, SRANDMEMBER, SMOVE, SCARD, SINTER, SUNION, SDIFF, SDIFF, SINTERSTORE, SUNIONSTORE, SDIFFSTORE, SSCAN

    • Hash Operations (cli and node.js)HSET, HGET, HGETALL, HDEL, HEXISTS, HKEYS, HVALS, HLEN, HINCRBY, HINCRBYFLOAT, HMSET, HMGET, HSETNX, HSTRLEN, HSCAN

    • Sorted Set Operations (cli and node.js)ZADD, ZREM, ZSCORE, ZRANGE, ZREVRANGE, ZRANGEBYSCORE, ZREVRANGEBYSCORE, ZCARD, ZCOUNT, ZINCRBY, ZLEXCOUNT, ZRANGEBYLEX, ZREVRANGEBYLEX, ZREMRANGEBYLEX, ZREMRANGEBYRANK, ZREMRANGEBYSCORE, ZUNIONSTORE, ZINTERSTORE, ZSCAN, ZPOPMIN, ZPOPMAX, BZPOPMIN, BZPOPMAX, ZRANK

    • REDIS STREAMS OPERATIONS (cli and node.js)XADD, XLEN, XRANGE, XREVRANGE, XREAD, XREADGROUP, XGROUP, XACK, XCLAIM, XDEL, XTRIM, XINFO, XSETID, XREWRITE

    • Bitmaps Operations (cli and node.js)GEOADD, GEOPOS, GEODIST, GEORADIUS, GEORADIUSBYMEMBER, GEOHASH, GEOSEARCH, GEOSEARCHSTORE

  • Redis Pub/Sub

  • Scale A Node.js Application with Redis

Introduction:

Redis is an open-source, in-memory key-value data store. It is versatile and can be used as a database, cache, and message broker. Redis supports various data structures such as Strings, Hashes, Lists, Sets, and more. It provides high availability via Redis Sentinel and automatic partitioning across multiple Redis nodes with Redis Cluster.

Installation:

  1. Download Docker Desktop from the official Docker website.

  2. Install Docker Desktop and open it.

  3. Open the terminal and run the following command to start the Redis server and Redis Commander:

docker run -d --name redis-stack -p 6379:6379 -p 8001:8001 redis/redis-stack:latest

This command will run the Redis server on port 6379 and Redis Commander on port 8001.

  1. Open a web browser and navigate to localhost:8001 to view the Redis Commander.

  2. Go back to the terminal and run docker ps to check if the Redis server is running. If it's not, run docker start redis-stack.

Now, you can use the Redis server in your project.

Redis CLI Commands:

  1. Run docker ps in the terminal to check the running container and copy the container id.

  2. Use docker exec -it <container_id> bash to open the bash terminal of the container. For example: docker exec -it 7b7e bash.

  3. Type redis-cli to open the Redis CLI terminal.

  4. Type ping to check if the Redis server is running. If you get PONG, then the server is running.

Nodejs Setup

  1. open the 5.redis folder and run the following command
npm run string
npm run list
npm run set
npm run hash
npm run sortedset
npm run stream
npm run bitmap
npm run geo
npm run pubsub
npm run dev
  1. open the server/src/client.ts setup the redis client
import Redis from "ioredis";

const client = new Redis({
    host: 'localhost', // replace with your host, if not localhost
    port: 6379  // replace with your port, if not 6379
});

export default client;
  1. open the 5.redis folder and you will get the following files
  • string.ts

  • list.ts

  • set.ts

  • hash.ts

  • sortedset.ts

  • stream.ts

  • bitmap.ts

  • geo.ts

  • pubsub.ts

  • src/client.ts

  • src/todos.ts

Time complexity, Limitations, Use cases

  • Time Complexity

    • Hashes: O(1) for each key-value pair, O(N) for N key-value pairs.

    • Lists: O(1) for each push/pop operation, O(N) for N items in the list.

    • Sets: O(1) for each add/remove operation, O(N) for N items in the set.

    • Sorted Sets: O(1) for each add/remove operation, O(log(N)+M) for N items in the sorted set and M elements returned.

    • Streams: O(1) for each item added to the stream, O(N) for N items in the stream.

    • Bitmaps: O(1) for each set bit, O(N) for N bits set.

    • Geo: O(log(N)) for each item added to the sorted set, where N is the number of elements in the sorted set.

    • Pub/Sub: O(N+M) for N channels and M subscribers.

  • Limitations

    • Hashes: The maximum number of fields is (2^32 - 1)4294967295, more than 4 billion of fields per hash).

    • Lists: The maximum number of elements is (2^32 - 1)4294967295, more than 4 billion of elements per list).

    • Sets: The maximum number of members is (2^32 - 1)4294967295, more than 4 billion of elements per set).

    • Sorted Sets: The maximum number of members is (2^32 - 1)4294967295, more than 4 billion of elements per sorted set).

    • Streams: The maximum number of entries is (2^64 - 1)18446744073709551615, more than 18 quintillion of entries per stream).

    • Bitmaps: The maximum number of bits is (2^32 - 1)4294967295, more than 4 billion of bits per bitmap).

    • geo: The maximum number of members is (2^32 - 1)4294967295, more than 4 billion of elements per geo set).

    • Pub/Sub: The maximum number of channels is 2^32 - 1)4294967295, more than 4 billion of channels per Redis instance).

  • Use cases

    • Redis hash—Use hashes when you have a large number of fields to store. For example, you can use hashes to store user information, such as name, email, address, and more.

    • Redis list—Use lists when you want to store a list of items. For example, you can use lists to store a list of products, a list of users, and more.

    • Redis set—Use sets when you want to store a unique list of items. For example, you can use sets to store a list of tags, a list of followers, and more.

    • Redis sorted set—Use sorted sets when you want to store a list of items in a sorted order. For example, you can use sorted sets to store a list of products sorted by price, a list of users sorted by age, and more.

    • Redis stream—Use streams when you want to store a list of items in a chronological order. For example, you can use streams to store a list of events, a list of messages, and more.

    • Bitmap — Use bitmaps when you want to store a list of items in a chronological order. For example, you can use bitmaps to store a list of events, a list of messages, and more.

    • Geo — Use geo when you want to store a list of items in a chronological order. For example, you can use geo to store a list of events, a list of messages, longitudes, latitudes, and more.

    • Pub/Sub — Use pub/sub when you want to store a list of items in a chronological order. For example, you can use pub/sub to store a list of events, a list of messages, and more.

Data Types

String Data Structure:

Cli Commands

1.1.set name

Type set name "subham" to set a key-value pair in the Redis server.

1.2.get name

Type get name to retrieve the value of the key from the Redis server.

Note: If you open your Redis stack in the browser, you will see the key and value set. You can also update the value from there. Just click on the key and update the value on the right side. The Best way to do this is

set user:1 "subham"

set user:2 "codexam"

set user:3 "xamcodexam"

set msg:1 "hello"

set msg:2 "hi"

set msg:3 "hey"

If you group on the redis-stack you will see the data like this

user
    1: "subham"
    2: "codexam"
    3: "xamcodexam"

msg
    1: "hello"
    2: "hi"
    3: "hey"

1.3.setnx

set if not exists(nx)

set user:1 "subham" nx

if you don't use nx, then it will overwrite the value

set user:1 "codexam"

1.4.MSET

set multiple values

mset user:1 "subham" user:2 "codexam" msg:1 "hello" msg:2 "hi"

1.5.MGET

get multiple values

mget user:1 user:2 msg:1 msg:2

1) "subham"
2) "codexam"
3) "hello"
4) "hi"

1.6.INCR

increment the value by 1

set user:1 10

incr user:1

(integer) 11

1.7.INCRBY

increment the value by 5

set user:1 10

incrby user:1 5

(integer) 15

Note: By default a single Redis string can be a maximum of 512MB in size.

1.8.GETRANGE

get the value from the range(SUBSTRING)

set user:1 "subham"

getrange user:1 0 3

"subh"

1.9.SETRANGE

set the value from the range(SUBSTRING)

set user:1 "subham"

setrange user:1 0 "codexam"

(integer) 7

get user:1

"codexam"

1.10.GETRANGE

get the value from the range(SUBSTRING)

set user:1 "subham"

getrange user:1 0 3

"subh"

1.11.STRLEN

get the length of the value

set user:1 "subham"

strlen user:1

(integer) 6

1.12.APPEND

append the value

set user:1 "subham"

append user:1 " codexam"

(integer) 14

get user:1

"subham codexam"

1.13.SETEX

set the value with expiration time (in seconds)

setex user:1 10 "subham"

(integer) 1

get user:1

"subham"

get user:1

(nil)

1.14.SETNX

set the value if the key doesn't exist

setnx user:1 "subham"

(integer) 1

get user:1

"subham"

setnx user:1 "codexam"

(integer) 0

get user:1

"subham"

1.15.MSETNX

set multiple values if the key doesn't exist


msetnx user:1 "subham" user:2 "codexam" msg:1 "hello" msg:2 "hi"


(integer) 1

get user:1

"subham"

get user:2

"codexam"

get msg:1

"hello"

get msg:2

"hi"

1.16.SETRANGE

set the value from the range(SUBSTRING)


set user:1 "subham"

setrange user:1 0 "codexam"

(integer) 7

get user:1

"codexam"

1.17.GETRANGE

get the value from the range(SUBSTRING)


set user:1 "subham"

getrange user:1 0 3

"subh"

1.18.STRLEN

get the length of the value


set user:1 "subham"

strlen user:1

(integer) 6

1.19.DECR

This command decreases the value of a key by 1. If the key does not exist, it is set to -1.

set user:1 10

decr user:1

(integer) 9

1.20.DECRBY

This command decreases the value of a key by the given number. If the key does not exist, it is set to negative the given number.

set user:1 10

decrby user:1 5

(integer) 5

1.21.PSETEX

This command sets the value and expiration in milliseconds of a key.

psetex user:1 10000 "subham"

(integer) 1

get user:1

"subham"

get user:1

(nil)

List Data Structure:

A list data structure is a collection of elements in the order they are inserted. It is similar to an array in other programming languages. The list data structure is often used to implement other data structures like queues and stacks.

List Operations

Here are some operations performed on a list:

OperationElement
Push1
Push2
Push3
Pop3
Pop2
Pop1

Cli Commands

2.1.LPUSH

This command inserts the specified value at the head of the list.

lpush user:1 "subham"
lpush user:1 "codexam"

Visualize the list in the Redis Commander. Last In First Out (LIFO) (similar to stack)

IndexElement
0codexam
1subham

2.2.RPUSH

This command inserts the specified value at the tail of the list.

rpush user:1 "subham"
rpush user:1 "codexam"

Visualize the list in the Redis Commander.

IndexElement
0subham
1codexam

Note

Redis can be used to implement a stack data structure, which follows a Last In, First Out (LIFO) principle. You can use the lpush command to insert elements at the head of the list, and the lpop command to remove elements from the head of the list.

Here's an example of how you can use Redis commands to implement a stack:

lpush user:1 "subham"
lpush user:1 "codexam"

lpop user:1  # Output: "codexam"
lpop user:1  # Output: "subham"

Visualization in Redis Commander

  • After lpush operations:
IndexElement
0codexam
1subham
  • After first lpop operation:
IndexElement
0subham
  • After second lpop operation:
IndexElement

As you can see, the last element pushed to the stack is the first one to be popped, which is characteristic of a stack.


2.3.LPOP

This command removes and returns the first element of the list.


lpush user:1 "subham"

lpush user:1 "codexam"

lpop user:1

"codexam"

2.4.RPOP

This command removes and returns the last element of the list.


lpush user:1 "subham"

lpush user:1 "codexam"

rpop user:1

"subham"

2.5.LLEN

This command returns the length of the list.


lpush user:1 "subham"

lpush user:1 "codexam"

llen user:1 

(integer) 2

2.6.LRANGE

This command returns the specified range of elements from the list.


lpush user:1 "subham"

lpush user:1 "codexam"

lrange user:1 0 1

1) "codexam"

2) "subham"

2.7.LINDEX

This command returns the element at the specified index.

lpush user:1 "subham"

lpush user:1 "codexam"

lindex user:1 0

"codexam"

2.8.LSET

This command sets the value at the specified index.

lpush user:1 "subham"

lpush user:1 "codexam"

lset user:1 0 "xamcodexam"

"OK"

lrange user:1 0 1

1) "xamcodexam"

2) "subham"

2.9.LINSERT

This command inserts the specified value before or after the specified pivot value.


lpush user:1 "subham"

lpush user:1 "codexam"

linsert user:1 before "subham" "xamcodexam"

(integer) 3

lrange user:1 0 1

1) "codexam"

2) "xamcodexam"

3) "subham"

2.10.LSET

This command sets the value at the specified index.


lpush user:1 "subham"

lpush user:1 "codexam"

lset user:1 0 "xamcodexam"

"OK"

lrange user:1 0 1

1) "xamcodexam"

2) "subham"

2.11.LTRIM

This command trims the list to the specified range.


lpush user:1 "subham"

lpush user:1 "codexam"

ltrim user:1 0 1

"OK"

lrange user:1 0 1

1) "codexam"

2) "subham"

2.12.LREM

This command removes the specified number of occurrences of the specified value from the list.


lpush user:1 "subham"

lpush user:1 "codexam"

lpush user:1 "subham"

lpush user:1 "codexam"

lrem user:1 2 "subham"

(integer) 2

lrange user:1 0 1

1) "codexam"

2) "codexam"

2.13.RPOPLPUSH

This command removes the last element from the source list and pushes it to the destination list.


lpush user:1 "subham"

lpush user:1 "codexam"

rpoplpush user:1 user:2

"subham"

lrange user:1 0 1

1) "codexam"

lrange user:2 0 1

1) "subham"

2.14.BRPOP

This command is similar to rpop, but it blocks the connection until an element is available or the timeout is reached.


lpush user:1 "subham"

lpush user:1 "codexam"

brpop user:1 10

1) "user:1"

2) "codexam"

It will block the connection for 10 seconds and then return the element. If no element is available, it will return nil.

2.15.BLPOP

This command is similar to lpop, but it blocks the connection until an element is available or the timeout is reached.


lpush user:1 "subham"

lpush user:1 "codexam"

blpop user:1 10

1) "user:1"

2) "codexam"

It will block the connection for 10 seconds and then return the element. If no element is available, it will return nil.

2.16.BRPOPLPUSH

This command is similar to rpoplpush, but it blocks the connection until an element is available or the timeout is reached.


lpush user:1 "subham"

lpush user:1 "codexam"

brpoplpush user:1 user:2 10

"subham"

It will block the connection for 10 seconds and then return the element. If no element is available, it will return nil.

Set Data Structure:

A set data structure is a collection of unordered, unique elements. It is similar to a set in mathematics. The set data structure is often used to implement other data structures like queues and stacks.

Set Operations

Here are some operations performed on a set:

OperationElement
Add1
Add2
Add3
Remove3
Remove2
Remove1

Cli Commands

3.1.SADD

This command adds the specified member to the set.

sadd user:1 "subham"
sadd user:1 "codexam"
sadd user:1 "subham"

smembers user:1

1) "subham"

2) "codexam"

Visualize the set in the Redis Commander.

IndexElement
0subham
1codexam

3.2.SREM

This command removes the specified member from the set.

sadd user:1 "subham"
sadd user:1 "codexam"

srem user:1 "subham"

smembers user:1

1) "codexam"

3.3.SISMEMBER

This command checks if the specified member is present in the set.

sadd user:1 "subham"
sadd user:1 "codexam"

sismember user:1 "subham"

(integer) 1

3.4.SMEMBERS

This command returns all the members of the set.


sadd user:1 "subham"
sadd user:1 "codexam"

smembers user:1

1) "subham"

2) "codexam"

3.5.SPOP

This command removes and returns a random member from the set.


sadd user:1 "subham"

sadd user:1 "codexam"

spop user:1

"codexam"

3.6.SRANDMEMBER

This command returns a random member from the set.


sadd user:1 "subham"

sadd user:1 "codexam"

srandmember user:1

"codexam"

3.7.SMOVE

This command moves the specified member from one set to another.


sadd user:1 "subham"

sadd user:1 "codexam"

sadd user:2 "xamcodexam"

smove user:1 user:2 "subham"

smembers user:1

1) "codexam"

smembers user:2

1) "xamcodexam"

2) "subham"

3.8.SCARD

This command returns the number of members in the set.


sadd user:1 "subham"

sadd user:1 "codexam"

scard user:1 


(integer) 2

3.9.SINTER

This command returns the intersection of all the sets specified.


sadd user:1 "subham"

sadd user:1 "codexam"

sadd user:2 "xamcodexam"

sinter user:1 user:2

1) "subham"

3.10.SUNION

This command returns the union of all the sets specified.


sadd user:1 "subham"

sadd user:1 "codexam"

sadd user:2 "xamcodexam"

sunion user:1 user:2

1) "subham"

2) "codexam"

3) "xamcodexam"

3.11.SDIFF

This command returns the difference between the first set and all the other sets specified.


sadd user:1 "subham"

sadd user:1 "codexam"

sadd user:2 "xamcodexam"

sdiff user:1 user:2

1) "codexam"

3.12.SINTERSTORE

This command stores the intersection of all the sets specified.


sadd user:1 "subham"

sadd user:1 "codexam"

sadd user:2 "xamcodexam"

sinterstore user:3 user:1 user:2

(integer) 1

smembers user:3

1) "subham"

3.13.SUNIONSTORE

This command stores the union of all the sets specified.


sadd user:1 "subham"

sadd user:1 "codexam"

sadd user:2 "xamcodexam"

sunionstore user:3 user:1 user:2


(integer) 3

smembers user:3

1) "subham"

2) "codexam"

3) "xamcodexam"

3.14.SDIFFSTORE

This command stores the difference between the first set and all the other sets specified.


sadd user:1 "subham"

sadd user:1 "codexam"

sadd user:2 "xamcodexam"

sdiffstore user:3 user:1 user:2

(integer) 1

3.15.SSCAN

This command scans the set for members matching the specified pattern.


sadd user:1 "subham"

sadd user:1 "codexam"

sscan user:1 0 match "sub*"

1) "0"

2) 1) "subham"

Hash Data Structure:

A hash data structure is a collection of key-value pairs. It is similar to a hash table in other programming languages. The hash data structure is often used to implement other data structures like queues and stacks.

Cli Commands

4.1.HSET

This command sets the specified field in the hash to the specified value.


hset user:1 name "subham"

hset user:1 email "subham@gmail.com"

Visualize the hash in the Redis Commander.

FieldValue
namesubham
emailcodexam

4.2.HGET

This command returns the value of the specified field in the hash.


hset user:1 name "subham"

hset user:1 email "

hget user:1 name

"subham"

4.3.HGETALL

This command returns all the fields and values of the hash.


hset user:1 name "subham"

hset user:1 email "subham@gmail.com"

hgetall user:1

1) "name"

2) "subham"

3) "email"

4) "subham@gmail.com"

4.4.HDEL

This command deletes the specified field from the hash.


hset user:1 name "subham"

hset user:1 email "subham@gmail.com"

hdel user:1 email

(integer) 1

hgetall user:1

1) "name"

2) "subham"

4.5.HEXISTS

This command checks if the specified field exists in the hash.


hset user:1 name "subham"

hset user:1 role "admin"

hexists user:1 role

(integer) 1

4.6.HKEYS

This command returns all the fields of the hash.


hset user:1 name "subham"

hset user:1 role "admin"

hkeys user:1

1) "name"

2) "role"

4.7.HVALS

This command returns all the values of the hash.


hset user:1 name "subham"

hset user:1 role "admin"

hvals user:1

1) "subham"

2) "admin"

4.8.HLEN

This command returns the number of fields in the hash.


hset user:1 name "subham"

hset user:1 role "admin"

hlen user:1

(integer) 2

4.9.HINCRBY

This command increments the specified field by the specified value.


hset user:1 age 20

hincrby user:1 age 5

(integer) 25

4.10.HINCRBYFLOAT

This command increments the specified field by the specified value.


hset user:1 age 20

hincrbyfloat user:1 age 5.5

"25.5"

4.11.HMSET

This command sets the specified fields to their respective values in the hash.


hmset user:1 name "subham" role "admin"

hgetall user:1

1) "name"

2) "subham"

3) "role"

4) "admin"

4.12.HMGET

This command returns the values of the specified fields in the hash.


hmset user:1 name "subham" role "admin"

hmget user:1 name role

1) "subham"

2) "admin"

4.13.HSETNX

This command sets the specified field to the specified value if the field does not exist in the hash.


hsetnx user:1 name "subham"

hsetnx user:1 name "codexam"

(integer) 0

4.14.HSTRLEN

This command returns the length of the value of the specified field in the hash.


hset user:1 name "subham"

hstrlen user:1 name

(integer) 6

4.15.HSCAN

This command scans the hash for fields matching the specified pattern.


hset user:1 name "subham"

hset user:1 role "admin"

hscan user:1 0 match "na*"

1) "0"

2) 1) "name"

   2) "subham"

Sorted Set Operations with Redis

A sorted set data structure is a collection of unique elements sorted by a score. It is similar to a sorted list in other programming languages. Priority queues are often implemented using a sorted set data structure.

Sorted Set Operations

Here are some operations performed on a sorted set:

OperationElementScore
Add11
Add22
Add33
Remove33
Remove22
Remove11

Cli Commands

5.1.ZADD

This command adds the specified member to the sorted set with the specified score.


zadd user:1 1 "subham"

zadd user:1 2 "codexam"

zadd user:1 3 "xamcodexam"

zrange user:1 0 -1 withscores

1) "subham"

2) "1"

3) "codexam"

4) "2"

5) "xamcodexam"

6) "3"

Visualize the sorted set in the Redis Commander.

IndexElementScore
0subham1
1codexam2
2xamcodexam3

5.2.ZREM

This command removes the specified member from the sorted set.


zadd user:1 1 "subham"

zadd user:1 2 "codexam"

zadd user:1 3 "xamcodexam"

zrem user:1 "subham"

zrange user:1 0 -1 withscores

1) "codexam"

2) "2"

3) "xamcodexam"

4) "3"

5.3.ZSCORE

This command returns the score of the specified member in the sorted set.


zadd user:1 1 "subham"

zadd user:1 2 "codexam"

zadd user:1 3 "xamcodexam"

zscore user:1 "subham"

"1"

5.4.ZRANGE

This command returns the specified range of elements from the sorted set.


zadd user:1 1 "subham"

zadd user:1 2 "codexam"

zadd user:1 3 "xamcodexam"

zrange user:1 0 -1 withscores

1) "subham"

2) "1"

3) "codexam"

4) "2"

5) "xamcodexam"

6) "3"

5.5.ZREVRANGE

This command returns the specified range of elements from the sorted set in reverse order.


zadd user:1 1 "subham"

zadd user:1 2 "codexam"

zadd user:1 3 "xamcodexam"

zrevrange user:1 0 -1 withscores

1) "xamcodexam"

2) "3"

3) "codexam"

4) "2"

5) "subham"

6) "1"

5.6.ZRANGEBYSCORE

This command returns the specified range of elements from the sorted set by score.


zadd user:1 1 "subham"

zadd user:1 2 "codexam"


zadd user:1 3 "xamcodexam"

zrangebyscore user:1 1 2 withscores

1) "subham"

2) "1"

3) "codexam"

4) "2"

5.7.ZREVRANGEBYSCORE

This command returns the specified range of elements from the sorted set by score in reverse order.


zadd user:1 1 "subham"

zadd user:1 2 "codexam"


zadd user:1 3 "xamcodexam"

zrevrangebyscore user:1 2 1 withscores

1) "codexam"

2) "2"

3) "subham"

4) "1"

5.8.ZCARD

This command returns the number of elements in the sorted set.


zadd user:1 1 "subham"

zadd user:1 2 "codexam"


zadd user:1 3 "xamcodexam"

zcard user:1

(integer) 3

5.9.ZCOUNT

This command returns the number of elements in the sorted set with a score between the specified minimum and maximum.


zadd user:1 1 "subham"

zadd user:1 2 "codexam"

zadd user:1 3 "xamcodexam"

zcount user:1 1 2

(integer) 2

5.10.ZINCRBY

This command increments the score of the specified member in the sorted set by the specified value.


zadd user:1 1 "subham"

zincrby user:1 2 "subham"


zrange user:1 0 -1 withscores

1) "subham"

2) "3"

5.11.ZLEXCOUNT

This command returns the number of elements in the sorted set between the specified minimum and maximum.


zadd user:1 1 "subham"

zadd user:1 2 "codexam"

zadd user:1 3 "xamcodexam"

zlexcount user:1 - +

(integer) 3

5.12.ZRANGEBYLEX

This command returns the specified range of elements from the sorted set by lexicographical order.


zadd user:1 1 "subham"

zadd user:1 2 "codexam"

zadd user:1 3 "xamcodexam"

zrangebylex user:1 - +

1) "codexam"

2) "subham"

3) "xamcodexam"

5.13.ZREVRANGEBYLEX

This command returns the specified range of elements from the sorted set by lexicographical order in reverse order.


zadd user:1 1 "subham"

zadd user:1 2 "codexam"

zadd user:1 3 "xamcodexam"


zrevrangebylex user:1 + -

1) "xamcodexam"

2) "subham"

3) "codexam"

5.14.ZREMRANGEBYLEX

This command removes the specified range of elements from the sorted set by lexicographical order.


zadd user:1 1 "subham"

zadd user:1 2 "codexam"

zadd user:1 3 "xamcodexam"


zremrangebylex user:1 - +

(integer) 3

5.15.ZREMRANGEBYRANK

This command removes the specified range of elements from the sorted set by index.


zadd user:1 1 "subham"

zadd user:1 2 "codexam"


zadd user:1 3 "xamcodexam"

zremrangebyrank user:1 0 1

(integer) 2

5.16.ZREMRANGEBYSCORE

This command removes the specified range of elements from the sorted set by score.


zadd user:1 1 "subham"

zadd user:1 2 "codexam"


zadd user:1 3 "xamcodexam"

zremrangebyscore user:1 1 2

(integer) 2

This command removes the specified range of elements from the sorted set by score.

zadd score 1 "subham"
zadd score 2 "codexam"
zadd score 3 "xamcodexam"

zrange score 0 -2 withscores

1) "subham"
2) "1"
3) "codexam"
4) "2"

5.17.ZUNIONSTORE

This command stores the union of all the sorted sets specified.


zadd user:1 1 "subham"

zadd user:1 2 "codexam"

zadd user:2 3 "xamcodexam"

zunionstore user:3 2 user:1 user:2

(integer) 3

zrange user:3 0 -1 withscores

1) "subham"

2) "1"

3) "codexam"

4) "2"

5) "xamcodexam"

6) "3"

5.18.ZINTERSTORE

This command stores the intersection of all the sorted sets specified.


zadd user:1 1 "subham"

zadd user:1 2 "codexam"

zadd user:2 3 "xamcodexam"

zinterstore user:3 2 user:1 user:2

(integer) 1

zrange user:3 0 -1 withscores

1) "xamcodexam"

2) "3"

5.19.ZSCAN

This command scans the sorted set for members matching the specified pattern.


zadd user:1 1 "subham"

zadd user:1 2 "codexam"

zadd user:2 3 "xamcodexam"

zscan user:1 0 match "sub*"

1) "0"

2) 1) "subham"

   2) "1"

5.20.ZRANK

This command returns the rank of the specified member in the sorted set.


zadd user:1 1 "subham"
zadd user:1 2 "codexam"

zrank user:1 "subham"

(integer) 0

Note: Normally, sets are used to store unique elements. However, sorted sets allow you to store duplicate elements. This is because each element in a sorted set is associated with a score, which makes it unique and normal sets are unordered.

REDIS STREAMS OPERATIONS

Redis Streams is a new feature in Redis 5.0 that allows you to store multiple fields and values in a single key. It is similar to a log file in other programming languages. Redis Streams is often used to implement other data structures like queues and stacks.

Cli Commands

6.1.XADD

This command adds the specified fields and values to the stream.

It returns time stamp of the message.


xadd user:1 * name "subham" role "admin" 

xadd user:1 * name "codexam" role "admin"

xadd user:1 * name "xamcodexam" role "admin"

xrange user:1 - +

1) 1) "1578060000000-0"

   2) 1) "name"

      2) "subham"

      3) "role"

      4) "admin"

2) 1) "1578060000001-0"


    2) 1) "name"

        2) "codexam"

        3) "role"

        4) "admin"

3) 1) "1578060000002-0"


    2) 1) "name"

        2) "xamcodexam"

        3) "role"

        4) "admin"

6.2.XLEN

This command returns the number of messages in the stream.


xadd user:1 * name "subham" role "admin"

xadd user:1 * name "codexam" role "admin"

xadd user:1 * name "xamcodexam" role "admin"

xlen user:1

(integer) 3

6.3.XRANGE

This command returns the specified range of messages from the stream.


xadd user:1 * name "subham" role "admin"

xadd user:1 * name "codexam" role "admin"

xadd user:1 * name "xamcodexam" role "admin"

xrange user:1 - +

1) 1) "1578060000000-0"

   2) 1) "name"

      2) "subham"

      3) "role"

      4) "admin"

2) 1) "1578060000001-0"


    2) 1) "name"

        2) "codexam"

        3) "role"

        4) "admin"


3) 1) "1578060000002-0"


    2) 1) "name"

        2) "xamcodexam"

        3) "role"

        4) "admin"

6.4.XREVRANGE

This command returns the specified range of messages from the stream in reverse order.


xadd user:1 * name "subham" role "admin"

xadd user:1 * name "codexam" role "admin"

xadd user:1 * name "xamcodexam" role "admin"

xrevrange user:1 + -

1) 1) "1578060000002-0"


    2) 1) "name"

        2) "xamcodexam"

        3) "role"

        4) "admin"

2) 1) "1578060000001-0"


    2) 1) "name"

        2) "codexam"

        3) "role"

        4) "admin"


3) 1) "1578060000000-0"


    2) 1) "name"

        2) "subham"

        3) "role"

        4) "admin"

6.5.XREAD

This command reads the specified number of messages from the stream.


xadd user:1 * name "subham" role "admin"

xadd user:1 * name "codexam" role "admin"

xadd user:1 * name "xamcodexam" role "admin"

xread count 2 streams user:1 0-0

1) 1) "user:1"

   2) 1) 1) "1578060000000-0"

         2) 1) "name"

            2) "subham"

            3) "role"

            4) "admin"

      2) 1) "1578060000001-0"


            2) 1) "name"

                2) "codexam"

                3) "role"

                4) "admin"

2) 1) "user:1"


     2) 1) 1) "1578060000002-0"

             2) 1) "name"

                  2) "xamcodexam"

                  3) "role"

                  4) "admin"

6.6.XREADGROUP

This command reads the specified number of messages from the stream in a consumer group.


xadd user:1 * name "subham" role "admin"

xadd user:1 * name "codexam" role "admin"

xadd user:1 * name "xamcodexam" role "admin"


xgroup create user:1 user:1 0-0 mkstream


xreadgroup group user:1 user:1 count 2 streams user:1 0-0

1) 1) "user:1"

   2) 1) 1) "1578060000000-0"

         2) 1) "name"

            2) "subham"

            3) "role"

            4) "admin"

      2) 1) "1578060000001-0"


            2) 1) "name"

                2) "codexam"

                3) "role"

                4) "admin"

2) 1) "user:1"


        2) 1) 1) "1578060000002-0"

                2) 1) "name"

                    2) "xamcodexam"

                    3) "role"

                    4) "admin"

6.7.XGROUP

This command creates a consumer group.


xadd user:1 * name "subham" role "admin"

xadd user:1 * name "codexam" role "admin"

xadd user:1 * name "xamcodexam" role "admin"


xgroup create user:1 user:1 0-0 mkstream

OK

6.8.XACK

This command acknowledges the specified messages in the stream.


xadd user:1 * name "subham" role "admin"

xadd user:1 * name "codexam" role "admin"

xadd user:1 * name "xamcodexam" role "admin"


xgroup create user:1 user:1 0-0 mkstream

xreadgroup group user:1 user:1 count 2 streams user:1 0-0

xack user:1 user:1 1578060000000-0 1578060000001-0

(integer) 2

6.9.XCLAIM

This command claims the specified messages in the stream.


xadd user:1 * name "subham" role "admin"

xadd user:1 * name "codexam" role "admin"

xadd user:1 * name "xamcodexam" role "admin"


xgroup create user:1 user:1 0-0 mkstream

xreadgroup group user:1 user:1 count 2 streams user:1 0-0

xclaim user:1 user:1 0-0 1578060000000-0 1578060000001-0

1) 1) "user:1"

   2) 1) 1) "1578060000000-0"

         2) 1) "name"

            2) "subham"

            3) "role"

            4) "admin"

      2) 1) "1578060000001-0"


            2) 1) "name"

                2) "codexam"

                3) "role"

                4) "admin"

2) 1) "user:1"


          2) 1) 1) "1578060000002-0"

                    2) 1) "name"

                        2) "xamcodexam"

                        3) "role"

                        4) "admin"

6.10.XDEL

This command deletes the specified messages in the stream.


xadd user:1 * name "subham" role "admin"

xadd user:1 * name "codexam" role "admin"


xadd user:1 * name "xamcodexam" role "admin"


xgroup create user:1 user:1 0-0 mkstream

xreadgroup group user:1 user:1 count 2 streams user:1 0-0

xdel user:1 1578060000000-0 1578060000001-0

(integer) 2

6.11.XTRIM

This command trims the specified messages in the stream.


xadd user:1 * name "subham" role "admin"

xadd user:1 * name "codexam" role "admin"


xadd user:1 * name "xamcodexam" role "admin"

xtrim user:1 maxlen 2

(integer) 1

6.12.XINFO

This command returns information about the stream.


xadd user:1 * name "subham" role "admin"

xadd user:1 * name "codexam" role "admin"

xinfo stream user:1


1) 1) "length"

   2) (integer) 2

2) 1) "radix-tree-keys"

    2) (integer) 1

3) 1) "radix-tree-nodes"


    2) (integer) 2

4) 1) "groups"


    2) (integer) 1


5) 1) "last-generated-id"


    2) "1578060000001-0"

6) 1) "first-entry"


    2) 1) "1578060000000-0"

       2) 1) "name"

          2) "subham"

          3) "role"

          4) "admin"

7) 1) "last-entry"


    2) 1) "1578060000001-0"

       2) 1) "name"

          2) "codexam"

          3) "role"

          4) "admin"

6.13.XSETID

This command sets the id of the stream.


xadd user:1 * name "subham" role "admin"

xadd user:1 * name "codexam" role "admin"


xadd user:1 * name "xamcodexam" role "admin"


xgroup create user:1 user:1 0-0 mkstream

xreadgroup group user:1 user:1 count 2 streams user:1 0-0

xsetid user:1 1578060000000-0

OK

6.14.XREWRITE

This command rewrites the stream to optimize memory usage.


xadd user:1 * name "subham" role "admin"

xadd user:1 * name "codexam" role "admin"


xadd user:1 * name "xamcodexam" role "admin"


xgroup create user:1 user:1 0-0 mkstream

xreadgroup group user:1 user:1 count 2 streams user:1 0-0

xrewrite user:1

(integer) 1

Redis Bitmaps

A bitmap data structure is a collection of bits. It is similar to an array in other programming languages. Bitmaps are often used to implement other data structures like sets and bloom filters.

Cli Commands

7.1.SETBIT

This command sets the bit at the specified index in the bitmap to either 1 or 0.


SETBIT pings:2024-01-01-00:00 123 1

(integer) 0

SETBIT pings:2024-01-01-00:00 456 1

(integer) 0

7.2.GETBIT

This command returns the value of the bit at the specified index in the bitmap.


SETBIT pings:2024-01-01-00:00 123 1

(integer) 0


GETBIT pings:2024-01-01-00:00 123

(integer) 1

7.3.BITCOUNT

This command returns the number of bits set to 1 in the bitmap.


SETBIT pings:2024-01-01-00:00 123 1

(integer) 0


SETBIT pings:2024-01-01-00:00 456 1

(integer) 0


BITCOUNT pings:2024-01-01-00:00

(integer) 2

7.4.BITOP

This command performs a bitwise operation between the bitmaps and stores the result in the destination bitmap.


SETBIT pings:2024-01-01-00:00 123 1

(integer) 0


SETBIT pings:2024-01-01-00:00 456 1

(integer) 0


BITOP AND pings:2024-01-01-00:00 pings:2024-01-01-00:00 pings:2024-01-01-00:00

(integer) 2

7.5.BITPOS

This command returns the index of the first bit set to 1 or 0 in the bitmap.


SETBIT pings:2024-01-01-00:00 123 1

(integer) 0


BITPOS pings:2024-01-01-00:00 1

(integer) 123

7.6.BITFIELD

This command performs a bitwise operation between the bitmaps and stores the result in the destination bitmap.


BITFIELD pings:2024-01-01-00:00 INCRBY i5 100 1 GET u4 0

1) (integer) 0

2) (integer) 0

3) (integer) 0

4) (integer) 0
.....

Geospatial Operations

A geospatial data structure is a collection of elements with a geospatial location. It is similar to a map in other programming languages. Geospatial data structures are often used to implement other data structures like geohashes and geofences.

Cli Commands

8.1.GEOADD

This command adds the specified elements to the geospatial data structure.


geoadd user:1 88.3639 22.5726 "subham"

(integer) 1

geoadd user:1 88.3639 22.5726 "codexam"

(integer) 1

8.2.GEOPOS

This command returns the longitude and latitude of the specified elements in the geospatial data structure.


geoadd user:1 88.3639 22.5726 "subham"

(integer) 1

geoadd user:1 88.3639 22.5726 "codexam"

(integer) 1

geopos user:1 "subham" "codexam"

1) 1) "88.36389994668960571"

   2) "22.57260005994199279"

2) 1) "88.36389994668960571"

   2) "22.57260005994199279"

8.3.GEODIST

This command returns the distance between the specified elements in the geospatial data structure.


geoadd user:1 88.3639 22.5726 "subham"

(integer) 1

geoadd user:1 88.3639 22.5726 "codexam"

(integer) 1

geodist user:1 "subham" "codexam" km


"0.0000"

8.4.GEORADIUS

This command returns the elements within the specified radius in the geospatial data structure.


geoadd user:1 88.3639 22.5726 "subham"

(integer) 1

geoadd user:1 88.3639 22.5726 "codexam"

(integer) 1

georadius user:1 88.3639 22.5726 100 km

1) "subham"

2) "codexam"

8.5.GEORADIUSBYMEMBER

This command returns the elements within the specified radius in the geospatial data structure.


geoadd user:1 88.3639 22.5726 "subham"

(integer) 1

geoadd user:1 88.3639 22.5726 "codexam"

(integer) 1

georadiusbymember user:1 "subham" 100 km

1) "subham"

2) "codexam"

8.6.GEOHASH

This command returns the geohash of the specified elements in the geospatial data structure.


geoadd user:1 88.3639 22.5726 "subham"

(integer) 1

geoadd user:1 88.3639 22.5726 "codexam"

(integer) 1

geohash user:1 "subham" "codexam"

1) "tqg0y0y0y0y0"

2) "tqg0y0y0y0y0"

8.7.GEOSEARCH

This command returns the elements matching the specified query in the geospatial data structure.


geoadd user:1 88.3639 22.5726 "subham"

(integer) 1

geoadd user:1 88.3639 22.5726 "codexam"

(integer) 1

geosearch user:1 frommember "subham" count 2

1) 1) "subham"

   2) 1) "88.36389994668960571"

      2) "22.57260005994199279"

2) 1) "codexam"

   2) 1) "88.36389994668960571"

      2) "22.57260005994199279"

8.8.GEOSEARCHSTORE

This command stores the elements matching the specified query in the geospatial data structure.


geoadd user:1 88.3639 22.5726 "subham"

(integer) 1

geoadd user:1 88.3639 22.5726 "codexam"

(integer) 1

geosearchstore user:2 frommember "subham" count 2

(integer) 2

Probabilistic Data Structures

You can use probabilistic data structures to store elements with a probability of false positives. It is similar to a set in other programming languages. Probabilistic data structures are often used to implement other data structures like bloom filters.

READ HERE: https://redis.io/docs/data-types/probabilistic/t-digest/

Time Series Data Structures

A time series data structure is a collection of elements with a timestamp. It is similar to a map in other programming languages. Time series data structures are often used to implement other data structures like time series.

READ HERE: https://redis.io/docs/data-types/timeseries/

Pub/Sub

Redis Pub/Sub implements the messaging system where the senders (publishers) sends the messages while the receivers (subscribers) receive them. The link between the publishers and subscribers is called channel.

  • Step 1: Open two terminals.

  • Open redis-cli in the first terminal and also in the second terminal. (steps are the given below)

    • docker ps (to get the container id)

    • if not running then run the container using docker start container_id or docker start redis-stack and then docker exec -it redis-stack redis-cli or docker exec -it container_id bash and then redis-cli to open redis-cli.

  • Now write the following command in the first terminal to subscribe to the channel.

SUBSCRIBE notifications
  • Now write the following command in the second terminal to publish a message to the channel.
PUBLISH notifications "Hello, World!"
  • You will see the following output in the first terminal.
Reading messages... (press Ctrl-C to quit)

1) "subscribe"
2) "notification"
3) (integer) 1
1) "message"
2) "notification"
3) "subham"

Reading messages... (press Ctrl-C to quit)

It is beneficial when you want to scale your socket.io application. You can use redis pub/sub to communicate between multiple socket.io servers.

Some Usecases of Redis Pub/Sub

  • Chat application

  • Real-time analytics

  • Real-time notifications

  • Distributed locks

  • Distributed cache invalidation

  • Distributed session management

  • Distributed job queue

  • Distributed event-driven programming

  • Distributed publish/subscribe system

  • Distributed system monitoring

  • Distributed system coordination

  • Distributed system configuration

Cli Commands

9.1.SUBSCRIBE

This command subscribes to the specified channels.


SUBSCRIBE notifications

Reading messages... (press Ctrl-C to quit)

1) "subscribe"

2) "notifications"

3) (integer) 1

9.2.UNSUBSCRIBE

This command unsubscribes from the specified channels.


SUBSCRIBE notifications

Reading messages... (press Ctrl-C to quit)

1) "subscribe"

2) "notifications"

3) (integer) 1

UNSUBSCRIBE notifications

Reading messages... (press Ctrl-C to quit)

1) "unsubscribe"

2) "notifications"

3) (integer) 0

9.3.PUBLISH

This command publishes the specified message to the specified channel.


SUBSCRIBE notifications

Reading messages... (press Ctrl-C to quit)

1) "subscribe"

2) "notifications"

3) (integer) 1

PUBLISH notifications "Hello, World!"

(integer) 1

1) "message"

2) "notifications"

3) "Hello, World!"

9.4.PUBSUB

This command returns information about the channels.


SUBSCRIBE notifications

Reading messages... (press Ctrl-C to quit)

1) "subscribe"

2) "notifications"

3) (integer) 1

PUBSUB CHANNELS

1) "notifications"

There are a lot of other commands in redis-cli. You can check them out by typing help in redis-cli.

Scale A Node.js Application With Redis

  1. Step 1. Initialize a Node.js project.
  • Copy the template what I already created for you.

  • npm i

  • replace the .env file with your own database credentials.

  • npm start to run the project.

  1. Third party api: https://jsonplaceholder.typicode.com/todos
  • We will try to speed up the api response time using redis.

  • npm i axios to install axios.

  1. Open server/src folder makes a new file todos.ts
import express from "express";
import axios from "axios";

const todos = express.Router();

todos.get("/todos", async (req, res) => {
  try {
    const { data } = await axios.get("https://jsonplaceholder.typicode.com/todos");
    res.json(data);
  } catch (error:any) {
    console.error("Error fetching todos:", error.message);
    res.status(500).json({ error: "Internal Server Error" });
  }
});

export default todos;
  1. Open server/src/app.ts and add the route to the express app.
app.use("/api/v1/", todos);
  1. now run npm run dev and go to http://localhost:5050/api/v1/todos to see the response.

  2. I have already setup Morgan for logging for response times, however, you can open Postman and check the response times.

  3. In the first fetching it takes 403ms to fetch the data from the api, and after multiple requests, it takes 120ms–351ms to fetch the data from the api.

  4. Now try to implement caching using redis.

  • you can find the client.ts file in the server/src folder.
        import Redis from "ioredis";

        const client = new Redis(
          {
           host: 'localhost', // replace with your host, if not localhost
           port: 6379  // replace with your port, if not 6379
          }
         );
        export default client;
  • Now open server/src/todos.ts and import the redis client.
       import client from "./client";

       todos.get("/todos", async (req, res) => {
            try {
              const todos = await client.get("todos");
              if (todos) {
                console.log("Fetching from redis");
                return res.json(JSON.parse(todos));
              }
              const { data } = await axios.get("https://jsonplaceholder.typicode.com/todos");
              client.set("todos", JSON.stringify(data));
              console.log("Fetching from api");
              res.json(data);
            } catch (error:any) {
              console.error("Error fetching todos:", error.message);
              res.status(500).json({ error: "Internal Server Error" });
            }
       });
  • Now run npm run dev and go to http://localhost:5050/api/v1/todos to see the response.

  • In the first fetching it takes 403ms to fetch the data from the api, and after multiple requests, it takes 0ms–1ms to fetch the data from the redis.

  • you can also add client.set("todos", JSON.stringify(data), "EX", 10) to set the expiration time of the key.

  • Now open you redis-cli and run keys * to see the keys and ttl todos to see the expiration time of the key.

  • If you open redis-stack container, you can see the todos with data.

  • Now you can scale your application by adding multiple instances of the application and using redis to cache the data.

Thank you for reading this blog and stay tuned for more. If you have any questions or feedback, feel free to leave a comment below or contact me directly. I would love to hear from you. 🙌

If you are looking for a freelance web developer who can help you with your projects, you can also contact me. I can help you build fast, scalable, and user-friendly web applications. 💯

I look forward to hearing from you and collaborating with you on your projects. 🙌

Until next time, happy coding! 👋