이 기사는 분산 잠금이 무엇인지 주로 소개하는 Redis에 대한 관련 지식을 제공합니다. Redis는 분산 잠금을 어떻게 구현합니까? 어떤 조건을 충족해야 합니까? 아래 내용을 살펴보겠습니다. 도움이 필요한 친구들에게 도움이 되기를 바랍니다.
분산 잠금: 분산 시스템 또는 클러스터 모드에서 여러 프로세스에 표시되고 상호 배타적인 잠금입니다.
분산 잠금이 충족해야 하는 조건:
세 가지 일반적인 분산 잠금이 있습니다:
Mysql: mysql 자체에는 잠금 메커니즘이 있지만 mysql의 평균 성능으로 인해 , 분산 잠금을 사용할 때 실제로 mysql을 분산 잠금으로 사용하는 경우는 상대적으로 드뭅니다
Redis: 분산 잠금으로서의 redis는 요즘에는 기본적으로 redis나 Zookeeper를 사용하는 방식이 매우 일반적입니다. setnx 메소드를 사용하여 키가 성공적으로 삽입되면 누군가가 성공적으로 삽입하면 다른 사람은 잠금을 얻을 수 없음을 나타냅니다. 분산 잠금 구현
Zookeeper: Zookeeper는 엔터프라이즈 수준 개발에서 분산 잠금을 구현하는 데에도 더 나은 솔루션입니다
두 가지 기본 방법에 필요한 분산 잠금 구현 시 구현:
잠금 획득:
잠금 해제:
Redis 기반 분산 잠금 원칙 구현:
SET resource_name my_random_value NX PX 30000
NX의 원자성을 사용하면 여러 스레드가 동시에 실행될 때 하나의 스레드만 성공적으로 설정될 수 있습니다. 성공적인 설정은 잠금을 획득했음을 의미합니다. 후속 비즈니스 처리가 가능합니다. 예외가 발생하고 잠금이 만료되면 잠금이 자동으로 해제됩니다.
1. Redis를 기반으로 분산 잠금을 구현합니다. - RedisLockpublic interface ILock extends AutoCloseable {
/**
* 尝试获取锁
*
* @param timeoutSec 锁持有的超时时间,过期后自动释放
* @return true代表获取锁成功;false代表获取锁失败
*/
boolean tryLock(long timeoutSec);
/**
* 释放锁
* @return
*/
void unLock();
}
잠금 실수 삭제 문제
문제 설명:
해결책:
잠금을 저장할 때 자신의 스레드 ID를 입력하세요. 잠금을 삭제할 때 현재 잠금의 ID가 저장한 ID인지 판단하세요. 그렇지 않다면 삭제하세요. , 삭제가 수행되지 않습니다.
버전 2: 실수로 잠금을 삭제하는 문제 해결public class SimpleRedisLock {
private final StringRedisTemplate stringRedisTemplate;
private final String name;
public SimpleRedisLock(StringRedisTemplate stringRedisTemplate, String name) {
this.stringRedisTemplate = stringRedisTemplate;
this.name = name;
}
private static final String KEY_PREFIX = "lock:";
@Override
public boolean tryLock(long timeoutSec) {
//获取线程标识
String threadId = Thread.currentThread().getId();
//获取锁
Boolean success = stringRedisTemplate.opsForValue()
.setIfAbsent(KEY_PREFIX + name, threadId, timeoutSec, TimeUnit.SECONDS);
return Boolean.TRUE.equals(success);
}
@Override
public void unLock() {
//通过del删除锁
stringRedisTemplate.delete(KEY_PREFIX + name);
}
@Override
public void close() {
unLock();
}
}
잠금 해제의 원자성 문제
이유는 Java 코드로 구현된 잠금 해제 프로세스가 원자적 연산이 아니며 스레드 안전성 문제가 있기 때문입니다.
해결책:Redis는 Lua 스크립트 기능을 제공합니다. 하나의 스크립트에 여러 Redis 명령을 작성하면 여러 명령 실행의 원자성을 보장할 수 있습니다.
버전 3: Lua 스크립트를 호출하여 분산 잠금 변환public class SimpleRedisLock {
private final StringRedisTemplate stringRedisTemplate;
private final String name;
public SimpleRedisLock(StringRedisTemplate stringRedisTemplate, String name) {
this.stringRedisTemplate = stringRedisTemplate;
this.name = name;
}
private static final String KEY_PREFIX = "lock:";
private static final String ID_PREFIX = UUID.randomUUID().toString(true) + "-";
@Override
public boolean tryLock(long timeoutSec) {
//获取线程标识
String threadId = ID_PREFIX + Thread.currentThread().getId();
//获取锁
Boolean success = stringRedisTemplate.opsForValue()
.setIfAbsent(KEY_PREFIX + name, threadId, timeoutSec, TimeUnit.SECONDS);
return Boolean.TRUE.equals(success);
}
@Override
public void unLock() {
// 获取线程标示
String threadId = ID_PREFIX + Thread.currentThread().getId();
// 获取锁中的标示
String id = stringRedisTemplate.opsForValue().get(KEY_PREFIX + name);
// 判断标示是否一致
if(threadId.equals(id)) {
// 释放锁
stringRedisTemplate.delete(KEY_PREFIX + name);
}
}
@Override
public void close() {
unLock();
}
}
권장 학습: "
"
위 내용은 분산 잠금의 원리와 Redis가 분산 잠금을 구현하는 방법에 대해 이야기해 보겠습니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!