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

Redis 분산 잠금 마스터하기:입증된 패턴, 일반적인 함정 및 실제 애플리케이션

Redis 분산 잠금 마스터하기:입증된 패턴, 일반적인 함정 및 실제 애플리케이션

소개

분산 잠금은 프로덕션에서 실제로 사용하기 전까지는 간단하게 들립니다.

하나의 프로세스에는 리소스에 대한 독점 액세스가 필요합니다. 여러 서버가 실행 중입니다. Redis는 중간에 위치합니다. 아이디어는 간단해 보입니다. Redis에 잠금을 설정하고 계속 진행하세요.

한동안은 이 접근 방식이 효과가 있는 것으로 보입니다. 그런 다음 프로세스가 충돌하거나 네트워크 지연이 발생하거나 대기 시간이 급증합니다. 갑자기 두 프로세스가 동일한 잠금을 요구하거나 프로세스를 소유하지 않거나 잠금이 해제되지 않습니다.

대부분의 Redis 잠금 문제는 Redis 자체로 인해 발생하지 않습니다. 이는 분산 잠금을 종종 오해하기 때문에 발생합니다. Redis는 완벽한 독점성을 보장하는 것이 아니라 조정을 위한 도구를 제공합니다.

분산 잠금의 실제 정의

분산 잠금은 메모리 내 뮤텍스와 동일하지 않습니다. 절대적인 보증을 제공하지 않으며 실패를 제거할 수도 없습니다.

분산 잠금은 신뢰할 수 없는 환경에서 작동하는 조정 메커니즘입니다. 네트워크가 실패하고, 프로세스가 중단되고, 시계가 표류합니다. 완벽한 동작을 가정하는 잠금 전략은 결국 깨질 것입니다.

Redis 잠금은 최선의 잠금입니다. 올바르게 설계하면 매우 효과적입니다. 아무렇게나 구현하면 미묘한 경쟁 조건과 데이터 손상이 발생합니다.

Redis 잠금을 안전하게 사용하는 첫 번째 단계는 기대치를 조정하는 것입니다.

Redis 잠금이 적합한 경우

Redis 분산 잠금은 다음과 같은 경우에 적합합니다:

  • 크리티컬 섹션의 동시 실행을 방지해야 합니다

  • 작업은 여러 서버에서 조정되어야 합니다

  • 작업 시간이 짧습니다

  • 재시도 가능

일반적인 사용 사례로는 작업 중복 제거, 예약된 작업 조정, 캐시 재구축, 이중 처리 방지 등이 있습니다.

Redis 잠금은 장기 실행 비즈니스 트랜잭션, 사용자가 직면하는 중요한 워크플로 또는 안전하게 재시도할 수 없는 작업에는 적합하지 않습니다. 재시도가 허용되지 않으면 Redis 잠금은 잘못된 도구입니다.

Redis의 유일한 안전 잠금 기본 요소

가장 안전한 Redis 잠금 기본 요소는 단일 원자 명령입니다:

SET 키 값 NX EX ttl

이 명령은 잠금이 아직 없는 경우에만 잠금을 생성하고, 고유한 소유자 값을 할당하고, 잠금이 자동으로 만료되도록 TTL을 설정합니다.

대체 접근 방식에는 경쟁 조건이 발생합니다. TTL 없이 SETNX를 사용하거나 별도의 단계에서 만료를 설정하면 오류가 발생합니다. TTL은 필수이며 프로세스가 예기치 않게 충돌할 때 시스템을 보호합니다.

잠금 TTL이 필수인 이유

TTL이 없으면 Redis 잠금은 영원히 지속될 수 있습니다. 잠금을 유지하는 동안 프로세스가 충돌하면 시스템이 조용히 멈춥니다.

TTL은 잠금을 자동 복구합니다. 오류가 발생하면 결국 잠금이 만료되고 진행이 재개됩니다. 이로 인해 잠시 중복이 발생할 수 있지만 이러한 절충은 의도적인 것입니다.

만료되지 않는 잠금은 전혀 잠금이 없는 것보다 더 위험합니다.

소유권 잠금 및 안전 해제

Redis 잠금은 이를 획득한 프로세스에 의해서만 해제되어야 합니다. 이것이 바로 잠금 값이 상수 문자열이 아닌 고유 식별자여야 하는 이유입니다.

잠금을 해제하려면 소유권 확인이 필요합니다. 안전한 접근 방식은 저장된 값을 확인하고 예상 소유자와 일치하는 경우에만 잠금을 삭제하는 Lua 스크립트를 사용하는 것입니다.

이는 잠금이 만료되어 다른 프로세스에 의해 획득된 후 원래 보유자가 실수로 삭제하는 경쟁 조건을 방지합니다.

안전 잠금 기간 선택

잠금 TTL은 보호된 작업의 최대 예상 실행 시간을 초과해야 합니다. 평균 실행 시간을 사용하는 것만으로는 충분하지 않습니다.

작업이 계속 실행되는 동안 잠금이 만료되면 다른 프로세스가 이를 획득하여 동일한 작업을 동시에 수행할 수 있습니다. 이로 인해 복제나 손상이 발생할 수 있습니다.

동시에 지나치게 긴 TTL은 문제가 발생할 때 복구를 지연시킵니다. 잠금 기간은 시스템이 변경됨에 따라 진화하는 균형입니다.

잠긴 작업을 소규모로 제한적으로 유지하는 것이 가장 안전한 접근 방식입니다.

확장 프로그램 및 하트비트 잠금

일부 작업은 예상보다 오래 걸립니다. 주기적으로 TTL을 새로 고쳐 잠금을 확장하는 것이 가능하지만 복잡성과 새로운 실패 모드가 추가됩니다.

잠금 소유자만 TTL을 연장할 수 있어야 하며, 소유권이 손실되면 즉시 연장을 중지해야 합니다.

많은 경우 작업을 더 작은 덩어리로 재설계하는 것이 잠금 확장 논리를 구현하는 것보다 안전합니다.

레드락 논쟁

Redlock은 여러 Redis 인스턴스를 사용하여 잠금 안전성을 향상시키는 알고리즘입니다. 또한 논란의 여지가 있고 운영상 복잡합니다.

대부분의 시스템에서 Redlock은 이점보다 더 많은 복잡성을 가져옵니다. 실제 환경에서는 보장하기 어려운 타이밍 가정에 의존합니다.

Redlock 수준의 보장이 필요한 경우 Redis는 적절한 도구가 아닐 수 있습니다. 트랜잭션 잠금 또는 특수 조정 시스템을 갖춘 데이터베이스가 더 적합할 수 있습니다.

대부분의 Redis 사용 사례에서는 적절한 TTL 기반 잠금 기능을 갖춘 단일 Redis 인스턴스로 충분합니다.

잠금은 거래가 아닙니다

Redis 잠금은 작업을 트랜잭션으로 만들지 않습니다. 작업 도중 오류가 발생할 경우 자동 롤백을 제공하거나 일관성을 보장하지 않습니다.

잠금은 동시성을 감소시킵니다. 그들은 실패를 제거하지 않습니다. 중요한 섹션은 반복 실행으로 인해 피해가 발생하지 않도록 멱등성을 갖도록 설계되어야 합니다.

이 설계 원칙은 잠금 관련 버그의 위험을 크게 줄여줍니다.

Redis가 다운되면 어떻게 되나요?

Redis가 다운되거나 다시 시작되면 모든 잠금이 사라집니다. 이는 예상된 동작입니다.

Redis가 다시 온라인 상태가 되면 여러 프로세스가 동시에 잠금을 획득하고 작업을 시작할 수 있습니다. 시스템은 이러한 가능성을 허용해야 합니다.

Redis를 다시 시작하는 동안 잠금이 손실되어 손상될 경우 잠금 설계는 안전하지 않으므로 재고해야 합니다.

프로덕션 잠금 모니터링

Redis 잠금은 절대로 보이지 않아야 합니다. 팀은 존재하는 잠금 수, 수명, 잠금 획득 실패 빈도를 모니터링해야 합니다.

비정상적으로 오래 지속되는 잠금은 프로세스가 중단되었음을 나타냅니다. 빈번한 획득 실패는 경합 또는 잘못된 잠금 설계를 나타냅니다.

안전한 작업을 위해서는 가시성이 필수적입니다.

일반적인 Redis 잠금 방지 패턴

일반적인 실수로는 TTL 없이 SETNX를 사용하는 것, 잠금 소유권에 상수 값을 사용하는 것, 맹목적으로 잠금을 삭제하는 것, 장기 실행 작업을 위해 잠금을 유지하는 것, 잠금이 정확성을 보장한다고 가정하는 것 등이 있습니다.

이러한 안티패턴은 실제 생산 중단 시 자주 나타납니다.

실용적인 잠금 체크리스트

안전한 Redis 잠금 구현에는 다음이 포함됩니다:

  • TTL로 키 잠금

  • 고유한 잠금 소유권 값

  • 출시 시 소유권 확인

  • 단기 중요 섹션

  • 멱등성 연산

  • 테스트된 실패 경로

이들 중 하나라도 누락된 경우 잠금 설계를 재고해야 합니다.

Redis 잠금을 위한 건강한 정신 모델

Redis 잠금 장치는 에어백이 아닌 안전벨트입니다. 피해를 줄여주지만 사고를 완전히 방지할 수는 없습니다.

신중하게 사용하면 분산 시스템의 조정이 단순화됩니다. 아무렇지도 않게 사용하면 미묘하고 지속적인 버그가 발생합니다.

요약

분산 잠금은 실패가 불가피하기 때문에 어렵습니다. Redis는 완벽하지는 않지만 빠르고 간단하며 실용적인 잠금 메커니즘을 제공합니다.

실패에 대비하여 설계하고, 잠금을 짧게 유지하고, TTL을 일관되게 사용하고, 작업을 다시 시도해도 안전한지 확인하세요. 올바르게 사용하면 Redis 분산 잠금은 프로덕션 시스템에서 안정적이고 효과적인 도구입니다.