>백엔드 개발 >PHP 튜토리얼 >Redis의 분산 잠금 구현에 대한 자세한 설명

Redis의 분산 잠금 구현에 대한 자세한 설명

小云云
小云云원래의
2017-12-14 14:42:412485검색

이전에 사용했던 예약된 작업은 단일 시스템에만 배포되었으며 단일 지점 문제를 해결하고 작업이 하나의 시스템에서만 실행되도록 하려면 잠금 문제를 고려해야 하므로 연구하는 데 시간을 투자했습니다. . 이 질문. 분산 잠금을 구현하는 방법은 무엇입니까? 이 글은 주로 Redis에서 분산 잠금을 구현하는 방법의 예를 소개합니다. 편집자는 이것이 꽤 좋다고 생각합니다. 이제 여러분에게 공유하고 참고할 수 있기를 바랍니다.

잠금의 본질은 상호 배제로, 클라이언트가 언제든지 동일한 잠금을 보유할 수 있도록 보장합니다. Redis를 사용하여 분산 잠금을 구현하는 것을 고려하는 경우 가장 간단한 해결책은 인스턴스에 키 값을 생성하고 해제하는 것입니다. 잠금 시간이면 키 값을 삭제하세요. 그러나 안정적이고 완전한 분산 잠금을 위해서는 고려해야 할 많은 세부 사항이 필요합니다. 올바른 분산 잠금을 작성하는 방법을 살펴보겠습니다.

분산 잠금의 단일 머신 버전 SETNX

그래서 우리는 redis의 setNX(SET if Not eXists) 명령을 기반으로 직접 간단한 잠금을 구현합니다. 의사 코드로 직접

잠금 획득:

SET resource_name my_random_value NX PX 30000

잠금 해제:

 if redis.call("get",KEYS[1]) == ARGV[1] then
  return redis.call("del",KEYS[1])
 else
  return 0
 end

주의해야 할 몇 가지 세부 사항:

먼저 잠금을 획득할 때 시간 제한을 설정해야 합니다. 네트워크 문제가 발생한 후 클라이언트가 충돌하거나 잠금이 유지되는 것을 방지하기 위해 시간 초과가 설정됩니다. 전체 시스템이 교착 상태에 빠졌습니다.

setNX 명령을 사용하여 쿼리 및 쓰기 단계가 원자성인지 확인하세요

잠금이 해제되면 KEYS[1]) == ARGV[1]라고 판단합니다. 여기서 KEYS[1]은 redis에서 가져옵니다. 값 ARGV[1]은 위에서 생성된 my_random_value입니다. 위 판단의 이유는 잠긴 홀더에 의해 잠금이 해제되었는지 확인하기 위한 것입니다. 이 확인 단계는 수행되지 않는다고 가정합니다.

  1. 클라이언트 A가 잠금을 획득하고 후속 스레드가 중단됩니다. 시간이 잠금 만료 시간보다 깁니다.

  2. 잠금이 만료된 후 클라이언트 B가 잠금을 획득합니다.

  3. 클라이언트 A가 복구된 후 관련 이벤트를 처리한 후 redis에 del 명령을 실행합니다. 잠금이 해제되었습니다

  4. 클라이언트 C가 잠금을 획득했습니다. 이때 시스템의 두 클라이언트는 동시에 잠금을 유지합니다.

이 문제의 핵심은 클라이언트 B가 보유한 잠금을 클라이언트 A가 해제한다는 것입니다.

작업의 원자성을 보장하려면 Lua 스크립트를 사용하여 잠금을 해제해야 합니다. 잠금 해제에는 get, 판단, del의 세 단계가 포함됩니다. 세 단계의 원자성을 보장할 수 없으면 분산 잠금에 동시성 문제가 발생합니다.

위의 세부 사항에 주의하면 단일 Redis 노드의 분산 잠금이 달성됩니다.

이 분산 잠금에는 여전히 Redis의 단일 지점이 있습니다. 아마도 Redis에는 마스터-슬레이브 아키텍처가 있다고 말할 것입니다. 장애가 발생하면 슬레이브로 전환하면 되지만 Redis 복제는 비동기식입니다.

  1. 클라이언트 A가 마스터에 대한 잠금을 얻는 경우.

  2. 마스터가 슬레이브에 데이터를 동기화하기 전에 마스터가 다운됩니다.

  3. 클라이언트 B가 슬레이브로부터 다시 잠금을 받았습니다.

이렇게 하면 마스터의 다운타임으로 인해 여러 사람이 동시에 자물쇠를 잡고 있게 됩니다. 시스템이 짧은 시간 동안 여러 사람이 잠금 장치를 보유할 수 있는 경우. 이 간단한 해결책으로 문제가 해결될 것입니다.

하지만 이 문제가 해결된다면. Redis는 공식적으로 Redlock 솔루션을 제공합니다.

RedLock 구현

Redis 단일 지점 문제를 해결하기 위해. Redis의 저자는 RedLock의 솔루션을 제안했습니다. 계획은 매우 영리하고 간결합니다.
RedLock의 핵심 아이디어는 중복성을 위해 여러 Redis 마스터를 동시에 사용하는 것이며 이러한 노드는 완전히 독립적이며 이러한 노드 간에 데이터를 동기화할 필요가 없습니다.

N개의 Redis 노드가 있다고 가정하면 N은 2보다 큰 홀수여야 합니다. RedLock 구현 단계:

  1. 현재 시간 가져오기

  2. 위에서 언급한 방법을 사용하여 N 노드의 Redis 잠금을 순차적으로 가져옵니다.

  3. 획득한 잠금 개수가 (N/2+1)보다 크고 획득 시간이 잠금 유효 시간(잠금 유효 시간)보다 작으면 유효한 잠금을 획득한 것으로 간주됩니다. 잠금 자동 해제 시간은 초기 잠금 해제 시간에서 이전에 잠금을 획득하는 데 소요된 시간을 뺀 값입니다.

  4. 잠금 획득 개수가 (N/2+1)개 미만이거나 잠금 유효 시간(잠금 유효 시간) 내에 획득한 잠금 수가 충분하지 않은 경우 잠금 획득에 실패한 것으로 간주됩니다. 이때 모든 노드에 잠금 해제 메시지를 보내야 합니다.

잠금 해제 구현은 매우 간단합니다. 이전에 잠금이 성공적으로 획득되었는지 여부에 관계없이 모든 Redis 노드에서 해제 작업을 시작합니다.

동시에 몇 가지 세부 사항에 주의해야 합니다.

잠금을 획득하기 위한 재시도 간격은 고정된 시간이 아닌 임의의 범위여야 합니다. 이렇게 하면 여러 클라이언트가 동시에 Redis 클러스터에 잠금 획득 작업을 보내는 것을 방지하고 동시 경쟁을 피할 수 있습니다. 동시에 동일한 개수의 잠금을 획득하는 상황입니다. (확률은 매우 낮지만)

마스터 노드에 장애가 발생한 경우 복구 시간 간격은 잠금 유효 시간보다 커야 합니다.

  1. 세 개의 Redis 노드 A, B, C가 있다고 가정합니다.

  2. 클라이언트 foo는 두 개의 잠금 A와 B를 획득합니다.

  3. 이때 B가 다운되어 메모리에 있던 데이터가 모두 손실됩니다.

  4. 노드 B가 응답합니다.

  5. 이때 클라이언트 바는 잠금을 다시 획득하고 B, C 두 개의 노드를 획득합니다.

  6. 현재 두 명의 고객이 추가로 잠금을 획득했습니다.

따라서 복구 시간이 잠금 유효 시간보다 길면 위 상황을 피할 수 있습니다. 동시에 성능 요구 사항이 높지 않은 경우 Redis의 지속성 옵션을 켤 수도 있습니다.

Summary

Redis의 분산 구현을 이해하고 나니 실제로 대부분의 분산 시스템의 원리는 매우 간단하다는 것을 느꼈지만 분산 시스템의 신뢰성을 보장하기 위해서는 많은 세부 사항과 사소한 예외 사항을 지불해야 합니다. 주의.

RedLock 알고리즘으로 구현된 분산 잠금은 간단하고 효율적이며 아이디어가 매우 영리합니다.

하지만 RedLock은 반드시 안전한가요? 나는 또한 이 문제를 논의하는 기사를 쓸 것입니다. 기대해주세요.

관련 권장 사항:

redisson의 분산 잠금 구현 방법 원리에 대한 자세한 설명

php redis 분산 잠금 및 작업 대기열 코드 예제 자세한 설명

분산 잠금의 여러 구현 방법

위 내용은 Redis의 분산 잠금 구현에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.