> 데이터 베이스 > Redis > Redis 연결 목록의 하위 계층을 구현하는 방법

Redis 연결 목록의 하위 계층을 구현하는 방법

WBOY
풀어 주다: 2023-05-28 22:46:58
앞으로
1494명이 탐색했습니다.

기본 구현

Redis 연결 목록의 하위 계층을 구현하는 방법

Redis 목록 데이터 구조의 기본 구현은 이중 연결 목록을 기반으로 합니다. 이중 연결 리스트는 일련의 노드로 구성된 공통 데이터 구조입니다. 각 노드는 이전 노드를 가리키는 포인터 prev, 다음 노드를 가리키는 다음 포인터 및 스토리지 A 포인터를 포함하는 listNode 구조로 표시됩니다. 가치를 소중히 여기다. Redis의 이중 연결 목록은 노드로 구성되며 각 노드는 요소를 나타내며 포인터를 통해 연결됩니다.

이중 연결 목록의 장점은 삽입 및 삭제 작업을 머리 부분과 꼬리 부분에서 빠르게 수행할 수 있다는 것입니다. Redis에서 새 요소가 목록의 헤드 또는 테일에 삽입되면 삽입 작업을 완료하려면 새 노드의 이전 및 다음 포인터와 원래 헤드 또는 테일 노드의 이전 또는 다음 포인터만 수정하면 됩니다. . 시간이 복잡합니다. 정도는 O(1)입니다. 마찬가지로 요소가 삭제되면 이전 노드의 다음 포인터나 다음 노드의 prev 포인터만 수정하면 삭제 작업이 완료되며 시간 복잡도도 O(1)입니다.

Redis는 이중 연결 목록을 사용하는 것 외에도 목록 데이터 구조의 성능을 향상하기 위해 다른 기술을 사용합니다. 예를 들어 목록의 요소 수가 특정 임계값을 초과하면 Redis는 목록을 압축 목록(zip 목록)으로 변환하여 메모리 사용량을 줄이고 액세스 속도를 높일 수 있습니다. 목록을 반복할 때 Redis는 반복자를 사용하여 목록의 요소를 순회하므로 순회 프로세스 중에 목록 수정으로 인해 발생하는 오류를 방지할 수 있습니다.

Redis 연결 목록의 하위 계층을 구현하는 방법

Redis의 목록형 데이터 구조는 목록의 시작이나 끝 부분에 요소를 추가하거나 제거할 수 있고, 지정된 위치에 요소를 삽입하거나 삭제할 수 있습니다. Redis의 이중 연결 목록 구현은 헤드 및 테일 노드에 대한 빠른 액세스는 물론 지정된 위치의 노드 삽입 및 삭제를 지원하므로 이러한 작업은 일정한 시간에 완료될 수 있습니다.

Redis 연결 목록의 하위 계층을 구현하는 방법

다음은 몇 가지 일반적인 Redis 목록 작업과 해당 시간 복잡도입니다.

  • LPUSH: 요소를 헤드에 삽입합니다. 시간 복잡도는 O(1)입니다.

  • RPUSH: 끝에 요소를 삽입하면 시간 복잡도는 O(1)입니다.

  • LPOP: 헤더 요소를 삭제합니다. 시간 복잡도는 O(1)입니다.

  • RPOP: 꼬리 요소를 삭제하면 시간 복잡도는 O(1)입니다.

  • LINDEX: 지정된 위치의 요소에 액세스합니다. 시간 복잡도는 O(n)입니다.

  • LINSERT: 지정된 위치에 요소를 삽입합니다. 시간 복잡도는 O(n)입니다.

  • LREM: 지정된 요소를 삭제합니다. 시간 복잡도는 O(n)입니다.

Redis 연결 목록의 하위 계층을 구현하는 방법

소스 코드 구현

Redis List 데이터 구조의 기본 코드는 C 언어를 사용하여 데모를 구현합니다.

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--;
}
로그인 후 복사

위 코드는 List 생성, 릴리스를 포함하여 List 데이터 구조의 기본 작업을 구현합니다. 헤더와 테일에 데이터를 나열하고 추가하며 요소 삽입 및 삭제를 수행합니다. 이러한 작업의 시간 복잡도는 O(1)입니다.

프로덕션에서의 실제 사용

Redis List 데이터 구조는 프로덕션 환경에서 많은 놀라운 용도를 가지고 있습니다.

  • 메시지 대기열: Redis List는 메시지 대기열로 사용될 수 있으며 생산자는 메시지를 List에 푸시하고 소비자는 blpop을 사용합니다. , brpop 등. 이 명령은 메시지를 획득하고 이를 차단 방식으로 처리하여 간단한 메시지 대기열을 구현합니다.

  • 주요 목록: Redis 목록의 푸시 및 팝 작업은 모두 O(1) 시간 복잡도를 가지며 사용자의 점수를 목록에 값으로 저장한 다음 lrange 명령을 통해 순위 목록을 얻을 수 있습니다.

  • 최근 연락처 목록: 사용자의 최근 연락처 ID가 목록에 저장될 수 있습니다. 사용자가 연락처와 상호 작용할 때마다 연락처 ID가 목록의 맨 위로 이동되어 사용자의 최근 연락처를 가져옵니다. lrange 명령을 통한 연락처 목록.

  • 페이징 쿼리: 데이터를 목록에 저장한 다음 lrange 명령을 사용하여 페이징 쿼리를 수행할 수 있습니다.

  • 느린 로그: Redis는 실행 시간이 특정 임계값을 초과하는 명령을 기록하고 이러한 명령의 정보를 List에 저장하며 lrange 명령을 통해 느린 로그 정보를 얻을 수 있습니다.

  • 채팅방: 채팅방의 메시지를 목록에 저장할 수 있습니다. 새 메시지가 있을 때마다 목록에 푸시한 후 lrange 명령을 통해 최신 메시지를 가져올 수 있습니다.

  • 작업 대기열: 실행해야 하는 작업을 목록에 저장한 다음 lpop 명령을 통해 작업을 가져와 실행할 수 있습니다.

  • 실시간 데이터 통계: 실시간 데이터를 List에 저장한 후 lrange 명령어를 사용하여 특정 시간 범위 내의 데이터를 얻어 통계 분석을 수행할 수 있습니다.

  • 队列延迟处理:可以将需要延迟处理的任务存储在 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);
    }
}
로그인 후 복사

示例中,定义了一个 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();
        }
    }
}
로그인 후 복사

我已经构建了一个 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);
        }
    }
}
로그인 후 복사

示例中,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();
    }
}
로그인 후 복사

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

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

위 내용은 Redis 연결 목록의 하위 계층을 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:yisu.com
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿