What is Redis? | Blog | Convesio

Redis is an open-source, in-memory data structure store used as a database, cache, and message broker. It offers high performance, flexibility, and a wide range of data structures. This guide provides an in-depth look into Redis commands, data structures, and features to help you utilize its full potential.


1. Getting Started with Redis

Installation

  • Linux: Use the package manager (e.g., sudo apt install redis or sudo yum install redis).
  • Windows: Download the precompiled binaries from the Redis official site.
  • Docker: Run docker pull redis and start the container.

Start the Redis server with redis-server and connect using the redis-cli command-line tool.


2. Redis Commands by Data Type

2.1 Strings

Strings are the simplest data type in Redis. Each key stores a single value.

How strings are stored:

A string in Redis can hold any type of data, including text, binary, or serialized objects. It is stored as a dynamic string that resizes itself based on the stored value. Redis uses efficient memory allocation techniques to minimize space usage.

Commands:

  • SET: Stores a value associated with a key.

    SET key value
    

    Example:

    SET name "Ajay"
    
  • SET with expiration: Stores a value with a time-to-live (TTL) in seconds.

    SET key value EX seconds
    

    Example:

    SET name "Ajay" EX 10
    

    (The key name will expire after 10 seconds.)

  • GET: Retrieves the value of a key.

    GET key
    

    Example:

    GET name
    
  • DEL: Deletes a key and its value.

    DEL key
    

    Example:

    DEL name
    

2.2 Hashes

Hashes are used to store multiple field-value pairs under a single key. Internally, Redis uses a hash table to manage these fields efficiently.

How Hashes Are Stored:

Hashes are represented as a hash table or a ziplist, depending on the size and number of fields. For small hashes, Redis uses a ziplist to save memory. For larger hashes, it switches to a hash table for faster lookups.

Commands:

  • HSET: Sets a field-value pair in a hash.

    HSET key field value
    

    Example:

    HSET user name "Ajay"
    HSET user age "27"
    
  • HGET: Retrieves the value of a specific field in a hash.

    HGET key field
    

    Example:

    HGET user name
    
  • HGETALL: Retrieves all field-value pairs in a hash.

    HGETALL key
    

    Example:

    HGETALL user
    
  • HDEL: Deletes a specific field in a hash.

    HDEL key field
    

    Example:

    HDEL user name
    

Example of Hash Storage:

+------------------+      +--------------------+
|    Redis Key     |      |   Hash Key-Value   |
|------------------|      |--------------------|
| user             | ---> | name: "Ajay"       |
|                  |      | age: "27"          |
+------------------+      +--------------------+

2.3 Lists

Lists are ordered collections of strings. Internally, Redis stores lists as either a linked list or a compressed list (ziplist), depending on their size. For small lists, Redis uses ziplists to save memory, while larger lists are stored as linked lists for better performance.

Performance Characteristics:

  • LPUSH/RPUSH: Both operations have O(1) complexity since they involve adding elements to the head or tail of the list.
  • LPOP/RPOP: Similarly, removing elements from the head or tail also has O(1) complexity.
  • LINDEX: Retrieving an element by index has O(N) complexity as it may require traversal of the list.
  • LRANGE: Fetching a range of elements has O(S+N) complexity, where S is the starting point and N is the number of elements fetched.

Commands:

  • LPUSH: Inserts a value at the head of a list.

    LPUSH key value
    

    Example:

    LPUSH tasks "Task1"
    
  • RPUSH: Inserts a value at the tail of a list.

    RPUSH key value
    

    Example:

    RPUSH tasks "Task2"
    
  • LPOP: Removes and returns the first element.

    LPOP key
    

    Example:

    LPOP tasks
    
  • RPOP: Removes and returns the last element.

    RPOP key
    

    Example:

    RPOP tasks
    
  • LINDEX: Retrieves an element by index.

    LINDEX key index
    

    Example:

    LINDEX tasks 0
    
  • LRANGE: Retrieves a range of elements.

    LRANGE key start stop
    

    Example:

    LRANGE tasks 0 -1
    

2.4 Pub/Sub Messaging

Redis provides Publish/Subscribe (Pub/Sub) messaging to facilitate real-time communication between multiple clients. This model allows one or more clients (subscribers) to listen to specific channels and receive messages sent by publishers.

How Pub/Sub Works

  • Channels: A channel is a named medium through which messages are transmitted. Subscribers listen to specific channels, and publishers send messages to these channels.
  • Message Delivery: When a message is published to a channel, Redis immediately delivers it to all clients subscribed to that channel. There is no storage of messages; they are delivered in real-time.
  • Multiple Channels: A subscriber can subscribe to multiple channels simultaneously. Each channel operates independently, allowing efficient segmentation of messages.

Commands:

  • SUBSCRIBE: Subscribes to one or more channels.
    SUBSCRIBE news sports
    
  • PUBLISH: Publishes a message to a channel.
    PUBLISH news "Breaking news!"
    
  • UNSUBSCRIBE: Unsubscribes from one or more channels.
    UNSUBSCRIBE news
    

Example with Multiple Channels:

Suppose there are two channels: news and sports. A subscriber can listen to both channels, and publishers can send different messages to each.

Subscriber Example:

const subscriber = new Redis();
subscriber.subscribe("news", "sports");
subscriber.on("message", (channel, message) => {
  console.log(`Received message: '${message}' from channel: '${channel}'`);
});

Publisher Example:

const publisher = new Redis();
await publisher.publish("news", "Breaking News: Redis 7.0 released!");
await publisher.publish("sports", "Live Update: Team A wins the championship!");

Output:

Received message: 'Breaking News: Redis 7.0 released!' from channel: 'news'
Received message: 'Live Update: Team A wins the championship!' from channel: 'sports'

Use Cases:

  • Real-time chat applications.
  • Notifications and alerts.
  • Live updates for dashboards or feeds.

This lightweight messaging system is highly efficient for real-time communication scenarios but does not store messages for later delivery.

Commands:

  • SUBSCRIBE: Subscribes to a channel.

    SUBSCRIBE news
    
  • PUBLISH: Publishes a message to a channel.

    PUBLISH news "Breaking news!"
    
  • UNSUBSCRIBE: Unsubscribes from a channel.


3. Advanced Features

3.1 Transactions

Transactions in Redis allow you to execute multiple commands atomically using the following commands:

  • MULTI: Begins a transaction.
  • EXEC: Executes all queued commands.
  • DISCARD: Cancels the transaction.

Example:

MULTI
SET name "Ajay"
SET age 27
EXEC

3.2 Persistence

Redis supports persistence by saving data to disk.

  • Snapshotting (RDB): Saves the dataset periodically.
  • Append-Only File (AOF): Logs every write operation.

Configure these in the redis.conf file.


4. Use Cases

  • Caching: Store frequently accessed data to reduce database load.
  • Session Storage: Manage user sessions in web applications.
  • Real-Time Analytics: Process and analyze live data streams.
  • Pub/Sub Messaging: Build real-time chat applications.

5. Best Practices

  1. Key Naming: Use a consistent naming convention (e.g., app:user:123).
  2. Set Expirations: Always set expiration for cache keys.
  3. Avoid Heavy Keys: Use smaller values to prevent memory bloat.
  4. Monitor Performance: Use commands like INFO and MONITOR.

6. Example in TypeScript

To interact with Redis in TypeScript, you can use the ioredis package:

Installation

npm install ioredis

Example in TypeScript with ioredis package

import Redis from "ioredis";

// Initialize Redis client
const redis = new Redis();

(async () => {
  // Working with Strings
  await redis.set("name", "Ajay", "EX", 10); // Set with expiration
  const name = await redis.get("name");
  console.log("Name:", name);

  // Working with Hashes
  await redis.hset("user", "name", "Ajay");
  await redis.hset("user", "age", "27");
  const userName = await redis.hget("user", "name");
  console.log("User Name:", userName);

  const userDetails = await redis.hgetall("user");
  console.log("User Details:", userDetails);

  // Working with Lists
  await redis.lpush("tasks", "Task1");
  await redis.rpush("tasks", "Task2");
  const tasks = await redis.lrange("tasks", 0, -1);
  console.log("Tasks:", tasks);

  // Pub/Sub Example
  const subscriber = new Redis();
  const publisher = new Redis();

  subscriber.subscribe("news");
  subscriber.on("message", (channel, message) => {
    console.log(`Received message from ${channel}: ${message}`);
  });
  publisher.publish("news", "Breaking news!");
})();