Database/Redis

[실전 레디스] 3-2. 고급 기능: 주요 기능

noahkim_ 2025. 3. 21. 21:39

하야시 쇼고 님의 "실전 레디스" 책을 정리한 포스팅 입니다.

 

1. 트랜잭션

명령어

MULTI/EXEC
MULTI
  SET foo 10
  INCR foo
  INCR foo
  GET foo
EXEC
  • 트랜잭션을 감싸는 명령어
  • 선언된 명령어를 큐에 집어넣음

 

DISCARD
MULTI
SET key1 "value1"
SET key2 "value2"
DISCARD  # 트랜잭션을 취소하고 변경 사항 반영 안 됨

 

WATCH
WATCH balance  # balance 키 감시
MULTI
INCR balance  # balance 증가
EXEC  # balance 값이 변경되지 않았다면 실행, 변경되었으면 실패
  • CAS (Compare and Sweep)
  • 트랜잭션 종료 전에 대상이 된 키가 변경되면 트랜잭션의 전체 실행을 중지
  • 다시 수행해야 함

 

특징

  • 롤백 지원 X
  • 실패한 명령어 건너뛰고 남은 작업을 계속 처리함

 

낙관적 락

require 'redis'
redis = Redis.new

def transfer(redis, amount)
  retry_count = 3

  retry_count.times do
    redis.watch("balance")  # 감시 시작
    balance = redis.get("balance").to_i

    if balance < amount
      redis.unwatch  # 감시 해제
      puts "잔액 부족"
      return false
    end

    redis.multi do |multi|
      multi.decrby("balance", amount)  # balance 감소
    end

    return true if redis.get("balance").to_i == balance - amount
  end

  puts "트랜잭션 실패: 충돌 발생"
  false
end

# 초기 잔액 설정
redis.set("balance", 100)

# 30만큼 출금 시도
transfer(redis, 30)
  • 트랜잭션 충돌이 일어나지 않을 것이라 기대하고 처리하는 방식

 

2. 모듈

  • 버전 호환성 레디스 버전에 의존하지 않음
  • 높은 성능 

 

기능

  • 자동 메모리 관리기능 제공
  • 저수준 API / 고수준 API 제공

 

등록

#include "redismodule.h"

// hello 명령어를 실행할 함수
int HelloCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
    if (argc != 1) {
        return RedisModule_WrongArity(ctx);
    }
    return RedisModule_ReplyWithSimpleString(ctx, "Hello, Redis!");
}

// 모듈 로드 시 실행되는 함수
int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
    if (RedisModule_Init(ctx, "hellomodule", 1, REDISMODULE_APIVER_1) == REDISMODULE_ERR) {
        return REDISMODULE_ERR;
    }

    // hello 명령어 등록
    if (RedisModule_CreateCommand(ctx, "hello", HelloCommand, "readonly", 0, 0, 0) == REDISMODULE_ERR) {
        return REDISMODULE_ERR;
    }

    return REDISMODULE_OK;
}
  • 모듈 파일 생성 (c)
    • RedisModule_Init: 함수로 모듈 등록 및 초기화
    • RedisModule_CreateCommand: 명령어 등록

 

gcc -shard -o hellomodule.so -fPIC hellomodule.c
MODULE LOAD /path/to/hellomodule.so
  • 컴파일 및 등록

 

명령어

MODULE UNLOAD hellomodule
MODULE LIST

 

활용

  • 자료형 정의

 

2. 키 공간 알림

  • 데이터 변경이나 서버에 이벤트가 발생할 경우 알림을 제공하는 시스템
  • Pub/Sub 기능을 사용하여 클라이언트에게 알람을 보냄

 

특징

클라이언트 설정 필요
  • 클라이언트 측에서 알람을 받기 위해 notify-keyspace-events 지시자 설정을 활성화해야 함

 

감지할 이벤트의 종류를 지정할 수 있음
  • notify-keyspace-events 설정 값으로 셋팅함

 

두 가지 유형의 알림 지원
  • Keyspace Notifications (__keyspace@0__:mykey)
  • Keyevent Notifications (__keyevent@0__:set)

 

notify-keyspace-events 지시자

지시자 설명 예시 이벤트
K Keyspace 알림 활성화 (키 단위 알림)
__keyspace@0__:mykey
E Keyevent 알림 활성화 (이벤트 단위 알림)
__keyevent@0__:set
A 모든 이벤트 활성화 (AKE)
set, del, expire 등 모든 이벤트
g 일반적인 GET, DEL, EXISTS 관련 이벤트 get, del, exists
s SET, SETEX, PSETEX 관련 이벤트 set, setex
x EXPIRE, PERSIST, TTL 관련 이벤트
expire, persist, ttl
e EVICT (LRU 정책에 따른 삭제) 관련 이벤트 evict
m RENAME, RENAME NX 관련 이벤트
rename, renamenx
d DEL, UNLINK 관련 이벤트 del, unlink
l LIST 관련 이벤트 (LPUSH, RPUSH, LPOP, RPOP) lpush, rpop
h HASH 관련 이벤트 (HSET, HDEL, HMSET) hset, hdel
z ZSET (Sorted Set) 관련 이벤트 zadd, zrem
t SET (String Type) 관련 이벤트 set
f Lua 스크립트 실행 관련 이벤트 eval, evalsha

 

설정

1. 알림 기능 활성화

config set notify-keyspace-events KEA
  • K: Keyspace 이벤트 활성화
  • E: Keyevent 이벤트 활성화
  • A: 모든 이벤트 감지

 

2. Pub/Sub 구독

SUBSCRIBE __keyspace@0__:mykey
  • keyspace 알림 구독 (키가 변경될 때 알림)

 

SUBSCRIBE __keyevent@0__:set
  • keyevent 알림 구독 (특정 이벤트 발생 시 알림)

 

6. 클라이언트 측 캐싱

  • RTT 오버헤드를 줄이기 위한 기능
  • 클라이언트에서 자주 사용하는 키를 캐싱하여 Redis 요청을 줄임

 

무효화 매커니즘

  • 데이터 정합성을 보장하기 위한 기능

 

작동 방식
  1. 클라이언트가 키를 캐싱
  2. 서버는 전역 테이블(무효화 테이블) 에 캐싱된 키를 갖는 클라이언트의 목록을 기록해 둠
  3. 키가 업데이트될 경우, 서버는 해당 키를 가진 클라이언트들에게 무효화 메시지 전송
  4. 클라이언트는 무효화 메시지를 받고 해당 키를 무효화함

 

설정
CLIENT TRACKING ON

 

모드

브로드캐스트 
  • 여러 클라이언트가 동일한 키를 구독할 때 사용하는 방식
  • 서버가 키 변경을 감지하면 모든 관련 클라이언트에 무효화 메시지를 전송함

 

설정

CLIENT TRACKING ON BCAST

 

 

RESP3
  • Redis의 새로운 응답 프로토콜
  • 데이터 유형을 명확하게 표현
  • 클라이언트 캐싱을 위한 무효화 메시지 포함 가능

 

설정

HELLO 3

CLIENT TRACKING ON RESP3