속도가 중요한 경우: Hazelcast 및 Redpanda를 사용한 라이브 스트림 처리

        이 튜토리얼에서는 실시간 데이터의 잠재력을 최대한 활용하는 안전하고 확장 가능한 고성능 애플리케이션을 구축하는 방법을 알아봅니다.

        이 튜토리얼에서는 실시간 데이터에 반응하는 고성능, 확장 가능, 내결함성 애플리케이션을 구축하기 위해 Hazelcast와 Redpanda의 강력한 조합을 살펴보겠습니다.

        Redpanda는 높은 처리량의 실시간 데이터 스트림을 처리하도록 설계된 스트리밍 데이터 플랫폼입니다. Redpanda는 Kafka와 API 호환되며 Apache Kafka에 대한 고성능 및 확장 가능한 대안을 제공합니다. Redpanda의 고유한 아키텍처를 통해 초당 수백만 개의 메시지를 처리하는 동시에 낮은 대기 시간, 내결함성 및 원활한 확장성을 보장합니다.

        Hazelcast는 스트림 처리와 빠른 데이터 저장의 고유한 조합을 통해 동적 데이터에 대한 즉각적인 작업을 지원하고 이벤트 스트림과 기존 데이터 소스에 대한 대기 시간이 짧은 쿼리, 집계 및 상태 계산을 가능하게 하는 통합 실시간 스트리밍 데이터 플랫폼입니다. 이를 통해 리소스 효율적인 실시간 애플리케이션을 신속하게 구축할 수 있습니다. 소규모 엣지 디바이스부터 대규모 클라우드 인스턴스 클러스터까지 모든 규모로 배포할 수 있습니다.

이 게시물에서는 강력한 스트리밍 분석을 위한 실시간 데이터 수집, 처리 및 분석을 위해 이 두 가지 기술을 설정하고 통합하는 과정을 안내합니다. 마지막으로, Hazelcast와 Redpanda의 결합된 기능을 활용하여 애플리케이션의 스트리밍 분석 및 임시 운영 잠재력을 활용하는 방법에 대한 통찰력을 얻게 됩니다.

자, 시작해 봅시다!

Pizza in Motion: 피자 배달 서비스를 위한 솔루션 아키텍처

        먼저, 우리가 무엇을 만들 것인지 이해해 봅시다. 우리 대부분은 피자를 좋아합니다. 피자 배달 서비스를 예로 들어보겠습니다. 우리의 피자 배달 서비스는 실시간으로 여러 사용자의 주문을 받습니다. 이러한 주문에는 타임스탬프, user_id, pizza_type 및 수량이 포함됩니다. Python을 사용하여 주문을 생성하고 이를 Redpanda로 가져온 다음 Hazelcast를 사용하여 처리합니다.

        하지만 상황별 데이터로 피자 주문을 강화하고 싶다면 어떻게 해야 할까요? 예를 들어, 특정 유형의 피자에 대한 특정 애피타이저를 ​​추천합니다. 실시간으로 이를 수행하는 방법은 무엇입니까?

        실제로는 몇 가지 옵션이 있지만 이 블로그 게시물에서는 Hazelcast를 사용하여 Hazelcast의 iMap에 저장된 애피타이저로 Redpanda에서 피자 주문을 풍성하게 만드는 방법을 보여 드리겠습니다.

다음은 솔루션의 간략한 개략도입니다.

튜토리얼: Redpanda 및 Hazelcast를 사용한 실시간 스트림 처리

Redpanda 설정

이 튜토리얼의 범위 내에서 Docker Compose를 사용하여 Redpanda 클러스터를 설정합니다. 따라서 Docker Compose가 로컬에 설치되어 있는지 확인하세요.
원하는 위치에 docker-compose.yml 파일을 만들고 다음 콘텐츠를 추가합니다.

version: "3.7"
name: redpanda-quickstart
networks:
redpanda_network:
driver: bridge
volumes:
redpanda-0: null
services:
redpanda-0:
command:
- redpanda
- start
- --kafka-addr internal://0.0.0.0:9092,external://0.0.0.0:19092
# Address the broker advertises to clients that connect to the Kafka API.
# Use the internal addresses to connect to the Redpanda brokers'
# from inside the same Docker network.
# Use the external addresses to connect to the Redpanda brokers'
# from outside the Docker network.
- --advertise-kafka-addr internal://redpanda-0:9092,external://localhost:19092
- --pandaproxy-addr internal://0.0.0.0:8082,external://0.0.0.0:18082
# Address the broker advertises to clients that connect to the HTTP Proxy.
- --advertise-pandaproxy-addr internal://redpanda-0:8082,external://localhost:18082
- --schema-registry-addr internal://0.0.0.0:8081,external://0.0.0.0:18081
# Redpanda brokers use the RPC API to communicate with eachother internally.
- --rpc-addr redpanda-0:33145
- --advertise-rpc-addr redpanda-0:33145
# Tells Seastar (the framework Redpanda uses under the hood) to use 1 core on the system.
- --smp 1
# The amount of memory to make available to Redpanda.
- --memory 1G
# Mode dev-container uses well-known configuration properties for development in containers.
- --mode dev-container
# enable logs for debugging.
- --default-log-level=debug
image: docker.redpanda.com/redpandadata/redpanda:v23.1.11
container_name: redpanda-0
volumes:
- redpanda-0:/var/lib/redpanda/data
networks:
- redpanda_network
ports:
- 18081:18081
- 18082:18082
- 19092:19092
- 19644:9644
console:
container_name: redpanda-console
image: docker.redpanda.com/redpandadata/console:v2.2.4
networks:
- redpanda_network
entrypoint: /bin/sh
command: -c 'echo "$$CONSOLE_CONFIG_FILE" > /tmp/config.yml; /app/console'
environment:
CONFIG_FILEPATH: /tmp/config.yml
CONSOLE_CONFIG_FILE: |
kafka:
brokers: ["redpanda-0:9092"]
schemaRegistry:
enabled: true
urls: ["http://redpanda-0:8081"]
redpanda:
adminApi:
enabled: true
urls: ["http://redpanda-0:9644"]
ports:
- 8080:8080
depends_on:
      - redpanda-0

위 파일에는 단일 에이전트로 Redpanda 클러스터를 시작하는 데 필요한 구성이 포함되어 있습니다. 원하는 경우 3개 브로커 클러스터를 사용할 수 있습니다. 그러나 우리의 사용 사례에서는 단일 브로커로 충분합니다.

Docker에서 Redpanda를 사용하는 것은 개발 및 테스트에만 권장됩니다. 다른 배포 옵션의 경우 Linux 또는 Kubernetes를 고려하세요 .

데이터를 생성하기 위해 Python 스크립트를 사용합니다.

import asyncio
import json
import os
import random
from datetime import datetime

from kafka import KafkaProducer
from kafka.admin import KafkaAdminClient, NewTopic

BOOTSTRAP_SERVERS = (
    "localhost:19092"
    if os.getenv("RUNTIME_ENVIRONMENT") == "DOCKER"
    else "localhost:19092"
)

PIZZASTREAM_TOPIC = "pizzastream"
PIZZASTREAM_TYPES = [
    "Margherita",
    "Hawaiian",
    "Veggie",
    "Meat",
    "Pepperoni", 
    "Buffalo",
    "Supreme",
    "Chicken",
]

async def generate_pizza(user_id):

    producer = KafkaProducer(bootstrap_servers=BOOTSTRAP_SERVERS)
    while True:
        data = {
            "timestamp_": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            "pizza": random.choice(PIZZASTREAM_TYPES),
            "user_id": user_id,
            "quantity": random.randint(1, 10),
        }
        producer.send(
            PIZZASTREAM_TOPIC,
            key=user_id.encode("utf-8"),
            value=json.dumps(data).encode("utf-8"),
        )
        print(
            f"Sent a pizza stream event data to Redpanda: {data}"
        )
        await asyncio.sleep(random.randint(1, 5))

async def main():
    tasks = [
        generate_pizza(user_id)
        for user_id in [f"user_{i}" for i in range(10)]
    ]
    await asyncio.gather(*tasks)

if __name__ == "__main__":
    # Create kafka topics if running in Docker.
    if os.getenv("RUNTIME_ENVIRONMENT") == "DOCKER":
        admin_client = KafkaAdminClient(
            bootstrap_servers=BOOTSTRAP_SERVERS, client_id="pizzastream-producer"
        )
        # Check if topics already exist first
        existing_topics = admin_client.list_topics()
        for topic in [PIZZASTREAM_TOPIC]:
            if topic not in existing_topics:
                admin_client.create_topics(
                    [NewTopic(topic, num_partitions=1, replication_factor=1)]
                )
    asyncio.run(main())

헤이즐캐스트 설정

Hazelcast 로컬 클러스터를 시작합니다. 그러면 로컬 네트워크에서 실행되는 Manager 인스턴스와 함께 클라이언트/서버 모드에서 Hazelcast 클러스터가 실행됩니다.

brew tap hazelcast/hz
brew install [email protected]
hz -V

이제 무엇을 구축해야 하는지 알고 전제 조건이 설정되었으므로 바로 솔루션을 살펴보겠습니다.

1단계: Redpanda 클러스터 시작

터미널에서 다음 명령을 실행하여 Redpanda 클러스터를 시작하겠습니다 . 파일을 저장한 위치와 동일한 위치에 있는지 확인하십시오 docker-compose.yml.

docker compose up -d

다음과 유사한 출력은 Redpanda 클러스터가 실행 중임을 확인합니다.

[+] Running 4/4
⠿ Network redpanda_network                 Created  0.0s
⠿ Volume "redpanda-quickstart_redpanda-0"  Created  0.0s
⠿ Container redpanda-0                     Started  0.3s
⠿ Container redpanda-console               Started  0.6s

2단계: 헤이즐캐스트 실행

다음 명령을 실행하여 하나의 노드로 Hazelcast 클러스터를 시작할 수 있습니다.

hz start

클러스터에 더 많은 구성원을 추가하려면 다른 터미널 창을 열고 시작 명령을 다시 실행하십시오.

3단계: Hazelcast에서 SQL 실행

클러스터에서 SQL 쿼리를 실행하는 가장 쉬운 방법인 SQL 셸을 사용하겠습니다. SQL을 사용하여 맵 및 Kafka 주제의 데이터를 쿼리할 수 있습니다. 결과는 클라이언트에 직접 전송되거나 맵 또는 Kafka 주제에 삽입될 수 있습니다. Hazelcast 클러스터와 Kafka 간의 이벤트를 스트리밍, 필터링 및 변환할 수 있는 Kafka 커넥터를 사용할 수도 있습니다  . 다음을 실행하여 이 작업을 수행할 수 있습니다.

bin/hz-cli sql

4단계: Hazelcast iMap(pizzastream) 수집

pizzastreamSQL 명령을 사용하여 맵을 생성합니다 .

CREATE OR REPLACE MAPPING pizzastream(
timestamp_ TIMESTAMP,
pizza VARCHAR,
user_id VARCHAR,
quantity DOUBLE
)
TYPE Kafka
OPTIONS (
'keyFormat' = 'varchar',
'valueFormat' = 'json-flat',
'auto.offset.reset' = 'earliest',
'bootstrap.servers' = 'localhost:19092');

5단계: 추천 데이터로 스트림 강화(추천자)

이 단계에서는 또 다른 맵을 만듭니다.

CREATE or REPLACE MAPPING recommender (
__key BIGINT,
user_id VARCHAR,
extra1 VARCHAR,
extra2 VARCHAR,
extra3 VARCHAR )
TYPE IMap
OPTIONS (
'keyFormat'='bigint',
'valueFormat'='json-flat');

지도에 몇 가지 값을 추가합니다.

INSERT INTO recommender VALUES
(1, 'user_1', 'Soup','Onion_rings','Coleslaw'),
(2, 'user_2', 'Salad', 'Coleslaw', 'Soup'),
(3, 'user_3', 'Zucchini_fries','Salad', 'Coleslaw'),
(4, 'user_4', 'Onion_rings','Soup', 'Jalapeno_poppers'),
(5, 'user_5', 'Zucchini_fries', 'Salad', 'Coleslaw'),
(6, 'user_6', 'Soup', 'Zucchini_fries', 'Coleslaw'),
(7, 'user_7', 'Onion_rings', 'Soup', 'Jalapeno_poppers'),
(8, 'user_8', 'Jalapeno_poppers', 'Coleslaw', 'Zucchini_fries'),
(9, 'user_9', 'Onion_rings','Jalapeno_poppers','Soup');

6단계: SQL을 사용하여 두 지도 병합

위의 두 맵을 기반으로 다음 SQL 쿼리를 보냅니다.

SELECT
    pizzastream.user_id AS user_id,
    recommender.extra1 as extra1,
    recommender.extra2 as extra2,
    recommender.extra3 as extra3,
     pizzastream.pizza AS pizza
FROM pizzastream
JOIN recommender
ON recommender.user_id = recommender.user_id 
AND recommender.extra2 = 'Soup';

7단계: 결합된 데이터 스트림을 Redpanda에 보내기

결과를 Redpanda로 다시 보내기 위해 우리는 SQL 쿼리 결과를 새 맵에 저장하는 Jet 작업을 Hazelcast에서 생성한 다음 Redpanda에 저장합니다.

CREATE OR REPLACE MAPPING recommender_pizzastream(
timestamp_ TIMESTAMP,
user_id VARCHAR,
extra1 VARCHAR,
extra2 VARCHAR,
extra3 VARCHAR,
pizza VARCHAR
)
TYPE Kafka
OPTIONS (
'keyFormat' = 'int',
'valueFormat' = 'json-flat',
'auto.offset.rest' = 'earliest',
'bootstrap.servers' = 'localhost:19092'
);

CREATE JOB recommender_job AS SINK INTO recommender_pizzastream SELECT
    pizzastream.timestamp_ as timestamp_,
    pizzastream.user_id AS user_id,
    recommender.extra1 as extra1,
    recommender.extra2 as extra2,
    recommender.extra3 as extra3,
    pizzastream.pizza AS pizza
FROM pizzastream
JOIN recommender
ON recommender.user_id = recommender.user_id 
AND recommender.extra2 = 'Soup';

결론적으로

이 글에서는 Redpanda와 Hazelcast를 사용하여 피자 배달 서비스를 구축하는 방법을 설명했습니다.

Redpanda는 피자 주문을 높은 처리량 스트림으로 수집하고 안정적으로 저장하며 Hazelcast가 확장 가능한 방식으로 이를 소비할 수 있도록 하여 가치를 더합니다. 일단 먹게 되면 Hazelcast는 상황에 맞는 데이터로 피자 주문을 강화하고(즉시 사용자에게 애피타이저를 ​​추천함) 강화된 데이터를 Redpanda로 다시 보냅니다.

Hazelcast를 사용하면 리소스 효율적인 실시간 애플리케이션을 빠르게 구축할 수 있습니다. 소규모 엣지 디바이스부터 대규모 클라우드 인스턴스 클러스터까지 모든 규모로 배포할 수 있습니다. Hazelcast 노드 클러스터는 데이터 저장 및 컴퓨팅 부하를 공유하며 동적으로 확장 및 축소될 수 있습니다.

추천

출처blog.csdn.net/qq_28245905/article/details/132290735