redis 기반 분포 식 잠 금 의 원리 와 방법
시스템 이 계속 확대 되 고 분포 식 자 물 쇠 는 가장 기본 적 인 보장 이다.한 기계 의 다 중 스 레 드 와 달리 분포 식 은 여러 기계 에 걸 쳐 있다.스 레 드 의 공유 변 수 는 기 계 를 뛰 어 넘 을 수 없습니다.
자바 병렬 처 리 는 높 은 병렬 저장 장면 에서 같은 스 레 드 로 만 작 동 할 수 있 도록 ReentrantLock 또는 Synchronized 를 제공 하여 상호 배척 통 제 를 제공 합 니 다.하지만 이 는 단기 환경 에 만 효과 가 있다.우 리 는 분포 식 자 물 쇠 를 대략 세 가지 방식 으로 실현 한다.
redis 분포 식 잠 금 실현데이터 베 이 스 는 분포 식 잠 금 을 실현 한다분포 식 잠 금 실현
오늘 우 리 는 redis 를 통 해 분포 식 자 물 쇠 를 실현 하 는 것 을 소개 한다.실제로 이 세 가 지 는 자바 와 비교 해 보면 한 종류 에 속한다.모두 프로그램 외부 자물쇠 에 속 합 니 다.
원리 분석
4.567917.상기 세 가지 분포 식 자 물 쇠 는 모두 각자 의 근 거 를 통 해 각 요구 에 대해 자 물 쇠 를 잠 그 고 자 물 쇠 를 풀 어 놓 는 것 을 제어 하 는 것 입 니 다.redis 잠 금 은 setnx 명령 을 기반 으로 합 니 다4.567917.setnx 는 키 만 존재 하지 않 습 니 다.주어진 키 가 존재 한다 면 setnx 는 동작 을 하지 않 습 니 다.setnx 는 원자 적 인 조작 이다4.567917.데이터베이스 분포 식 에 비해 redis 메모리 가 가 볍 기 때 문 입 니 다.그래서 redis 분산 잠 금 성능 이 더 좋 습 니 다.
이루어지다
원 리 는 간단 하 다.springboot 프로젝트 와 결합 하여 우 리 는 주해 형식 을 통 해 인 터 페 이 스 를 재고 잠 금 사례 로 이해 하 는 것 을 실현 합 니 다.
주 해 를 쓰다
우 리 는 주 해 를 쓴다.인터페이스 에 주 해 를 추가 하여 차단 정 보 를 제공 하 는 데 편리 합 니 다.
/**
* @author
* @version V1.0
* @Package com.ay.framework.order.redis.product
* @date 2020 03 26 , 0026 10:29
* @Copyright © 2020
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface StockLock {
/**
* @author zxhtom
* @Description key
* @Date 15:25 2020 03 25 , 0025
* @Param []
* @return java.lang.String
*/
String prefix() default "";
/**
* @author zxhtom
* @Description key
* @Date 15:27 2020 03 25 , 0025
* @Param []
* @return java.lang.String
*/
String delimiter() default ":";
}
/**
* @author
* @version V1.0
* @Package com.ay.framework.order.redis.product
* @date 2020 03 26 , 0026 11:09
* @Copyright © 2020
*/
@Target({ElementType.PARAMETER , ElementType.METHOD , ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface StockParam {
/**
* @author zxhtom
* @Description key
* @Date 11:11 2020 03 26 , 0026
* @Param []
* @return java.lang.String[]
*/
String[] names() default {""};
}
차단기redis 분산 잠 금 실현 의 관건 은 차단기 의 작성 이다.위의 주 해 는 단지 차단 을 실현 하기 위 한 보조 일 뿐이다.
@Around("execution(public * *(..)) && @annotation(com.ay.framework.order.redis.product.StockLock)")
springboot 의 Around 를 통 해 StockLock 주 해 를 차단 합 니 다.차단 을 통 해 차단 하 는 방법,파라미터,그리고 필요 한 자물쇠 의 인 자 를 얻 을 수 있 습 니 다.잠 금 이 필요 한 이름 을 가 져 왔 습 니 다.
우리 가 재 고 를 삭감 할 때 재 고 를 갱신 하 는 것 을 편리 하 게 하기 위해 서.우 리 는 재 고 를 점차 줄 이기 전에 또 다른 자 물 쇠 를 빌려 야 한다.이 자 물 쇠 는[a]라 고 합 니 다.key】
다시 말 하면 우리 인터페이스 가 방문 하려 면[a]자 물 쇠 를 가 져 와 야 하고[a]자 물 쇠 를 가 져 오 려 면 재 고 를 줄 여야 합 니 다.재 고 를 줄 이기 전에 획득[a열쇠
자 물 쇠 를 가 져 온 후에 논 리 를 처리 한 후에 우 리 는 대응 하 는 자 물 쇠 를 풀 어야 한다.
RedisAtomicLong entityIdCounter = new RedisAtomicLong(lockKey, redisTemplate.getConnectionFactory());
if (redisTemplate.hasKey(CoreConstants.UPDATEPRODUCTREDISLOCKKEY + lockKey)) {
// lockKey 。
throw new BusinessException(" 。 ");
}
Long increment = entityIdCounter.decrementAndGet();
if (increment >= 0) {
try {
Object proceed = pjp.proceed();
} catch (Throwable throwable) {
//
while (!redisLock.tryGetLock(CoreConstants.UPDATEPRODUCTREDISLOCKKEY + lockKey, "")) {
}
// lockKey 。
long l = entityIdCounter.incrementAndGet();
if (l < 1) {
redisTemplate.opsForValue().set(lockKey,1);
}
redisLock.unLock(CoreConstants.UPDATEPRODUCTREDISLOCKKEY + lockKey);
throwable.printStackTrace();
}
} else {
redisTemplate.opsForValue().set(lockKey,0);
throw new BusinessException(" ! ");
}
우리 가 자 물 쇠 를 채 우려 면 자 물 쇠 를 풀 어야 하기 때문이다.그러나 프로그램 이 중간 에 업 무 를 처리 하 는 것 은 이상 이 발생 하여 자 물 쇠 를 풀 어 주 는 절차 에 이 르 지 못 했다.이 럴 때 우리 의 분포 식 자물쇠 가 계속 잠 겨 있다.속칭[자물쇠]라 고 한다.이런 장면 을 피하 기 위해 서우 리 는 항상 자 물 쇠 를 채 울 때 유효기간 을 준다.유효기간 이 지나 자 자동 으로 자 물 쇠 를 풀 었 습 니 다.이 특성 은 redis 의 만 료 전략 과 일치 하지 않 습 니 다.상기 언급 도구
RedisLock
public Boolean tryGetLock(String key , String value) {
return tryGetLock(key, value, -1, TimeUnit.DAYS);
}
public Boolean tryGetLock(String key , String value, Integer expire) {
return tryGetLock(key, value, expire, TimeUnit.SECONDS);
}
public Boolean tryGetLock(String key , String value, Integer expire , TimeUnit timeUnit) {
ValueOperations operations = redisTemplate.opsForValue();
if (operations.setIfAbsent(key, value)) {
// redis key ,
if (expire > 0) {
redisTemplate.expire(key, expire, timeUnit);
}
return true;
}
return false;
}
public Boolean unLock(String key) {
return redisTemplate.delete(key);
}
StockKeyGenerator
@Component()
@Primary
public class StockKeyGenerator implements CacheKeyGenerator {
@Override
public String getLockKey(ProceedingJoinPoint pjp) {
//
MethodSignature signature = (MethodSignature) pjp.getSignature();
Method method = signature.getMethod();
// cacheLock
StockLock stockLock = method.getAnnotation(StockLock.class);
//
Object[] args = pjp.getArgs();
Parameter[] parameters = method.getParameters();
StringBuilder builder = new StringBuilder();
for (int i = 0; i < parameters.length; i++) {
StockParam stockParam = parameters[i].getAnnotation(StockParam.class);
Object arg = args[i];
if (arg instanceof Map) {
Map<String, Object> temArgMap = (Map<String, Object>) arg;
String[] names = stockParam.names();
for (String name : names) {
if (builder.length() > 0) {
builder.append(stockLock.delimiter());
}
builder.append(temArgMap.get(name));
}
}
}
return builder.toString();
}
}
문제 분석위 에서 자물쇠 가 없 는 장면 을 분 석 했 는데 이론 적 으로 자물쇠 가 나 왔 다.우리 redis 분포 자 물 쇠 는 분포 식 문 제 를 잘 해결 했다.그래도 문제 가 생 길 수 있 습 니 다.다음은 편집장 이 만난 문 제 를 열거 하 겠 습 니 다.
업무 처리 시간>잠 금 만 료 시간
a 라인 에서 자 물 쇠 를 가 져 오고 업무 처 리 를 시작 하려 면 8S 가 필요 합 니 다.
8S 에서 자물쇠 의 유효기간 은 5S 이 고 자물쇠 가 만 료 된 후에 6S 입 니 다.b 스 레 드 가 들 어가 자 물 쇠 를 얻 기 시 작 했 을 때 b 는 새로운 자 물 쇠 를 얻 을 수 있 습 니 다.이 럴 때 문제 야.
b 스 레 드 업무 처리 에 3S 만 필요 하 다 고 가정 하지만 a 스 레 드 가 자 물 쇠 를 풀 었 기 때문에 8S 에 b 스 레 드 가 자 물 쇠 를 풀 지 않 았 고 b 의 자물쇠 도 기한 이 지나 지 않 았 지만 이때 도 자물쇠 가 없 었 다.이 로 인해 C 라인 도 들 어 갈 수 있다
총결산
여기 서 redis 를 바탕 으로 분포 식 잠 금 을 실현 하 는 원리 와 방법 을 바탕 으로 하 는 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 관련 redis 분포 식 잠 금 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 바 랍 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Redis 해시에 대한 완벽한 가이드변경 가능하므로 필요에 따라 쉽게 변경하고 업데이트할 수 있습니다. Redis 해시는 구조가 평평하므로 JSON에서와 같이 여러 수준을 가질 수 없습니다. redis 해시의 명명 규칙은 hash:key 로 입력되므로...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.