Home .NET Core에서 Redis Job Queue 사용하기
Post
Cancel

.NET Core에서 Redis Job Queue 사용하기

소개

Redis는 Key, Value 구조의 비정형 데이터를 저장하고 관리하기 위한 오픈 소스 기반의 비관계형 데이터베이스 관리 시스템(DBMS)입니다.

데이터베이스, 캐시, 메시지 브로커로 사용되며 인메모리 데이터 구조를 가진 저장소입니다.

많이들 Redis의 자료구조 중 List를 가지고 Queue나 Stack을 만들어 사용합니다.

속도는 O(n)의 속도를 가지며 이 포스트에서는 Job Queue를 만들어 Message Queue 처럼 사용하는 방법에 대해 소개하도록 하겠습니다.

flowchart LR
    Client -- 3, 2, 1 --> Queue
    Queue -- 1 --> Worker1
    Queue -- 2 --> Worker2
    Queue -- 3--> Worker3

Redis Nuget Package

.NET에서 Redis를 지원하는 패키지는 많이 있으나 가장 많이 사용하는 StackExchange.Redis를 사용하여 구연하도록 하겠습니다.

Redis 연결

StackExchange.Redis로 Redis에 연결하기 위해서는 아래와 같은 방법으로 Connection을 생성하면 됩니다.

1
ConnectionMultiplexer.Connect("localhost:6379");

Connection이 생성 되었다면 아래와 같이 메서드를 정의 할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
public void Enqueue(string value)
{
    _connection.GetDatabase().ListLeftPush(_queueName, value.ToString());
}

public string Dequeue()
{
    var result = _connection.GetDatabase().ListRightPop(_queueName);
    return result.ToString();
}

Enqueue의 경우 List의 왼쪽에 Push를 하고 Dequeue의 경우 오른쪽에서 Pop을 하면 됩니다.

Stack 구현 시 Push의 경우 ListLeftPush Pop의 경우 ListLeftPop을 하면 되겠죠?

메시지 삭제

Redis의 경우 Message Queue 처럼 사용하지만 중간의 데이터를 삭제 할 수 있습니다.

예를 들어 RabbitMQ의 경우는 메시지를 Publish하면 메시지를 Queue에서 강제로 삭제가 불가능합니다.

하지만 Redis는 List이기 때문에 O(n)의 속도로 삭제가 가능합니다.

1
2
3
4
5
public int Remove(string value, long count = 1)
{
    var removeItems = _connection.GetDatabase().ListRemove(_queueName, value.ToString(), count);
    return Convert.ToInt32(removeItems);
}

ListRemove를 사용하면 삭제가 가능하며 count는 삭제하려는 value를 몇개까지 지우는지 설정합니다.

예제 소스

https://github.com/Jandari91/Redis-.NET

예제 소스 설명

Client-WPF의 경우 WPF로 만들었고 textbox에 글자를 넣고 Input 버튼을 누르면 Redis로 Message가 Enqueue 됩니다.

그리고 WorkerService는 위 그림과 같이 메시지를 하나하나씩 가져와 처리됩니다.

docker-compose.yml은 아래와 같이 정의하여 Worker를 3개 띄우도록 하였습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
version: '3.4'

services:
  workerservice:
    image: ${DOCKER_REGISTRY-}workerservice
    build:
      context: .
      dockerfile: WorkerService/Dockerfile

  workerservice2:
    image: ${DOCKER_REGISTRY-}workerservice
    build:
      context: .
      dockerfile: WorkerService/Dockerfile
  workerservice3:
    image: ${DOCKER_REGISTRY-}workerservice
    build:
      context: .
      dockerfile: WorkerService/Dockerfile

  redis:
    image : redis:latest
    ports:
    - 6379:6379
This post is licensed under CC BY 4.0 by the author.