Table of Contents
Underlying implementation
Source code implementation
Practical Uses in Production
实战实例
Redis 聊天室示例
Home Database Redis How to implement the bottom layer of Redis linked list

How to implement the bottom layer of Redis linked list

May 28, 2023 pm 10:46 PM
redis

Underlying implementation

How to implement the bottom layer of Redis linked list

#The underlying implementation of Redis's list data structure is based on a doubly linked list. A doubly linked list is a common data structure that consists of a series of nodes. Each node is represented by a listNode structure, which contains a pointer prev pointing to the previous node, a pointer next pointing to the next node and a storage A pointer to value value. The doubly linked list in Redis is composed of nodes, each node represents an element and is connected through pointers.

The advantage of a doubly linked list is that insertion and deletion operations can be performed quickly at the head and tail. In Redis, when a new element is inserted into the head or tail of the List, you only need to modify the prev and next pointers of the new node and the prev or next pointer of the original head or tail node to complete the insertion operation. The time is complicated. The degree is O(1). Similarly, when an element is deleted, you only need to modify the next pointer of the previous node or the prev pointer of the next node to complete the deletion operation, and the time complexity is also O(1).

Redis uses other technologies to improve the performance of the List data structure, in addition to using doubly linked lists. For example, when the number of elements in the List exceeds a certain threshold, Redis will convert the List into a compressed list (zip list), which can reduce memory usage and increase access speed. When iterating over a List, Redis uses an iterator to traverse the elements in the List, which can avoid errors caused by modifying the List during the traversal process.

How to implement the bottom layer of Redis linked list

#Redis' list type data structure allows adding or removing elements at the beginning or end of the list, and inserting or deleting elements at specified positions. These operations can be completed in constant time because Redis's doubly linked list implementation supports fast access to head and tail nodes, as well as insertion and deletion of nodes at specified locations.

How to implement the bottom layer of Redis linked list

The following are some common Redis list operations and their time complexity:

  • LPUSH: insert elements at the head, time The complexity is O(1).

  • RPUSH: Insert elements at the end, the time complexity is O(1).

  • LPOP: Delete the header element, the time complexity is O(1).

  • RPOP: Delete the tail elements, the time complexity is O(1).

  • LINDEX: Access the element at the specified position, the time complexity is O(n).

  • LINSERT: Insert an element at the specified position, the time complexity is O(n).

  • LREM: Delete the specified element, the time complexity is O(n).

How to implement the bottom layer of Redis linked list

Source code implementation

The underlying code of the Redis List data structure implements demo, using C language:

typedef struct listNode {
    struct listNode *prev;
    struct listNode *next;
    void *value;
} listNode;

typedef struct list {
    listNode *head;
    listNode *tail;
    unsigned long len;
} list;

list *listCreate(void) {
    list *l;

    if ((l = malloc(sizeof(*l))) == NULL) return NULL;
    l->head = l->tail = NULL;
    l->len = 0;
    return l;
}

void listRelease(list *list) {
    unsigned long len;
    listNode *current, *next;

    current = list->head;
    len = list->len;
    while(len--) {
        next = current->next;
        free(current);
        current = next;
    }
    free(list);
}

listNode *listAddNodeHead(list *list, void *value) {
    listNode *node;

    if ((node = malloc(sizeof(*node))) == NULL) return NULL;
    node->value = value;
    if (list->len == 0) {
        list->head = list->tail = node;
        node->prev = node->next = NULL;
    } else {
        node->prev = NULL;
        node->next = list->head;
        list->head->prev = node;
        list->head = node;
    }
    list->len++;
    return node;
}

listNode *listAddNodeTail(list *list, void *value) {
    listNode *node;

    if ((node = malloc(sizeof(*node))) == NULL) return NULL;
    node->value = value;
    if (list->len == 0) {
        list->head = list->tail = node;
        node->prev = node->next = NULL;
    } else {
        node->prev = list->tail;
        node->next = NULL;
        list->tail->next = node;
        list->tail = node;
    }
    list->len++;
    return node;
}

void listDelNode(list *list, listNode *node) {
    if (node->prev)
        node->prev->next = node->next;
    else
        list->head = node->next;
    if (node->next)
        node->next->prev = node->prev;
    else
        list->tail = node->prev;
    free(node);
    list->len--;
}
Copy after login

The above code implements the basic operations of the List data structure, including creating List, releasing List, inserting elements at the head and tail, and deleting elements. The time complexity of these operations is O(1).

Practical Uses in Production

The Redis List data structure has many wonderful uses in the production environment:

  • Message Queue: Redis List can be used as a message queue, The producer pushes the message into the List, and the consumer obtains the message and processes it blockingly through commands such as blpop and brpop, thus realizing a simple message queue.

  • Ranking list: The push and pop operations of Redis List both have time complexity of O(1). The user's score can be stored in the List as a value and then obtained through the lrange command. Ranking list.

  • Recent Contact List: The ID of the user's recent contacts can be stored in the List, and whenever the user interacts with a contact, the ID of the contact is moved to The head of the List, so that the user's recent contact list can be obtained through the lrange command.

  • Paging query: You can store the data in List, and then use the lrange command to perform paging query.

  • Slow log: Redis can record commands whose execution time exceeds a certain threshold, store the information of these commands in List, and obtain slow log information through the lrange command.

  • Chat room: You can store the messages in the chat room in a List. Whenever there is a new message, push it to the List, and then get the latest message through the lrange command.

  • Task queue: You can store the tasks that need to be executed in a List, and then obtain the tasks through the lpop command and execute them.

  • Real-time data statistics: You can store real-time data in List, and then use the lrange command to obtain data within a certain time range and perform statistical analysis.

  • 队列延迟处理:可以将需要延迟处理的任务存储在 List 中,同时将任务的执行时间作为 score 存储在 Sorted Set 中,然后使用 Redis 的定时任务功能,每隔一段时间就将 Sorted Set 中过期的任务移动到 List 中,然后通过 lpop 命令获取任务并执行。

  • 日志收集:可以将应用程序的日志信息存储在 List 中,然后通过 lrange 命令获取日志信息进行分析和处理。

实战实例

基于 Redis List 数据结构实现消息队列的 Java 代码示例:

import redis.clients.jedis.Jedis;

public class RedisMessageQueue {
    private Jedis jedis;
    private String queueKey;

    public RedisMessageQueue(Jedis jedis, String queueKey) {
        this.jedis = jedis;
        this.queueKey = queueKey;
    }

    public void enqueue(String message) {
        jedis.rpush(queueKey, message);
    }

    public String dequeue() {
        return jedis.lpop(queueKey);
    }
}
Copy after login

示例中,定义了一个 RedisMessageQueue 类,包含一个 Jedis 对象和一个队列键名 queueKey。enqueue 方法用于将消息 push 到队列中,dequeue 方法用于从队列中获取消息并将其 pop 出来,使用该类可以方便地实现消息队列功能。

使用方法如下:

import redis.clients.jedis.Jedis;

public class TestRedisMessageQueue {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost");
        RedisMessageQueue queue = new RedisMessageQueue(jedis, "myqueue");

        // 生产者向队列中添加消息
        queue.enqueue("Hello, Redis!");
        queue.enqueue("How are you?");

        // 消费者从队列中获取消息
        String message = queue.dequeue();
        while (message != null) {
            System.out.println("Received message: " + message);
            message = queue.dequeue();
        }
    }
}
Copy after login

我已经构建了一个 RedisMessageQueue 实例,并向队列中添加了两条信息。接着,调用 dequeue 方法从队列中取出消息,并将其输出到控制台。

该示例代码仅为演示 Redis List 数据结构实现消息队列的思路,实际生产环境中需要考虑更多的细节问题,例如如何处理消息重复、如何保证消息的可靠性等等。

Redis 聊天室示例

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPubSub;

import java.util.Scanner;

public class RedisChatRoom {
    private Jedis jedis;
    private String channel;
    private String chatListKey;

    public RedisChatRoom(Jedis jedis, String channel, String chatListKey) {
        this.jedis = jedis;
        this.channel = channel;
        this.chatListKey = chatListKey;
    }

    public void start() {
        // 订阅 Redis 频道
        jedis.subscribe(new JedisPubSub() {
            @Override
            public void onMessage(String channel, String message) {
                System.out.println("Received message: " + message);
                // 将消息添加到聊天列表中
                jedis.rpush(chatListKey, message);
            }
        }, channel);

        // 发布消息到 Redis 频道
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.print("Enter message: ");
            String message = scanner.nextLine();
            jedis.publish(channel, message);
        }
    }

    public void printChatList() {
        // 获取聊天列表中的所有消息并输出到控制台
        System.out.println("Chat list:");
        for (String message : jedis.lrange(chatListKey, 0, -1)) {
            System.out.println(message);
        }
    }
}
Copy after login

示例中,RedisChatRoom 类中添加了一个聊天列表 chatListKey,用于存储聊天室中的所有消息。在订阅 Redis 频道时,通过 JedisPubSub 的 onMessage 方法将收到的消息添加到聊天列表中。在 printChatList 方法中,通过 lrange 命令获取聊天列表中的所有消息,并输出到控制台中。

使用方法如下:

import redis.clients.jedis.Jedis;

public class TestRedisChatRoom {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost");
        RedisChatRoom chatRoom = new RedisChatRoom(jedis, "mychannel", "mychatlist");
        chatRoom.start();
        chatRoom.printChatList();
    }
}
Copy after login

创建了一个 RedisChatRoom 对象,并指定了频道名为 mychannel 和聊天列表键名为 mychatlist。执行 start 方法即可开始 Redis 频道的订阅并发布消息。在最后一步中,使用 printChatList 方法从聊天列表中获取所有消息并输出到控制台上。

该示例仅仅简单演示 Redis List 数据结构实现聊天室的思路,实际项目中需要更周全的设计以及考虑。

The above is the detailed content of How to implement the bottom layer of Redis linked list. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: How To Unlock Everything In MyRise
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How is the redis cluster implemented How is the redis cluster implemented Apr 10, 2025 pm 05:27 PM

Redis cluster is a distributed deployment model that allows horizontal expansion of Redis instances, and is implemented through inter-node communication, hash slot division key space, node election, master-slave replication and command redirection: inter-node communication: virtual network communication is realized through cluster bus. Hash slot: divides the key space into hash slots to determine the node responsible for the key. Node election: At least three master nodes are required, and only one active master node is ensured through the election mechanism. Master-slave replication: The master node is responsible for writing requests, and the slave node is responsible for reading requests and data replication. Command redirection: The client connects to the node responsible for the key, and the node redirects incorrect requests. Troubleshooting: fault detection, marking off line and re-

How is the key unique for redis query How is the key unique for redis query Apr 10, 2025 pm 07:03 PM

Redis uses five strategies to ensure the uniqueness of keys: 1. Namespace separation; 2. HASH data structure; 3. SET data structure; 4. Special characters of string keys; 5. Lua script verification. The choice of specific strategies depends on data organization, performance, and scalability requirements.

How to handle redis transactions How to handle redis transactions Apr 10, 2025 pm 05:24 PM

Redis transactions ensure atomicity, consistency, isolation, and persistence (ACID) properties, and operate as follows: Start a transaction: Use the MULTI command. Record command: Execute any number of Redis commands. Commit or rollback transactions: Use the EXEC command to commit the transaction, or the DISCARD command to rollback transactions. Commit: If there is no error, the EXEC command commits the transaction and all commands are applied atomically to the database. Rollback: If there is an error, the DISCARD command rolls back the transaction, all commands are discarded, and the database status remains unchanged.

How to view all keys in redis How to view all keys in redis Apr 10, 2025 pm 07:15 PM

To view all keys in Redis, there are three ways: use the KEYS command to return all keys that match the specified pattern; use the SCAN command to iterate over the keys and return a set of keys; use the INFO command to get the total number of keys.

How to implement the underlying redis How to implement the underlying redis Apr 10, 2025 pm 07:21 PM

Redis uses hash tables to store data and supports data structures such as strings, lists, hash tables, collections and ordered collections. Redis persists data through snapshots (RDB) and append write-only (AOF) mechanisms. Redis uses master-slave replication to improve data availability. Redis uses a single-threaded event loop to handle connections and commands to ensure data atomicity and consistency. Redis sets the expiration time for the key and uses the lazy delete mechanism to delete the expiration key.

How to use redis zset How to use redis zset Apr 10, 2025 pm 07:27 PM

Redis Ordered Sets (ZSets) are used to store ordered elements and sort by associated scores. The steps to use ZSet include: 1. Create a ZSet; 2. Add a member; 3. Get a member score; 4. Get a ranking; 5. Get a member in the ranking range; 6. Delete a member; 7. Get the number of elements; 8. Get the number of members in the score range.

How to view the version number of redis How to view the version number of redis Apr 10, 2025 pm 05:57 PM

To view the Redis version number, you can use the following three methods: (1) enter the INFO command, (2) start the server with the --version option, and (3) view the configuration file.

How to optimize memory with redis How to optimize memory with redis Apr 10, 2025 pm 06:24 PM

To optimize Redis memory usage, you can take the following steps: Use appropriate data structures such as hash tables, lists, compressed lists, or hash tables. Enable compression to compress duplicate data. Use object sharing to store similar objects. Limit the number of keys and group the relative keys using hash tags. Delete expired keys and use persistence to prevent data loss. Use RDB or AOF as a persistence method to monitor memory usage and use a Redis memory server. Use space-efficient data structures, disable lazy expiration, and control the number of compressed list entries in zset.

See all articles