Computer >> 컴퓨터 >  >> 프로그래밍 >> Redis

Redis 복제본의 키 개수가 원본보다 적게 보이는 이유

Redis에서 만료되는 키(이른바 "volatile" 키)를 사용한다면, 새로운 레플리카(replica)를 데이터베이스에 연결할 때 의외의 상황을 마주할 수 있습니다. 레플리카의 키 개수가 기본(primary) 데이터베이스보다 현저히 적게 나타나는 경우가 있기 때문입니다. 특히 만료 키가 많은 환경에서는 이런 현상이 더욱 흔하게 발생합니다.

과연 레플리카에서 키가 누락된 걸까요? 데이터를 잃어버린 걸까요? 짧게 답하자면 "아니요"입니다. 하지만 데이터 손실 없이도 왜 레플리카의 키 개수가 더 적게 보고되는지 그 이유를 이해해 두면 큰 도움이 됩니다. 여기에는 두 가지 구현 세부 사항이 관련되어 있습니다. 바로 Redis가 키를 만료시키는 방식과, 새 레플리카에 데이터셋을 전송하는 방식입니다.

Redis는 만료 키를 어떻게 처리할까?

Redis에서 volatile 키는 설정된 만료 시점에 정확히 메모리에서 제거되지 않습니다. 대신 다음 두 가지 방법 중 하나로 삭제됩니다.

  1. 클라이언트가 어떤 키에 대해 읽기 또는 쓰기 작업을 수행하면, Redis 서버는 먼저 해당 키가 존재하는지, 만료 시간이 설정되어 있는지 확인합니다. 키가 존재하고 만료 시간이 이미 지났다면, Redis는 해당 명령을 처리하기 전에 즉시 키를 메모리에서 제거합니다.

  2. 접근되지 않는 만료 키가 메모리에 영원히 남아있지 않도록, Redis는 간단한 수동(passive) 알고리즘으로 키를 만료 처리합니다. 10밀리초마다 무작위로 volatile 키 100개를 샘플링하고, 그중 만료 시간이 지난 키를 즉시 제거합니다. 제거된 키가 25개 이상이라면, 즉시 다시 100개를 샘플링해 같은 과정을 반복합니다.

두 번째 방식이 중요한 이유는, 상당수의 키가 이미 "만료"된 상태임에도 불구하고 아직 메모리에서 제거되지 않고 남아 있을 수 있기 때문입니다.1 Redis는 이러한 키들이 실제로 제거될 때까지 INFO 명령 출력의 "keys" 및 "expires" 카운트에 계속 포함시킵니다.

Redis는 새 레플리카에 데이터셋을 어떻게 전송할까?

Redis 레플리카가 Redis 서버에 연결되면, 기본 서버는 자신의 데이터셋에 대한 RDB 스냅샷을 생성해 레플리카에 전송합니다. 그리고 Redis가 RDB 스냅샷을 생성할 때는 만료 시간이 지난 키는 절대 포함하지 않습니다. 설령 그 키가 아직 메모리에서 제거되지 않은 상태라 해도 마찬가지입니다.

그래서 왜 레플리카의 키 개수가 기본 서버보다 적을까?

레플리카를 Redis 인스턴스에 연결하면, 해당 레플리카는 기본 데이터베이스에 남아 있는 "만료되었지만 아직 제거되지 않은" volatile 키가 빠진 데이터셋을 전달받게 됩니다. RDB 백업으로 Redis 서버를 복원할 때 키 개수가 줄어드는 것도 정확히 같은 이유 때문입니다.

RDB 동작 추적에 도움을 주신 @mattsta님께 특별히 감사드립니다.


  1. 실제 운영 환경에서는 Redis가 끊임없이 삭제 대상 키를 탐색하기 때문에, 이 숫자는 대체로 훨씬 낮습니다. ↩