콘텐츠로 이동

2025 01 03

2025-01-03

Redis

참고: https://devocean.sk.com/search/techBoardDetail.do?ID=165057

  • 개요
    • 오픈소스, 인메모리 데이터 저장소
    • 용도 : DB, 캐시, 스트리밍엔진, 메세지 브로커
  • 구성에 따른 구분
    • 단일 모드(standalone)
      • 간단한 설치 및 개발
      • 어플리케이션이 하나의 Redis에 데이터 읽고 씀
    • Master-Slave 복제모드
      • 읽기 성능 확장 필요 시
      • 데이터 쓸 때엔 Master, 읽을 땐 Slave
        • 읽기 성능 늘리기 위해서 Slave 노드 추가하기도 함
    • Cluster 모드
      • 대규모 데이터 운용하기 위함
      • 기본 6개의 노드 (클러스터 구성 위한 최소 단위는 6개)
      • 3개의 Master, 3개의 Slave로 구성
  • Multi Key Operation

    • 한번의 명령에 여러 키 동시 전달 처리
      MGET key1 key2 key3
      MSET key1 val1 key2 val2
      SINTER setKey1 setKey2
      SUNION setKey1 setKey2
      
    • 단일 노드 문제 없음
    • 클러스터에서는 키들이 서로 다른 노드에 있으면 한번에 처리 어려움
    • Redis Cluster는 키들을 슬롯 단위로 나눠 각 노드에 분산 저장
  • 명령어
    • pexpire : 키 만료시간을 밀리초 단위로 설정. (Expire는 초 기준)
    • lpush : 리스트의 왼쪽에 값 추가
    • lrange : 리스트의 지정된 범위의 요소 반환
    • lpop : 리스트의 왼쪽 요소 제거하고 반환
    • blpop : lpop의 블로킹 버전. 리스트가 비어있다면 지정된 시간동안 대기하다가 요소 추가시 그 요소 제거하고 반환
    • sadd : Set에 하나 이상 멤버 추가, 없다면 새로운 Set 생성
    • srem : Set에 지정된 멤버 제거
    • zadd : Sorted Set에 하나 이상의 멤버와 그에 해당하는 점수 추가

Redis Cluster

참고: https://co-de.tistory.com/24
참고: https://jaehoney.tistory.com/328

  • 샤딩의 문제점
    • key % 3 이런식으로 연산 때려버리면... 샤드 늘어날 때 마다 데이터 전혀 다른곳으로 이동해야 함
    • Redis는 16384개의 해시 슬롯으로 키 공간 나눠서 관리
      • CRC16 해싱 % 16384 -> 해시 슬롯 매핑
  • 개요
    • Redis Cluster 특징 : master 여러개 두어 분산 저장 가능하며, Sharding/Scale out 가능
    • Master 하나 이상의 Slave 둘 수 있음
    • Slave가 죽어서 복제 노드가 없는 마스터가 생긴다면, 다른 마스터 노드에 여유분이 있다면 해당 노드로 빈자리 채울 수 있음
      • Master가 죽으면 Slave가 Master로 자동 failover
    • 여러 노드에 자동적인 데이터 분산
    • 일부 노드의 실패나 통신 단절에도 계속 작동하는 가용성
    • 고성능 보장, 선형 확장성 제공
  • 특징
    • full-mesh 구조 통신
    • cluster bus 추가 채널 사용
    • gossip protocol : 근처 노드 통신
    • Multi key 명령어가 제한됨
    • 클라이언트는 모든 노드에 접속?
  • 데이터 분산
    • hash slot (각 키 해싱 후 모듈러 연산해 매핑)
      • CRC16 해싱 후 모듈러 연산으로 16384개의 해시 슬롯 중 하나로 매핑
    • 클라이언트 데이터 접근
  • 클러스터 제약 사항
    • 클러스터는 DB 0 만 사용 가능
      • Redis는 한 인스턴스에 여러 데이터베이스를 가질 수 있으며 디폴트는 16
      • 이는 용도별로 분리하여 관리를 용이하게 하기 위한 목적
      • 하지만, 클러스터에서는 해당 기능 사용 못하고 DB 0으로 고정
    • Multi key operation 사용 제약
      • key들이 각각 다른 노드에 저장 -> MSET 등 multi-key operation 사용 X

redisclient.debasishg.net > RedisClient

참고: https://github.com/debasishg/scala-redis

  • 레디스 클러스터 환경에 연결/명령 실행하자
    class RedisCluster(protected val hosts: List[ClusterNode],
                       override protected val keyTag: Option[KeyTag]) extends RedisClusterOps
    
  • 특징
    1. 클러스터 노드 정보 관리 : Redis 클러스터에 여러 노드(호스트/포트)를 등록
    2. 키 태그 설정 : 키-슬롯 매핑 효율적으로 제어하기 위함
    3. 클러스터 명령 라우팅

Redis Pub/Sub

참고: https://lucas-owner.tistory.com/60
참고: https://oliveyoung.tech/2023-08-07/async-process-of-coupon-issuance-using-redis/
참고: https://medium.com/frientrip/pub-sub-%EC%9E%98-%EC%95%8C%EA%B3%A0-%EC%93%B0%EC%9E%90-de9dc1b9f739

  • 개요
    • Message Queue 패턴 중에 하나
    • 채팅/푸시/구독 시스템에 사용
    • 수신 확인, 메시지 저장이 필요하지 않다면, 사용하기 좋다. (In-memory라 속도 빠름)
  • vs Kafka
    • Kafka는 Topic에 publish 되는 메시지를 저장하지만, Redis는 publish 메시지 저장하지 않음
    • Redis에 subscriber 존재하지 않으면 메시지 사라짐
  • pub/sub
    • 특정 주제를 구독한 구독자에게 메시지를 발행하는 방식
    • 레디스는 인메모리라서 웹 소켓을 사용하는 네트워크 방식보다 매우 빠름
  • Redis Pub/Sub 순서
    • Redis는 Topic 따로 생성하지 않고, Subscribe가 Topic을 구독하면 Topic이 생성
    • Pub/Sub 순서
      1. Subscriber가 특정 Topic 구독
      2. 클라이언트가 특정 Topic에 pub
      3. Topic을 구독하는 Subscriber 들이 메시지 수신
    • 명령어
      subscribe chnannel        // 특정 채널 구독, 메시지 수신 받음
      publish channel message   // 메시지를 특정 채널에 발송
      pubsub subcommand         // Redis에 등록된 채널, 패턴 조회
      psubscribe pattern        // 채널 이름을 패턴으로 등록
      unsubscribe [channel]     // 특정 채널 구독 해제
      punsubscribe [pattern]    // psubscribe로 구독한 패턴 채널 구독 해제
      
  • Subscriber는 계속 커넥션을 잡고 있어야 하나?
    • Redis Pub/Sub에서도 Redis 클라/서버 간 사용되는 RESP(Redis Serialization Protocol) 사용
    • Subscriber 입장에서 지속적으로 Redis 서버와 TCP 연결을 유지해야 실시간 수신 가능
      • 이는 Pub/Sub에서 자연스러운 동작
    • 프로토콜
      • RESP(버전에 따라 RESP2/RESP3) 텍스트 기반의 경량 프로토콜
      • 별도 MQTT, AMQP와 같은 복잡한 메시징 프로토콜이 아니라, Redis 고유 프로토콜
      • Redis 서버나 클라이언트 사용에 특별한 설정 X
    • 성능/부하
      1. 지속 연결로 인한 과부하 X
        • 매우 가벼운 오버헤드를 가지고 수많은 구독자 연결
      2. 메시지 처리량 이슈
        • Redis Pub/Sub은 브로커 역할이라, Redis에서 메시지 받아서 바로 모든 Subscriber에게 전송
        • 매우 빈번하거나 대량이라면, Redis 서버의 네트워크 대역폭, CPU 부하가 문제될 수 있음
        • 일반적인 규모로는 Redis 단일로도 충분
      3. Scale Out
        • 트래픽 기하급수적으로 늘어나면 Redis 클러스터 구성을 통해 분산 처리 가능
        • Pub/Sub보다 고급 기능 (메시지, ack, reprocessing)에서는 Redis Stream, Kafka 등의 메시징 시스템 고려도 함

Scala 2.11 라이브러리를 Scala 2.13에서 쓰면 안 되는 이유

  • 개요
    • 스칼라는 마이너 버전(2.11, 2.12, 2.13)간의 바이너리 호환성을 보장하지 않음
    • 스칼라 2.11로 컴파일된 라이브러리는 내부적으로 스칼라 2.11 표준 라이브러리와 컴파일러 구현 디테일에 의존
      • 스칼라 2.13에서 이거 그대로 쓰면 런타임 시점에 충돌
  • 구체적인 이유
    1. 표준 라이브러리 변경됨
      • 스칼라 2.11에서 사용되던 컬렉션/메서드/API가 스칼라 2.13에서 삭제/시그니처 변경되었을 수 있음
      • NoSuchMethodError, ClassNotFoundError 등장하기 좋음
    2. 매크로/컴파일러 내부 구현 차이
      • 컴파일러 내부 구조, 트리 구조가 바뀌어 호환되지 않는 경우가 많음
    3. 바이너리 호환성 미보장
      • 자바는 메이저 버전간 바이너리 호환성이 깨져?
    4. SBT나 Maven, Gradle 등에서 충돌