>데이터 베이스 >Redis >Redis의 공통 분산 잠금 원칙 및 구현(요약 공유)

Redis의 공통 분산 잠금 원칙 및 구현(요약 공유)

WBOY
WBOY앞으로
2022-08-25 11:53:502471검색

추천 학습: Redis 비디오 튜토리얼

Java의 잠금에는 주로 JUC 패키지의 동기화된 잠금 및 잠금이 포함되어 있으며 이러한 잠금은 단일 JVM 인스턴스의 잠금에 사용되며 분산 환경에서는 유효하지 않습니다. 분산 잠금 기반 구현?

일반적인 분산 잠금의 구현은 다음과 같습니다.

데이터베이스 기반

Pessimistic Lock

Pessimistic Lock(Pessimistic Lock)은 이름에서 알 수 있듯이 매우 비관적인 잠금이며, 데이터가 검색될 때마다 잠깁니다. 이러한 방식으로 비관적 잠금이 해제될 때까지 데이터를 얻으려는 다른 사용자는 차단됩니다. 비관적 잠금의 공유 리소스는 한 번에 하나의 스레드에서만 사용되며, 다른 스레드는 사용 후 차단됩니다. 그러나 효율성 측면에서 잠금 메커니즘은 추가 오버헤드를 생성하고 교착 상태가 발생하기 쉽습니다.

구현 원칙

비관적 동시성 제어는 실제로 데이터 처리의 보안을 보장하는 "잠금을 먼저 확보한 후 액세스"하는 보수적인 전략입니다.

특정 구현

예: 인벤토리 비관적 잠금을 통해 추론이 이루어집니다. 의사 코드는 다음과 같습니다.

// 对于库存记录进行行锁

SELECT *FROM sys_goods s WHERE s.Id='1' FOR UPDATE;

//执行库存扣减
update sys_stock s set s.stockQty=s.stockQty-#{number} where s.goodId=1 and s.stockQty>0;

//提交事务,自动释放悲观锁。

Optimistic lock

Introduction

Optimistic 잠금은 데이터 버전 번호(version) 메커니즘을 기반으로 구현됩니다. 데이터베이스 테이블에 "버전" 필드를 추가합니다. 업데이트 프로세스 중에 이 버전 번호가 판독됩니다. 버전 번호가 일치하면 작업이 성공적으로 실행되고 버전 번호가 표시됩니다. 1. 버전 번호가 일치하지 않으면 업데이트가 실패합니다.

구현 원리

낙관적 잠금의 구현은 데이터베이스의 잠금 메커니즘을 사용하지 않고 CAS(비교 및 교체) 메커니즘을 사용하여 구현됩니다. .

  • 1, 비교: A 값을 읽고 B로 업데이트하기 전에 원래 값이 여전히 A인지 확인합니다(다른 스레드에 의해 변경되지 않음).
  • 2, 설정: If 변경 사항이 전송되지 않으면 A를 B로 업데이트하고 종료합니다. 변경 사항이 발생하면 아무 작업도 수행하지 마십시오.

특정 구현

예를 들어, 재고 공제를 달성하기 위한 낙관적 잠금의 의사 코드는 다음과 같습니다.

// 查询库存记录,获取版本号
SELECT stockQty,version FROM sys_goods s WHERE s.Id='1'

//执行库存扣减,防止出现超卖
update sys_stock s set 
  s.stockQty=s.stockQty-#{number},
  s.version=version+1
  where s.goodId=1 and s.stockQty>0 and version=#{version};

Redis는 분산 잠금을 구현합니다.

Redis 분산 잠금 구현에 대해서는 이전 기사에서 설명했습니다. 다음 글을 참고하세요

Spring Boot는 Redis 분산 잠금 원리를 구현합니다

Spring Boot는 Redisson을 통합하여 분산 잠금 세부 사례를 구현합니다

Zooker는 분산 잠금을 구현합니다

Zookper는 주로 임시 및 임시 잠금을 사용하여 분산 잠금을 구현합니다. 질서정연함을 달성하기 위해 사육사 노드의 합입니다.

잠금 프로세스

클라이언트 1이 요청하면 Zookeeper 클라이언트는 영구 노드 잠금 노드를 생성합니다. 클라이언트 1이 잠금을 획득하려는 경우 모든 임시 노드를 찾으면 임시 노드 /node_000000을 생성합니다. under Locks 정렬된 하위 노드는 가장 작은 노드일 때 성공적으로 잠금을 획득합니다.

클라이언트 2가 잠금을 획득하려고 하면 잠금 상태에 있는 임시 노드도 확인하여 자체 노드/node_000001이 가장 작은지 확인합니다. 가장 작지 않으면 잠금 획득에 실패하고 클라이언트 2는 실패합니다. node_000000 노드는 node_000000이 존재하는지 감시하기 위해 watch 이벤트를 등록합니다. 비록 잠금 획득에 실패하더라도 node_000001은 대기 상태로 들어갑니다.

잠금 해제 과정

주키퍼의 클라이언트 업무가 완료되거나 클라이언트에 장애가 발생하면 임시 노드가 삭제되고 잠금이 해제됩니다. 작업이 완료되면 클라이언트 1은 node_000000을 삭제하라는 명령도 명시적으로 호출합니다.

예를 들어 위 그림에서는 클라이언트 1의 연결이 끊어지고 임시 노드 node_000000이 삭제되었습니다. 이때 node_000001은 감시자 모니터링을 통해 자신을 가장 작은 임시 노드로 발견하므로 잠금을 성공적으로 획득합니다.

异常场景分析

客户端1创建临时节点后,会与Zookeeper服务器维护一个Session,这个Session会依赖客户端 定时心跳来维持连接。由于网路异常原因,Zookeeper长时间收不到客户端1的心跳,就认为这个Session过期了,也会把这个临时节点删除,此时客户端2创建临时节点能够获取锁成功。当客户端网络恢复正常后,它仍然认为持有锁,此时就会造成锁冲突。

具体实现

Zookeeper实现分布式锁,可以采用Curator实现分布式锁,关于SpringBoot如何集成Curator,大家可以参考如下文章:

Java Spring Boot 集成Zookeeper

Zookpeer实现分布式锁实现库存扣减

 @RequestMapping("/lockStock")
    public void lockStock()
    {
       zooKeeperUtil.lock("/Locks", 1000, TimeUnit.SECONDS, ()->{
           //业务逻辑
       });
    }

小结:

关于分布式锁的实现的对比,详情请查看下图:

推荐学习:Redis视频教程

위 내용은 Redis의 공통 분산 잠금 원칙 및 구현(요약 공유)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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