무엇을 하고 싶은가?
버그 수정 및 적용을 위해 실서버 환경에서 Redis 캐시(데이터) 갱신이 필요했다. 캐시 전략은 Cache-aside Pattern을 사용하고 있기 때문에 삭제를 통해 필요한 유저만 갱신하기로 했다. 패턴 조회를 통해 필요한 버그에 관련된 key값만 골라 삭제해 주기로 했다.
어떻게 할 수 있는가?
패턴을 통한 삭제는 Redis 명령어 keys, scan을 통해서 처리를 할 수 있다. keys를 사용하면 전체 키를 조회해서 삭제를 할 수 있지만, Redis는 기본적으로 싱글 스레드로 동작을 하기 때문에 key가 많을 경우 다른 요청을 받아서 처리할 수 없는 특징이 있다. 실제 운영이 되고 있는 Redis에 keys를 날릴 경우 서비스에 장애를 가져다줄 수 있다. 운영 서비스에 영향을 덜 주기 위해 일정 크기만큼 key값을 조회할 수 있는 scan을 통해서 삭제를 하기로 했다.
Scan 구성
Scan 명령어는 2.8.0v부터 도입되었으며 SCAN cursor [MATCH pattern] [COUNT count] [TYPE type] 형식으로 구성이 되어있다. cursor는 조회하고자 하는 bucket를 가리킨다. pattern, count, type은 옵셔널한 값으로 각각 찾고자 하는 key의 패턴, 조회 개수, redis type을 나타낸다. count는 설정하지 않으면 기본 값은 10이며 설정한 값은 Scan을 동작할 때 참고 크기이며 꼭 지켜지는 크기는 아니다. type은 내부적으로 구현된 타입을 기준으로 찾아주며, 조회 데이터가 감소를 하는 것이 아닌 전체 데이터를 대상으로 하기에 성능적인 이점은 없다.
Scan의 특징
Scan의 경우 중복된 key를 반환할 수 있다. 특정 크기만큼 순회하면서 key 값을 가져오는 구조이기 때문에, 운영이 되고 있는 서비스에 key가 생성이 되고 삭제가 되면서 rehashing이 일어나게 된다. 이 때 기존 데이터 구조와 새로운 데이터 구조를 모두 참조해서 key를 반환하기 때문이다.
Scan의 count 값은 참고 사항이며 항상 설정한 개수만큼 key값을 반환하지 않습니다. 그리고 count 크기를 적절하게 선정하지 않으면, 너무 많은 반복을 돌며 요청을 하게 되거나 keys와 같이 동작하게 되어 명령 수행 시간이 길어질 수 있습니다. 적절한 설정이 필요합니다.
실제 서버에서 Scan 동작시켜서 처리하기
운영 서버에서 Scan cursor pattern 100 으로 설정을 하고 반복하면서 키 삭제를 했습니다. 이때 어떤 이유에서인지 10분 넘게 끝나지 않고 동작이 계속 되엇다. 서비스가 운영되면서 키가 실시간으로 추가되고 삭제되는 과정에서 무한 반복에 빠질 수 있는 것인가 싶어 찾아보았지만, 그런 사례를 찾아볼 수 없었다. count 값이 작고 rehashing이 자주 일어난다면 무한 반복처럼 보일 수는 있다고 한다. 서비스 운영을 위해 빠르게 처리를 해줘야 했기 때문에 count를 1000까지 했을 때도 단일 요청 시간이 1ms 내외로 처리가 되었다. 1000으로 주고 처리를 했고 10초 안에 필요한 키들을 모두 삭제할 수 있었다.
Scan Count 값이 100일 때 발생했던 이슈?
10분이 넘어도 끝나지 않던 Count 100과 10초 안에 모두 처리를 한 Count 1000을 기준으로 두었고, 실제 운영 서비스에서 사용자가 실시간으로 데이터를 삭제 및 쓰기가 이루어지고 있어 Rehashing이 일어나고 있다는 가정을 해보았다. 이런 가정 속에서 여러 참고 문서들을 찾아보았지만 원인을 파악하지 못했다. 다음 주를 사용해서 시간을 더 내서 원인을 파악해 봐야겠다. 같은 상황을 로컬에서 먼저 구성을 해보고 원인을 찾아볼 수 있으면 좋겠다.
참고 사이트
Redis의 SCAN은 어떻게 동작하는가? - tech.kakao.com
Redis의 기능 중에 쓰면 안되지만, 그 단맛에 끌려 어쩔 수 없이 치게 되는 ...
tech.kakao.com
SCAN
Iterates over the key names in the database.
redis.io
'프로젝트' 카테고리의 다른 글
코틀린 Data Class와 Mybatis 같이 사용할 때 주의점 (1) | 2025.03.04 |
---|---|
시간 유효성 검사에서 시간 값 생성 시점 (0) | 2024.11.03 |
불변 객체와 깊은 복사를 사용 해야 하는 이유 (0) | 2024.10.28 |
Github PR을 했을 때 Slack 알림 보내기 (0) | 2024.10.21 |
재화(크레딧, 투표권 등) 로그 데이터 정리 작업 (0) | 2024.09.02 |