[Redis] 클러스터 적용 이후 Lua Script 실행 오류 문제

Nicky·2024년 11월 23일
0

Trouble Shooting 

목록 보기
4/4
post-thumbnail

문제 상황

Redis Cluster 모드 적용 이후에 대기열 진입 API 실행 시에 다음과 같이 500 에러가 발생하는 것을 확인하였다.

검색을 통해 Redis Cluster 환경에서 발생하는 CROSSSLOT 에러라는 것을 확인 할 수 있었다.

문제 원인

Redis Cluster는 설정된 마스터 노드의 개수에 따라 Slot을 균등하게 배분받는다. 이 때 저장되는 키들은 해당하는 Slot을 관리하는 노드에 저장되게 된다.

현재 대기열 진입 API는 작업열 인원 수에 따라 분기가 발생하므로 Lua Script를 통해 실행되고 있는데, 스크립트에서 실행되는 연산들은 원자성을 보장받기 위해 하나의 노드에서 실행되어야 한다고 한다.

하지만 현재 사용 중인 키들이 서로 다른 해시 슬롯에 매핑되어 있어 스크립트 실행이 불가능한 것이었다.

RedisKeyPrefix

@Getter
@RequiredArgsConstructor
public enum RedisKeyPrefix {

    // 대기열
    WAITING_QUEUE("WaitingQueue:"),
    WORKING_QUEUE("WorkingQueue:"),
    TOKEN_VALUE("UserToken:");
    
    private final String value;

}

해결 과정

결국 이를 해결하려면 스크립트에서 사용하는 키들이 같은 Slot으로 계산되어 저장되게 수정하면 된다.

먼자 Redis 키의 해시 슬롯 계산 방식에 대해 살펴보면 다음과 같다.

  1. 키 이름의 해시값을 계산 (CRC16)
  2. 해시값을 16384(총 슬롯 수)로 나눈 나머지를 구함
  3. 해당 나머지 값에 해당하는 슬롯을 관리하는 노드에 키가 저장된다

이때 예외적으로, 키 이름에 중괄호 형태(ex: {...})의 해시 태그가 포함되어 있을 경우 해시 태그 내부의 문자열만을 사용하여 해시값을 계산한다고 한다.

따라서 이전의 키 prefix를 다음과 같이 수정해주었다.

@Getter
@RequiredArgsConstructor
public enum RedisKeyPrefix {

    // 대기열
    WAITING_QUEUE("{Queue}:WaitingQueue:"),
    WORKING_QUEUE("{Queue}:WorkingQueue:"),
    TOKEN_VALUE("{Queue}:UserToken:");
    
    private final String value;

}

이제 API 요청을 성공적으로 수행하는 것을 확인할 수 있다.

profile
배우고 기록하는 공간

0개의 댓글