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

Redis에서 대용량 정렬 집합(Sorted Set) 안전하게 삭제하는 방법

Redis에서 대용량 객체 삭제가 느린 이유가 궁금하다면, 먼저 관련 개요 문서를 참고해 보세요.

Redis는 단일 스레드로 동작하기 때문에 수백만 개의 멤버를 가진 큰 정렬 집합(Sorted Set)을 DEL 명령으로 한 번에 삭제하면 서버 전체가 블로킹되어 다른 모든 클라이언트의 요청 처리가 멈출 수 있습니다. 이를 방지하려면 아래와 같은 점진적 삭제 전략을 사용해야 합니다.

삭제 절차

  1. 키 이름 변경(Rename): 먼저 해당 키를 고유한 네임스페이스를 가진 새 키로 변경합니다. 이렇게 하면 다른 Redis 클라이언트 입장에서는 원래 키가 즉시 "삭제된" 것처럼 보입니다.

  2. 점진적 배치 삭제: 정렬 집합의 멤버를 작은 단위(예: 100개씩)로 나누어 반복적으로 삭제하고, 집합이 완전히 비워질 때까지 진행합니다. 삭제 명령의 크기를 제한함으로써 서버가 오랫동안 블로킹되지 않도록 보장할 수 있습니다.

주의: 아래 코드는 Redis 연결 실패 상황을 우아하게 처리하지 않습니다. Redis 명령 실행 중 예외가 발생하면 남은 잔여 데이터를 직접 수동으로 정리해야 합니다.

의사 코드(Pseudo-code)

# 키 이름 변경
newkey = "gc:hashes:" + redis.INCR("gc:index")
redis.RENAME("my.zset.key", newkey)

# 100개씩 배치로 멤버 삭제
while redis.ZCARD(newkey) > 0
  redis.ZREMRANGEBYRANK(newkey, 0, 99)
end

Ruby 구현 예제

$redis = Redis.new

def delete_sorted_set(key)
  # 키 이름 변경
  newkey = "gc:zsets:#{$redis.incr("gc:index")}"
  $redis.rename(key, newkey)

  # 100개씩 배치로 멤버 삭제
  while $redis.zcard(newkey) > 0
    $redis.zremrangebyrank(newkey, 0, 99)
  end
end

# 사용 예:
#
#   delete_sorted_set("my.large.set")

백그라운드 잡 활용

대용량 삭제 작업은 시간이 걸릴 수 있으므로, 애플리케이션의 응답성을 유지하려면 백그라운드 잡으로 실행하는 것이 좋습니다. Ruby 진영에서 널리 쓰이는 다음 잡 큐 라이브러리들을 활용한 구현 예제를 참고할 수 있습니다.

  • Resque — Redis 기반 백그라운드 잡 큐
  • Sidekiq — 고성능 스레드 기반 잡 프로세서

이 방식의 핵심은 ZREMRANGEBYRANK를 이용해 한 번에 소량의 멤버만 삭제하므로, 각 명령이 마이크로초~밀리초 수준으로 빠르게 완료된다는 점입니다. 그 결과 서버 지연 없이 수백만 개의 멤버도 안전하게 제거할 수 있습니다.

← "Redis에서 대용량 객체 삭제하기"로 돌아가기