>  기사  >  데이터 베이스  >  Redis의 잠금에 대한 간략한 분석, Redlock(redis 분산 잠금)에 대해 이야기해 보겠습니다.

Redis의 잠금에 대한 간략한 분석, Redlock(redis 분산 잠금)에 대해 이야기해 보겠습니다.

青灯夜游
青灯夜游앞으로
2022-01-20 10:07:3013774검색

이 글에서는 Redis의 잠금에 대해 설명하고 잠금이 사용되는 이유를 소개합니다. Redlock(redis 분산 잠금)이 정말 필요한가요? 모두에게 도움이 되기를 바랍니다!

Redis의 잠금에 대한 간략한 분석, Redlock(redis 분산 잠금)에 대해 이야기해 보겠습니다.

잠금 장치를 사용해야 하는 이유

제가 근무했던 k12 교육 회사에서는 이런 비즈니스 시나리오가 있었습니다. 비즈니스 측에서 학생을 위한 수업을 준비해야 하는 경우가 있습니다. 학생의 수업 시간은 확실히 충분하지만 수업 시간이 부족하다는 피드백이 페이지를 새로 고치면 더 이상 충분하지 않은 것으로 확인됩니다. 더욱 무서운 점은 학생들의 수업시간이 마이너스로 깎이는 경우가 가끔 있다는 것입니다(회사의 수업시간은 무료로 사용됩니다). [관련 추천사항 : Redis 영상 튜토리얼]

또 다른 예시는 다음과 같습니다

Redis의 잠금에 대한 간략한 분석, Redlock(redis 분산 잠금)에 대해 이야기해 보겠습니다.

위의 두 가지 문제는 모두 우리 사업의 동시성으로 인한 문제입니다. 이 문제에 대한 핵심 솔루션은 하나의 요청만 이러한 민감한(중요한) 데이터를 동시에 읽고 쓸 수 있도록 허용된다는 것입니다. 따라서 이때 프로그램의 동시 실행을 제한하려면 분산 잠금을 사용해야 합니다.

setnx의 문제점은 무엇입니까

먼저 누구나 익숙할 Redis를 이용한 분산 잠금 구현 방법을 살펴보겠습니다. 예를 들어, 내 기사의 시작 부분에서 언급한 학생 수업 일정 문제의 경우 다음과 같이 잠글 수 있습니다

Redis의 잠금에 대한 간략한 분석, Redlock(redis 분산 잠금)에 대해 이야기해 보겠습니다.

이것이 우리가 일상적으로 setnx를 사용하여 잠금을 구현하는 방법입니다.

이제 그런 시나리오가 있다고 가정해 보겠습니다. A씨에게 잠금장치를 요청하자 2단계 학생수업 일정에서 프로그램이 중단돼 잠금이 해제되지 않았다. 그러면 잠금이 교착 상태가 됩니다. 동일한 학생을 조작하려는 다음 요청은 잠금을 얻지 못하며 학생을 예약할 수 없습니다. 이때 잠금을 수동으로 해제해야 합니다.

교착 상태 문제를 해결하기 위해 잠금에 만료 시간을 추가합니다.

Redis의 잠금에 대한 간략한 분석, Redlock(redis 분산 잠금)에 대해 이야기해 보겠습니다.

만료 시간을 추가한 후 요청 A가 적극적으로 잠금을 해제하지 않으면 잠금이 만료된 후에 적극적으로 해제되므로 요청 B도 잠금 처리 비즈니스 로직을 얻을 수 있습니다. 그러나 만료 시간이 추가되면 프로그램이 1단계와 2단계 사이에서 충돌이 발생합니다. 그러면 여전히 교착 상태 문제가 발생합니다. 이 문제의 근본 원인은 setnx 및 만료 두 명령이 원자적 명령이 아니라는 것입니다. 따라서 setnx와 만료가 모두 실행되거나 전혀 실행되지 않으면 좋을 것입니다.

이러한 이유로 Redis2.8 이전에는 이 문제를 해결하기 위해 커뮤니티에 수많은 확장 패키지가 등장했습니다. 이러한 혼란을 제어하기 위해 공식은 버전 2.8에서 set 명령어의 확장 매개변수를 추가하여 setnx 및 만료 명령어를 함께 실행할 수 있으므로 이제 다음과 같은 분산 잠금을 사용해야 합니다

Redis의 잠금에 대한 간략한 분석, Redlock(redis 분산 잠금)에 대해 이야기해 보겠습니다.

이것은 완벽해 보입니다. "setnx와 만료가 모두 실행되거나 전혀 실행되지 않는다면 좋을 것입니다."라는 우리의 기대는 달성되었습니다. 이제 다음과 같은 시나리오가 있다고 가정해 보겠습니다.

요청이 이제 잠금을 획득하고 잠금 시간 제한이 5초로 설정되었습니다. 2단계에서는 비즈니스 로직이 실행되는데 어떤 이유에서인지 5초 후에도 비즈니스 로직이 실행되지 않았습니다. 이때 타임아웃으로 인해 잠금이 자동으로 해제됩니다. 이때 B요청도 왔고, Lock을 받은 후 비즈니스 로직이 실행되기 시작했습니다. 이때 A의 요청에 대한 비즈니스 로직이 실행되어 세 번째 단계가 시작되고 잠금이 해제됩니다. 이때 B의 요청으로 Lock을 획득했으나 A의 요청으로 해제되었다. 그러면 C 요청이 잠금을 얻을 수 있습니다. 이때 요청 B와 요청 C는 동시성 문제를 발생시킵니다. 따라서 이 예에서 분산 잠금의 만료 시간 설정이 매우 중요하다는 것을 알 수 있습니다. 설정 시간이 이 인터페이스의 응답 시간보다 짧으면 동시성 문제가 계속 발생합니다. 따라서 잠금 만료 시간을 설정하려면 인터페이스 응답 시간 모니터링을 참조할 수 있습니다.

Redlock

위의 솔루션은 모두 단일 지점 Redis 구현을 기반으로 합니다. 분산 잠금의 단일 지점 Redis 구현은 기본적으로 비즈니스 시나리오의 95%를 충족할 수 있습니다. 나머지 5%는 데이터 일관성에 대한 매우 엄격한 요구 사항과 잠금 손실에 대한 무관용이 적용되는 비즈니스 시나리오입니다. 이때 Redlock을 고려해야 합니다. 단일 포인트 Redis의 경우 Sentinel을 통해 고가용성을 보장하더라도 마스터 노드가 어떤 이유로 마스터-슬레이브를 전환하고 마스터-슬레이브 데이터 동기화가 적시에 이루어지지 않으면 데이터 손실이 발생하고 잠금 손실이 발생합니다. .

여러 Redis 인스턴스가 있다고 가정합니다. 이러한 노드는 완전히 독립적이며 데이터 조정을 위해 복제 또는 시스템을 사용할 필요가 없습니다. 클라이언트가 잠금을 얻으려면 5개의 Redis 마스터 노드가 있다고 가정합니다. 단계는 다음과 같습니다:

  • 현재 서버 시간을 밀리초 단위로 가져옵니다

  • 잠금을 획득하려면 동일한 키와 임의의 값을 사용해 보십시오. 클라이언트는 잠금을 획득할 때 각 머신에 대해 시간 제한을 두어야 합니다. 예를 들어 잠금의 만료 시간은 10초이고 단일 획득에 대한 시간 제한이 있습니다. 노드 잠금은 약 5~50밀리초여야 합니다. 이것의 목적은 클라이언트가 실패한 시스템에 연결하는 데 추가 시간을 낭비하지 않도록 하는 것입니다. 제한 시간 내에 데이터를 획득하지 못한 경우 해당 노드는 폐기되고 다음 Redis 노드를 획득하게 됩니다.

  • 획득이 완료된 후 클라이언트가 Redis 노드의 절반 이상(여기서는 3개 노드)에서 잠금을 획득한 경우에만 현재 시간에서 1단계에서 획득한 시간을 뺀 시간과 획득한 시간을 획득합니다. 잠금이 잠금 시간 제한 시간보다 작으면 잠금이 효과적이라는 것을 증명합니다!

  • 잠금이 획득되면 키의 실제 유효 시간은 유효 시간에서 잠금을 획득하는 데 사용된 시간을 뺀 값과 같습니다(3단계에서 계산된 결과).

  • 잠금을 획득한 머신의 절반 이상이 만족되지 않거나 계산 후 잠금 시간 초과가 음수이거나 기타 비정상적인 작업이 수행되는 경우 일부 Redis 인스턴스가 잠겨 있지 않더라도 시스템은 모든 인스턴스의 잠금을 해제하려고 시도합니다. 일부 노드는 잠금을 획득했지만 클라이언트는 응답을 받지 못하여 일정 기간 동안 잠금을 다시 획득할 수 없게 됩니다. 단일 지점 Redis보다 안정적인 잠금.

  • 나와 같은 Node.js 프로그래머라면 직접 사용할 수 있는 타사 라이브러리
redlock

가 있습니다.

우리에게 레드락이 정말로 필요한가

실제로 레드락에 대한 또 다른 목소리가 있습니다. Martin Kleppmann(캠브리지 대학 연구원, 데이터베이스와 분산 시스템의 교차점에서 TRVE DATA 프로젝트에 참여)이 쓴 글입니다. 및 정보 보안) Redlock에 대한 몇 가지 견해에 대해

블로그

를 게시한 적이 있습니다. 관심이 있으시면 읽어보실 수 있습니다. Redis 작성자 Salvatore도 이 기사의 질문에 대해 응답을 했는데, 이는 매우 흥미롭습니다. 저자 블로그의 주요 내용은 다음과 같습니다. 분산 잠금은 두 번 이상 사용할 수 없습니다.

효율성: 잠금을 사용하면 불필요한 동일한 작업을 두 번 수행하는 것을 피할 수 있습니다(예: 비용이 많이 드는 계산). 잠금이 실패하고 두 노드가 모두 동일한 작업을 수행하게 되면 결과적으로 비용이 약간 증가하거나(다른 경우보다 AWS에 5센트를 더 지불하게 됨) 약간의 불편함(예: 사용자가 결국 동일한 이메일을 받게 됨)이 발생합니다. 공고).

정확성: 잠금을 사용하면 동시 프로세스가 서로 간섭하고 시스템 상태가 손상되는 것을 방지할 수 있습니다. 잠금이 실패하고 두 노드가 동일한 데이터 조각을 동시에 처리하는 경우 결과적으로 파일 손상, 데이터 손실, 영구적인 불일치, 환자에게 잘못된 약물 투여량 또는 기타 매우 심각한 문제가 발생합니다.
  • 효율성을 위해서라면 Redlock의 비용과 복잡성을 감당할 필요가 없습니다. 잠금 손실로 인해 여러 개의 이메일을 보내는 비용과 Redis 서버 5대를 운영하는 데 드는 비용에 비해 그냥 사용하는 것이 좋습니다. 단일 Redis 인스턴스. 단일 Redis 인스턴스를 사용하고 있는데 Redis 노드의 전원이 갑자기 꺼지거나 충돌이 발생하거나 다른 문제가 발생하는 경우 물론 이때 잠금이 손실됩니다. 그러나 효율성 최적화를 위해 잠금을 사용하고 이러한 충돌이 자주 발생하지 않는다면 큰 문제는 아닙니다. 이 "별것 아닌" 시나리오가 바로 Redis가 뛰어난 부분입니다. 최소한 단일 Redis 인스턴스에 의존한다면 시스템을 보는 모든 사람이 문제를 더 쉽게 찾을 수 있을 것입니다.
  • 정확성을 위해서라면 엄밀히 말하면 Redlock은 Strong Consistency의 엄격함을 전혀 가지고 있지 않습니다. 다음은 몇 가지 예입니다

타이밍 및 시스템 시계는 위험한 가정을 하며 각 서버의 시계에 크게 의존합니다. 시스템에 GC가 있기 때문에 GC 중에 서버 전체가 램핑되고, 시간이 정체되어 시계에 대한 강한 의존성을 가질 수 없습니다.

  • 토큰이 없습니다. 서버는 클라이언트가 잠금을 획득할 때마다 토큰을 발행하지 않습니다. 서버는 잠금 작동을 어렵게 하기 위해 각 작업 중에 클라이언트의 토큰이 서버의 현재 토큰과 일치해야 하는지 확인해야 합니다.

  • 저자는 위의 관점을 주로 다루고 있으니 관심이 있으신 분은 원문을 읽어보시길 권합니다.

  • 더 많은 프로그래밍 관련 지식을 보려면
프로그래밍 소개

를 방문하세요! !

위 내용은 Redis의 잠금에 대한 간략한 분석, Redlock(redis 분산 잠금)에 대해 이야기해 보겠습니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 juejin.cn에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제