> Java > java지도 시간 > 본문

Redis를 사용하여 분산 잠금을 구현하는 방법

PHPz
풀어 주다: 2024-08-31 18:31:04
원래의
751명이 탐색했습니다.

나는 멍청하다

글쎄요, 로컬 시스템에서 작업할 때마다 모든 것이 버터처럼 작동합니다. 이것이 바로 우리가 "127.0.0.1보다 더 좋은 곳은 없습니다"라고 부르지만 현실을 깨우쳐 보세요

How to implement a Distributed Lock using Redis

제작 과정에서 항상 예상대로 작동하는 것은 아닙니다. 주로 애플리케이션의 여러 인스턴스를 실행할 때 발생합니다.

How to implement a Distributed Lock using Redis

? 보시다시피 애플리케이션의 여러 인스턴스가 실행 중이고 클라이언트가 사용자를 DB에서 유료 사용자로 표시하도록 요청한다고 가정해 보겠습니다.

  • 클라이언트가 서버를 요청합니다
  • 요청은 로드 밸런서에 도달합니다
  • 인스턴스 중 하나가 요청을 받고 DB에 쓰기 쿼리를 작성합니다

괜찮은 것 같죠? 지금까지는 문제가 없었습니다.

그렇습니다. 지금까지는 문제가 없습니다. 하지만 다음과 같은 비즈니스 로직을 작성하고 싶다면 어떻게 해야 할까요? -

  • DB에서 사용자 가져오기
  • 사용자가 무료 사용자인지 이미 유료인지 확인
  • 무료라면 유료로 표시하고 DB에 저장하세요
  • 결제된 경우 응답으로 "이미 결제됨"을 보내주세요.

⚡️ 알고 있듯이(여기서는 MySQL을 사용한다고 가정) MySQL DB는 ACID를 준수하므로 모든 쿼리는 원자적이고 격리됩니다. 이는 MySQL 쿼리가 원자 방식으로 실행되어 통과하거나 실패한다는 것을 의미합니다. 하지만 중간에 멈추지는 않습니다.

? 하지만 여기에는 한 가지 문제가 있습니다. 생각하다, 생각하다....

  • 1단계: 사용자를 가져오는 중입니다(Atomic 트랜잭션)
  • 2단계: 코드에서 일부 비즈니스 로직 실행
  • 3단계: 사용자가 비용을 지불하지 않은 경우 MySQL 기록 업데이트(원자적 트랜잭션)

2단계에서 결제 취소 요청이 한 번 더 들어오고 해당 쿼리가 먼저 실행되어 사용자를 무료로 표시한 다음 3단계가 실행되고 사용자가 유료로 표시되면 어떻게 될까요?

?? 만세, 사용자는 비용을 지불하지 않고도 당사 제품에 액세스할 수 있습니다.

잠금

✅ 구세주 락스가 온다
How to implement a Distributed Lock using Redis

? 잠금은 한 번에 하나의 스레드만 임계 섹션(여러 작업자가 액세스해서는 안 되는 코드 블록, 즉 스레드)에 들어갈 수 있도록 허용하는 구조입니다.

따라서 작업이 완료되기 전에 잠금을 획득하고 완료 후에 해제됩니다.-

  • 0단계: try-acquire() 잠금
  • 1단계: 획득한 경우 사용자를 가져오는 중입니다(Atomic 트랜잭션)
  • 2단계: 코드에서 일부 비즈니스 로직 실행
  • 3단계: 사용자가 비용을 지불하지 않은 경우 MySQL 기록 업데이트(원자적 트랜잭션)
  • 4단계: 잠금 해제()

? 문제

이제 문제가 발생합니다. 즉, 메모리 잠금 데이터 구조나 메모리 기반 잠금 중 일부를 사용하면 애플리케이션에 대해 하나의 인스턴스에 적합하다는 문제가 발생합니다. 동일한 코드를 실행하고 DB에서 업데이트하는 다른 인스턴스는 어떻습니까?

여기서 분산 잠금 개념이 등장합니다

? 분산 잠금

How to implement a Distributed Lock using Redis

여기서 잠금은 중앙 집중식 서비스 역할을 하며, 서비스의 한 인스턴스가 잠금을 획득하면 다른 서비스 인스턴스가 동일한 키를 사용할 수 없습니다.

결제 서비스의 핵심은 무엇인가요?

? 사용자가 결제 키를 만드는 경우 = "PAYMENT_" + user_id + 금액

의 조합이 될 수 있습니다.

이는 사용자별로 고유합니다. 그리고 이 키는 사용자가 결제를 하거나 결제를 취소하는 경우에도 동일하게 유지됩니다. 따라서 하나가 발생하면 두 작업 모두 동일한 키를 획득하려고 시도하므로 다른 작업을 진행할 수 없습니다.

? 키, 잠금 획득, 잠금 해제가 도대체 ​​뭐죠? 그리고 가장 중요한 것은 Redis가 어떻게 사용되고 있는가?


? Redis를 사용하여 분산 잠금 구현

Redis의 단일 인스턴스 사용:-

How to implement a Distributed Lock using Redis

그러나 단일 Redis 인스턴스에는 다음과 같은 몇 가지 문제가 있습니다.-

  • 단일 인스턴스가 실패하고 획득한 잠금이 해제되지 않을 수 있습니다.
  • 한 클라이언트가 하나의 인스턴스에 대해 잠금을 획득할 때 두 개의 인스턴스가 사용되는 경우(마스터-복제본)
  • 동기화하려면 마스터가 복제본과 동일하게 통신해야 합니다. 이 통신 자체가 비동기 통신입니다

? 따라서 마스터에서 잠금이 획득되고 복제본과 통신하는 동안 마스터가 복제본과 동기화되기 전에 다운되면. 레플리카는 마스터가 되며 이전에 마스터에서 획득한 동일한 키에 대한 잠금을 획득할 수 있습니다.

우리 서비스의 두 인스턴스는 두 개의 인스턴스(마스터-복제본)가 있어도 Redis에 대한 잠금을 획득할 수 있습니다.

Redlock 알고리즘 사용:-

잠금 획득:- 잠금 만료 시간이 있는 여러 Redis 인스턴스에 대한 잠금을 획득하려고 합니다
잠금 유효성 검사:- 주요 Redis 인스턴스가 클라이언트에 대해 잠금을 획득한 경우 잠금은 획득된 것으로 간주됩니다
잠금 해제:- 잠금을 해제하면 모든 인스턴스가 잠금을 해제합니다

How to implement a Distributed Lock using Redis

그렇습니다.

❤️ 읽어주셔서 감사합니다. 더 많은 기사를 보려면 뉴스레터를 구독하세요.- https://www.serversidedigest.com/

자세한 내용은 다음을 참조하세요.-

  • Java의 Jedis:- https://redis.io/docs/latest/develop/connect/clients/java/jedis/
  • Golang의 Redis 클라이언트:- https://github.com/redis/go-redis

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

원천:dev.to
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿