SpringBoot 는 Redis 를 사용 하여 분포 식 잠 금 을 실현 합 니 다.
7955 단어 SpringBootRedis분산 식 자물쇠
단일 컴퓨터 응용 시대 에 우 리 는 공 유 된 대상 을 다 중 스 레 드 로 방문 할 때 자바 의 synchronized 키워드 나 ReentrantLock 류 를 사용 하여 작업 대상 에 자 물 쇠 를 추가 하면 대상 의 스 레 드 안전 문 제 를 해결 할 수 있 습 니 다.
분산 식 응용 시대 에 이 방법 은 통 하지 않 습 니 다.우리 의 응용 은 여러 대의 기계 에 배치 되 고 서로 다른 JVM 에서 실 행 될 수 있 습 니 다.한 대상 이 여러 대의 기계 의 메모리 에 동시에 존재 할 수 있 습 니 다.공유 대상 을 어떻게 하면 한 스 레 드 로 만 처리 하 느 냐 가 문제 가 될 수 있 습 니 다.
분포 식 시스템 에서 한 대상 이 높 은 병행 상황 에서 한 라인 만 사용 할 수 있 도록 하기 위해 서 우 리 는 JVM 을 뛰 어 넘 는 상호 배척 메커니즘 으로 공유 자원 의 접근 을 제어 해 야 한다.이때 우리 의 분포 식 잠 금 을 사용 해 야 한다.
분포 식 자 물 쇠 는 일반적으로 세 가지 실현 방식 이 있다.1.데이터 베 이 스 를 통 해 분포 식 자 물 쇠 를 실현 한다.2.캐 시(Redis 등)를 통 해 분산 잠 금 을 실현 한다.3.Zookeeper 를 통 해 분포 식 잠 금 을 실현 합 니 다.이 글 은 레 디 스 를 통 해 분산 잠 금 을 실현 하 는 두 번 째 방식 을 소개 한다.
분산 식 자물쇠 의 필요 조건
분포 식 자물쇠 의 가용성 을 확보 하기 위해 서 는 다섯 가지 조건 이 필요 합 니 다.
1.같은 시간 에 기계 한 대의 스 레 드 만 자 물 쇠 를 가 질 수 있 도록 보장 합 니 다.
2.자물쇠 가 생기 면 안 되 고 자 물 쇠 를 가 진 기계 가 무 너 지면 자동 으로 자 물 쇠 를 풀 수 있어 야 합 니 다.
3.자 물 쇠 를 효율적으로 획득 하고 방출 한다.
4.비 차단 성 을 가지 고 자 물 쇠 를 얻 지 못 하면 바로 자 물 쇠 를 추가 하 는 데 실패 합 니 다.
5.독점 성,즉 자신 이 추가 한 자 물 쇠 는 자신 만 이 풀 수 있 습 니 다.
코드 구현
구성 요소 의존
우선 pom.xml 파일 에 의존 도 를 추가 합 니 다:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
잠 금 코드코드 는 다음 과 같 습 니 다:
/**
*
* @param lockKey
* @param identity ( )
* @param expireTime ( : )
* @return
*/
public boolean lock(String lockKey, String identity, long expireTime){
boolean lockResult = redisTemplate.opsForValue().setIfAbsent(lockKey, identity, expireTime, TimeUnit.SECONDS);
return opsForValue;
}
잠 금 을 추가 하 는 방법 은 세 가지 인자 만 필요 합 니 다:lockKey,idenity,expireTime.잠 금 해제 코드
코드 는 다음 과 같 습 니 다:
/**
*
* @param lockKey
* @param identity ( )
* @return
*/
public boolean releaseLock(String lockKey, String identity){
String luaScript =
"if " +
" redis.call('get', KEYS[1]) == ARGV[1] " +
"then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
DefaultRedisScript<Boolean> redisScript = new DefaultRedisScript<>();
redisScript.setResultType(Boolean.class);
redisScript.setScriptText(luaScript);
List<String> keys = new ArrayList<>();
keys.add(lockKey);
boolean result = redisTemplate.execute(redisScript, keys, identity);
return result;
}
잠 금 을 푸 는 방법 은 두 개의 인자 만 필요 합 니 다:lockKey,idenity.테스트 코드
package com.qixi.lock.demo.lockdemo.controller;
import com.qixi.lock.demo.lockdemo.util.RedisLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
*
* @author ZhengNC
* @date 2020/5/13 17:27
*/
@RestController
@RequestMapping("test")
public class TestRedisLockController {
private final String lockKeyName = "testKey";
@Autowired
private RedisLock redisLock;
/**
*
* @param id id
* @param identity
* @return
*/
@GetMapping("lock")
public String lock(@RequestParam("id") String id,
@RequestParam("identity") String identity){
String lockKey = lockKeyName+":"+id;
boolean lockSuccess = redisLock.lock(lockKey, identity, 60);
String result = "lock failed";
if (lockSuccess){
result = "lock success";
}
return result;
}
/**
*
* @param id id
* @param identity
* @return
*/
@GetMapping("release")
public String release(@RequestParam("id") String id,
@RequestParam("identity") String identity){
String lockKey = lockKeyName+":"+id;
boolean releaseSuccess = redisLock.releaseLock(lockKey, identity);
String result = "release failed";
if (releaseSuccess){
result = "release success";
}
return result;
}
}
package com.qixi.lock.demo.lockdemo.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* Redis
* @author ZhengNC
* @date 2020/5/13 17:27
*/
@Component
public class RedisLock {
@Autowired
private RedisTemplate<String, String> redisTemplate;
/**
*
* @param lockKey
* @param identity ( )
* @param expireTime ( : )
* @return
*/
public boolean lock(String lockKey, String identity, long expireTime){
boolean lockResult = redisTemplate.opsForValue().setIfAbsent(lockKey, identity, expireTime, TimeUnit.SECONDS);
return lockResult;
}
/**
*
* @param lockKey
* @param identity ( )
* @return
*/
public boolean releaseLock(String lockKey, String identity){
String luaScript =
"if " +
" redis.call('get', KEYS[1]) == ARGV[1] " +
"then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
DefaultRedisScript<Boolean> redisScript = new DefaultRedisScript<>();
redisScript.setResultType(Boolean.class);
redisScript.setScriptText(luaScript);
List<String> keys = new ArrayList<>();
keys.add(lockKey);
boolean result = redisTemplate.execute(redisScript, keys, identity);
return result;
}
}
결어제 글 을 읽 어 주 셔 서 감사합니다. 제 문 제 를 지적 해 주신 것 을 환영 합 니 다.여기 서 토론 을 통 해 공동의 발전 을 이 룰 수 있 기 를 바 랍 니 다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
【Java・SpringBoot・Thymeleaf】 에러 메세지를 구현(SpringBoot 어플리케이션 실천편 3)로그인하여 사용자 목록을 표시하는 응용 프로그램을 만들고, Spring에서의 개발에 대해 공부하겠습니다 🌟 마지막 데이터 바인딩에 계속 바인딩 실패 시 오류 메시지를 구현합니다. 마지막 기사🌟 src/main/res...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.