Redis 트랜잭션: 안전한 데이터 변경 처리하기

2024. 9. 11. 10:53·DB/Redis

1. HTTP 트랜잭션

HTTP 트랜잭션은 클라이언트와 웹 서버 간의 통신을 나타내며, 다음과 같은 흐름으로 이루어집니다:

  • 클라이언트가 HTTP 요청을 전송: 클라이언트는 서버에 요청을 보냅니다. 이 요청에는 URL, 메소드(GET, POST 등), 그리고 추가적인 데이터(예: 헤더, 본문)가 포함됩니다.
  • 서버가 응답: 서버는 요청을 처리한 후, 해당하는 응답(HTTP 응답 코드, 데이터)을 클라이언트로 전송합니다.

HTTP 트랜잭션은 주로 요청-응답 기반으로 이루어지며, 요청의 성공 또는 실패에 대한 즉각적인 응답이 제공됩니다. 그러나 트랜잭션의 일관성이나 원자성에 대한 보장은 없습니다.

2. 데이터베이스 트랜잭션 (DB 트랜잭션)

데이터베이스 트랜잭션은 주로 ACID 속성에 기반하여 정의됩니다:

  • 원자성(Atomicity): 트랜잭션 내의 모든 작업이 성공하거나, 하나라도 실패하면 전체 트랜잭션이 취소됩니다.
  • 일관성(Consistency): 트랜잭션이 성공적으로 완료되면, 데이터베이스는 일관된 상태를 유지해야 합니다.
  • 격리성(Isolation): 동시에 수행되는 여러 트랜잭션이 서로에게 영향을 미치지 않아야 합니다.
  • 지속성(Durability): 트랜잭션이 완료되면 그 결과가 영구적으로 기록되어야 합니다.

데이터베이스 트랜잭션은 주로 SQL 쿼리의 형태로 진행되며, 클라이언트가 데이터베이스에 쿼리를 전송하면 데이터베이스는 이를 처리하고 결과를 반환합니다. DB 트랜잭션은 복잡한 데이터 일관성을 유지해야 할 때 유용합니다.

3. Redis 트랜잭션

Redis 트랜잭션은 특정 명령들을 묶어서 실행할 수 있는 기능을 제공합니다. Redis의 트랜잭션은 몇 가지 중요한 특징이 있습니다:

  • MULTI: 트랜잭션을 시작할 때 사용하며, 이후 실행할 명령들을 큐에 저장합니다.
  • EXEC: 큐에 저장된 명령들을 실행합니다.
  • DISCARD: 트랜잭션 내의 명령들을 모두 취소합니다.
  • WATCH: 특정 키를 감시하여, 해당 키의 값이 다른 클라이언트에 의해 수정되었을 경우 트랜잭션이 자동으로 실패하게 만듭니다.

Redis의 트랜잭션은 다음과 같은 특징을 가집니다:

  • 원자성 보장: 트랜잭션 내의 명령들은 모두 하나의 블록으로 실행되며, 중간에 실패가 발생하지 않으면 한꺼번에 적용됩니다.
  • 단일 스레드 처리: Redis는 단일 스레드 기반으로 동작하므로, 각 클라이언트가 명령을 보내면 순차적으로 처리됩니다. 이는 격리성을 자동으로 제공하는 장점이 있습니다.
  • 에러 처리: 트랜잭션 내에서 하나의 명령이 오류를 발생시키면, 전체 트랜잭션이 실패하고 이전 명령들도 적용되지 않습니다. 이를 통해 데이터의 일관성을 유지합니다.

Redis 트랜잭션은 SQL 데이터베이스의 트랜잭션처럼 복잡한 ACID 속성을 모두 보장하지는 않지만, 빠른 응답과 기본적인 트랜잭션 처리를 제공합니다. 특히 WATCH를 사용하여 낙관적 잠금을 구현할 수 있어 특정 상황에서는 충돌 제어에 유리한 장점이 있습니다.

트랜잭션 비교 : HTTP, RDBMS , Redis

특징 HTTP 트랜잭션 RDBMS 트랜잭션 Redis 트랜잭션
트랜잭션 정의 클라이언트와 서버 간의 요청-응답 한 쌍 여러 SQL 명령을 하나의 작업 단위로 묶음 여러 Redis 명령어를 하나의 작업으로 묶음
원자성 (Atomicity) 없음 지원 (ACID 원칙 중 하나) 명령어 단위로 원자성 보장
일관성 (Consistency) 서버 상태와 요청 간 일치성을 보장하지 않음 지원 (데이터 일관성 보장) 명령어 실행 순서를 통해 일관성 보장
격리성 (Isolation) 없음 지원 (ACID 원칙 중 하나) 단일 스레드 처리로 자연스러운 격리성 제공
지속성 (Durability) 요청이 끝나면 연결이 종료됨 지원 (완료된 트랜잭션은 영구적으로 저장) 명령어 실행 후 변경사항은 영구 저장 가능
에러 처리 클라이언트에 에러 반환 오류 발생 시 트랜잭션 전체를 롤백 개별 명령어 에러 발생 시 트랜잭션 전체 취소
처리 방식 비동기적으로 처리 가능 동기/비동기 모두 가능 단일 스레드로 처리
주요 사용 사례 웹 브라우저와 서버 간의 데이터 전송 복잡한 데이터 처리, 높은 데이터 무결성 요구 빠른 캐싱 및 단순한 데이터 트랜잭션 처리
속도 빠름 (단일 요청에 대한 처리) 상대적으로 느림 (트랜잭션 복잡도에 따라 다름) 매우 빠름 (단일 스레드, 메모리 기반)
트랜잭션의 복잡도 낮음 복잡 (여러 명령과 데이터 관계 관리) 중간 (기본적인 트랜잭션 처리 가능)
트랜잭션 관리 없음 ACID 원칙에 따른 엄격한 관리 MULTI/EXEC/DISCARD를 통한 기본 관리
주요 기능 요청-응답 기반 데이터 전송 복잡한 쿼리와 트랜잭션 처리 명령어 그룹을 원자성 있게 실행

요약:

  • HTTP 트랜잭션은 요청-응답 간의 단순 통신 방식이며, 트랜잭션 일관성이나 원자성에 대한 요구가 없습니다.
  • RDBMS 트랜잭션은 ACID 원칙을 기반으로 하며, 데이터의 무결성과 일관성을 보장하기 위한 복잡한 트랜잭션 처리가 가능합니다.
  • Redis 트랜잭션은 단순하고 빠르게 트랜잭션을 처리할 수 있으며, 주로 캐싱이나 상태 관리와 같은 간단한 트랜잭션에 적합합니다.

이 표를 통해 각 트랜잭션 방식의 특성과 차이점을 명확히 비교할 수 있습니다.


REDIS 트랜잭션의 원자성

다음은 Redis 트랜잭션에서의 오류 처리 방식을 Mermaid 다이어그램을 사용하여 표현한 코드입니다. 이를 통해 트랜잭션의 전체 롤백과 부분 실행 상황을 시각적으로 나타낼 수 있습니다.

1. 전체 롤백 - 존재하지 않는 명령어로 인한 오류

2. 부분 실행 - 인자 값 오류로 인한 부분 실패

설명:

  • 첫 번째 시나리오: 트랜잭션 중 SET123 key2 2000 명령에서 존재하지 않는 명령어로 인해 오류가 발생하고, 전체 트랜잭션이 EXECABORT로 롤백됩니다.
  • 두 번째 시나리오: SET key2 2000 5000에서 인자 값 오류가 발생했지만, 나머지 명령어는 정상적으로 처리됩니다. 첫 번째 명령(GET key1)은 성공하고, 두 번째 명령에서 오류가 발생한 후, 마지막 명령(SET key3 3000)은 정상적으로 처리됩니다.

Redis 명령어 실습

아래는 Redis의 트랜잭션을 실습하는 예시로, MULTI, EXEC, DISCARD, WATCH를 이용한 트랜잭션을 설명하는 코드 및 명령어 예시입니다. 각 기능을 Redis CLI를 사용해 시뮬레이션할 수 있습니다.

1. MULTI - EXEC/DISCARD 트랜잭션 예시

  • MULTI를 사용하여 트랜잭션을 시작하고, 명령어를 큐에 저장한 후 EXEC를 통해 실행합니다.
  • DISCARD를 사용하여 트랜잭션을 취소할 수도 있습니다.
127.0.0.1:6379> MULTI  # 트랜잭션 시작
OK

127.0.0.1:6379> SET key1 "value1"  # 첫 번째 명령어 큐에 저장
QUEUED

127.0.0.1:6379> SET key2 "value2"  # 두 번째 명령어 큐에 저장
QUEUED

127.0.0.1:6379> GET key1  # 세 번째 명령어 큐에 저장
QUEUED

# EXEC를 사용하여 트랜잭션 실행
127.0.0.1:6379> EXEC
1) OK  # 첫 번째 SET 명령어 실행 결과
2) OK  # 두 번째 SET 명령어 실행 결과
3) "value1"  # GET 명령어 실행 결과

# 트랜잭션을 실행하지 않고 취소할 경우 (DISCARD 사용)
127.0.0.1:6379> MULTI  # 트랜잭션 시작
OK

127.0.0.1:6379> SET key3 "value3"  # 명령어 큐에 저장
QUEUED

127.0.0.1:6379> DISCARD  # 트랜잭션 취소
OK

127.0.0.1:6379> GET key3  # 확인: 트랜잭션이 취소되었으므로 key3는 존재하지 않음
(nil)

2. 트랜잭션 격리성 (Isolation)

Redis 트랜잭션은 기본적으로 격리성을 제공합니다. 한 클라이언트가 트랜잭션을 실행 중일 때, 다른 클라이언트의 작업이 트랜잭션에 영향을 미치지 않습니다. 즉, 모든 명령어는 트랜잭션이 끝날 때 실행되므로, 그 전까지는 다른 명령어가 해당 키에 접근할 수 없습니다.

예시:

# 클라이언트 1
127.0.0.1:6379> MULTI  # 트랜잭션 시작
OK

127.0.0.1:6379> SET key1 "value1"
QUEUED

127.0.0.1:6379> GET key1
QUEUED

# 클라이언트 2에서 GET key1 시도
127.0.0.1:6379> GET key1  # 아직 트랜잭션이 완료되지 않았으므로 값이 없음
(nil)

# 클라이언트 1에서 트랜잭션 완료
127.0.0.1:6379> EXEC
1) OK
2) "value1"

# 클라이언트 2에서 다시 GET 시도
127.0.0.1:6379> GET key1
"value1"  # 트랜잭션이 완료된 후 값을 읽을 수 있음

3. WATCH with MULTI (낙관적 잠금 예시)

  • WATCH 명령어는 특정 키를 모니터링하여, 다른 클라이언트가 그 키를 수정하면 트랜잭션을 중단하게 만듭니다. 이 방식은 낙관적 잠금(Optimistic Locking)이라고 합니다.

예시:

# 클라이언트 1에서 WATCH 명령 실행
127.0.0.1:6379> WATCH key1
OK

127.0.0.1:6379> GET key1
"value1"  # 현재 key1의 값은 "value1"

127.0.0.1:6379> MULTI  # 트랜잭션 시작
OK

127.0.0.1:6379> SET key1 "new_value1"
QUEUED

# 클라이언트 2에서 key1을 수정
127.0.0.1:6379> SET key1 "other_value"
OK

# 클라이언트 1에서 트랜잭션 실행
127.0.0.1:6379> EXEC  # WATCH로 인해 중단됨
(nil)  # 트랜잭션 실패

127.0.0.1:6379> GET key1  # 클라이언트 2의 변경이 적용된 상태
"other_value"

설명:

  • WATCH는 key1을 모니터링하고 있습니다. 클라이언트 1이 트랜잭션을 실행하려고 하지만, 클라이언트 2가 중간에 key1 값을 수정했기 때문에 트랜잭션이 중단됩니다.
  • 트랜잭션이 실패할 경우, EXEC는 (nil)을 반환하고, 트랜잭션 내의 명령어는 실행되지 않습니다.

Redis 트랜잭션 실습 요약:

1. MULTI - EXEC/DISCARD:

  • MULTI로 트랜잭션 시작 후, 명령을 큐에 적재하고 EXEC로 실행하거나 DISCARD로 취소할 수 있습니다.

2. 격리성:

  • Redis는 트랜잭션 내에서 명령어가 실행되기 전까지 명령어의 영향을 받지 않으며, 트랜잭션이 끝나야 키의 값이 다른 클라이언트에게 노출됩니다.

3. WATCH with MULTI:

  • WATCH는 낙관적 잠금을 구현하여, 다른 클라이언트가 키를 변경할 경우 트랜잭션이 중단되도록 할 수 있습니다. EXEC 실행 전 감시 중인 키가 변경되면 트랜잭션이 실패합니다.

이 예시를 통해 Redis의 트랜잭션과 관련된 기능들을 연습할 수 있습니다.

저작자표시 (새창열림)

'DB > Redis' 카테고리의 다른 글

Redis Cache 활용법: 성능 최적화를 위한 캐시 전략  (0) 2024.09.12
Redis Key와 Scan 명령어: 대규모 데이터 검색  (0) 2024.09.11
Redis Bitmap 실습: 비트 단위 데이터 처리  (0) 2024.09.11
Redis Geospatial 실습: 좌표 기반 데이터 처리  (0) 2024.09.11
Redis Sorted Set 실습: 정렬된 데이터를 효율적으로 처리하기  (0) 2024.09.11
'DB/Redis' 카테고리의 다른 글
  • Redis Cache 활용법: 성능 최적화를 위한 캐시 전략
  • Redis Key와 Scan 명령어: 대규모 데이터 검색
  • Redis Bitmap 실습: 비트 단위 데이터 처리
  • Redis Geospatial 실습: 좌표 기반 데이터 처리
hyeseong-dev
hyeseong-dev
안녕하세요. 백엔드 개발자 이혜성입니다.
  • hyeseong-dev
    어제 오늘 그리고 내일
    hyeseong-dev
  • 전체
    오늘
    어제
    • 분류 전체보기 (286) N
      • 여러가지 (107)
        • 알고리즘 & 자료구조 (72)
        • 오류 (4)
        • 이것저것 (29)
        • 일기 (1)
      • 프레임워크 (39)
        • 자바 스프링 (39)
        • React Native (0)
      • 프로그래밍 언어 (38)
        • 파이썬 (30)
        • 자바 (3)
        • 스프링부트 (5)
      • 컴퓨터 구조와 운영체제 (3) N
      • DB (17)
        • SQL (0)
        • Redis (17)
      • 클라우드 컴퓨팅 (2)
        • 도커 (2)
        • AWS (0)
      • 스케쥴 (65)
        • 세미나 (0)
        • 수료 (0)
        • 스터디 (24)
        • 시험 (41)
      • 트러블슈팅 (1)
      • 자격증 (0)
        • 정보처리기사 (0)
      • 재태크 (5)
        • 암호화폐 (5)
        • 기타 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    spring
    RDS
    프로그래머스
    Python
    백준
    ecs
    Spring WebFlux
    시험
    #개발자포트폴리오 #개발자이력서 #개발자취업 #개발자취준 #코딩테스트 #항해99 #취리코 #취업리부트코스
    취업리부트
    항해99
    AWS
    WebFlux
    완전탐색
    자바
    java
    mybatis
    Redis
    파이썬
    그리디
    FastAPI
    SAA
    Docker-compose
    reactor
    celery
    DP
    EC2
    OOP
    Spring Boot
    docker
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
hyeseong-dev
Redis 트랜잭션: 안전한 데이터 변경 처리하기
상단으로

티스토리툴바