>데이터 베이스 >Redis >Redis 분산 잠금을 구현하는 방법

Redis 분산 잠금을 구현하는 방법

尚
원래의
2019-06-29 10:43:4625203검색

Redis 분산 잠금을 구현하는 방법

redis 분산 잠금:
1. 구현 원칙
분산 잠금을 구현하려면 redis에서 set 명령을 사용하세요.

Redis 버전 2.6.12부터 set은 다음 매개변수를 사용할 수 있습니다.

SET KEY VALUE [EX 초] [PX 밀리초] [NX|XX]

EX 초: 키의 만료 시간을 초로 설정합니다. . SET 키 값 EX 초의 효과는 SETEX 키 초 값과 동일합니다.
PX 밀리초: 키 만료 시간을 밀리초 밀리초로 설정합니다. SET 키 값 PX 밀리초 효과는 PSETEX 키 밀리초 값과 동일합니다.
NX: 키가 존재하지 않는 경우에만 키를 설정하세요. SET 키 값 NX의 효과는 SETNX 키 값과 동일합니다.
XX: 키가 이미 존재하는 경우에만 키가 설정됩니다.
반환 값:
SET은 설정 작업이 성공적으로 완료된 경우에만 OK를 반환합니다.
NX 또는 XX를 설정했지만 조건이 충족되지 않아 설정 작업이 실행되지 않은 경우 명령은 NULL 대량 응답을 반환합니다.
명령:
> SET 키 값 EX ttl NX

일반적인 아이디어는 다음과 같습니다.
(a) SET lock currentTime+expireTime EX 600 NX, set을 사용하여 잠금 값을 설정하고 만료 시간을 600초로 설정합니다. 성공, 잠금 획득

(b) 잠금을 획득한 후 노드가 오프라인이 되면 ock 값은 만료 시간에 자동으로 만료됩니다.
(c) 잠금을 해제할 때 del을 사용하여 잠금 키 값을 삭제합니다.
Redis 독립형 머신을 사용하여 분산 잠금 수행 서비스에는 단일 지점 문제가 있어 서비스 가용성이 저하될 수 있습니다. 따라서 서비스 안정성이 높은 상황에서는 Redis 클러스터(예: 클러스터 5개)를 사용하는 것이 공식적으로 권장됩니다. 3개 이상의 성공적인 잠금 요청이 성공하면 잠금은 획득된 것으로 간주되어 Redis 스타일 잠금을 달성합니다. 자세한 내용은 RedLock을 참조하세요.
2. 장점
고성능, redis는 지속 가능하고 데이터가 쉽게 손실되지 않습니다.
redis 클러스터 방식은 안정성을 향상시킵니다.
3. 단점
Redis 마스터-슬레이브 전환을 사용하면 일부 데이터가 손실될 수 있습니다.
4. 오픈 소스 구현
Python 버전의 오픈 소스 구현: python-redis-lock.

Redis 분산 잠금의 구체적인 구현 방법:

잠금 및 잠금 해제 방법:

private static final String LOCK_SUCCESS = "OK";
    private static final String SET_IF_NOT_EXIST = "NX";
    private static final String SET_WITH_EXPIRE_TIME = "PX";
    private static final Long RELEASE_SUCCESS = 1L; 

    /**
     * 尝试获取分布式锁
     * @param lockKey 锁
     * @param requestId 请求标识
     * @param expireTime 超期时间
     * @return 是否获取成功
     */
    public Boolean tryGetDistributedLock(String lockKey, String requestId, int expireTime) {
        Jedis jedis = this.jedisPool.getResource();
        String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
        if (LOCK_SUCCESS.equals(result)) {
            return true;
        }
        return false;

    }

     /**
     * 释放分布式锁
     * @param lockKey 锁
     * @param requestId 请求标识
     * @return 是否释放成功
     */
    public Boolean releaseDistributedLock(String lockKey, String requestId) {
        Jedis jedis = this.jedisPool.getResource();
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
        if (RELEASE_SUCCESS.equals(result)) {
            return true;
        }
        return false;

    }

2. 특정 애플리케이션

try{
String requestId = UUID.randomUUID().toString();
Boolean flag = tryGetDistributedLock(lock,requestId,1000);
int n = 0;
while(!flag){
      //如果没有获取锁,可以尝试下一个lock,如果都没有,则尝试 n 次,退出
     ...
     if(n++>5){ throw new Exception("尝试获取锁失败");}  
     ...  
}
if(!flag){
throw new Exception("尝试获取锁失败");
}
}catch(){
}finally{
    releaseDistributedLock(lock,requestId);
}

더 많은 Redis 관련 지식을 보려면 Redis 사용 튜토리얼 칼럼을 방문하세요!

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

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.