Redis 분포 식 잠 금 10 연속 질문 실현
7075 단어 javaredis
분산 식 잠 금 은 여러 프로 세 스 간 에 서로 배척 하 는 목적 을 달성 하 는 것 이다.흔히 볼 수 있 는 방안 은 DB 의 유일한 색인,Zookeeper 의 임시 질서 있 는 노드,Redis 의 SETNX 를 바탕 으로 이 루어 진다.Redis 는 고성능 이 광범 위 하 게 사용 되 기 때문에 본 고 는 일문일답 방식 으로 Redis 가 분포 식 자 물 쇠 를 어떻게 실현 하 는 지 알 고 자 한다.
1.Redis 는 분포 식 잠 금 을 어떻게 실현 합 니까?
Redis
에서 제공 하 는SETNX
명령 을 사용 하여 한 번 만 기록 할 수 있 도록 합 니 다.SETNX key value
만약 에
key
만 존재 하지 않 으 면key
에 값 을value
로 설정 합 니 다.주어진key
이 이미 존재 한다 면 아무것도 하지 않 는 다.127.0.0.1:6379> setnx lock 001
(integer) 1
127.0.0.1:6379> setnx lock 002
(integer) 0
물론
SET
명령 을 사용 하고NX
키 워드 를 사용 할 수 있 습 니 다.set NX
2.자 물 쇠 를 가 져 온 노드 가 끊 기 면 어떻게 하나
만약 에
SETNX
명령 만 사용 하면 특정한 노드 가 자 물 쇠 를 선점 할 때 현재 노드 가 끊 으 면 이 자 물 쇠 를 풀 지 못 하고 결국은 자물쇠 가 나타 날 것 이다.이때 생각 나 는 것 은key
에 만 료 시간 을 설정 하 는 것 이다.그러면 노드 가 끊 어도 자동 으로 삭제 된다.127.0.0.1:6379> expire lock 5
(integer) 1
이상 expire 명령 을 사용 하여 만 료 시간 을 설정 합 니 다.
3.Set 가 Expire 미 실행 노드 를 실행 하면 끊 습 니 다
상기 문제 의 원인 은
SETNX
명령 과Expire
원자 조작 이 아니 기 때문에 모든 것 이SETNX
명령 을 집행 한 후에 노드 가 끊 어 질 수 있 기 때문이다.이때Expire
가 미 처 집행 하지 못 하면 자물쇠 가 풀 리 지 않 고 자물쇠 가 꺼 지 는 현상 이 나타 날 수 있다.127.0.0.1:6379> set lock 001 ex 5 nx
OK
위의 명령 과 같이
SETNX
명령 을 하나의 원자 조작 으로 통합 시 켜 동시에 성공 하고 실 패 를 보장 합 니 다.4.자 물 쇠 를 가 져 오지 않 은 노드 는 어떻게 차단 합 니까?
자 물 쇠 를 얻 지 못 한 노드 는 차단 상태 에 있 고 정시 에 다시 시도 하여 첫 번 째 시간 에 자 물 쇠 를 얻 을 수 있 도록 해 야 합 니 다.
while(true){
set lock uuid ex 5 nx; ##
if( ){
break;
}
......
sleep(1); ## CPU
}
기능 이 더 강해 지 려 면 차단 시간 을 지정 할 수 있 습 니 다.지정 한 차단 시간 을 초과 하면 잠 금 을 가 져 오 는 데 실 패 했 습 니 다.
5.자물쇠 의 재 입 문 제 를 해결 하면
다시 들 어 갈 수 있 는 것 은 특정한 스 레 드 가 자 물 쇠 를 가 져 오 면 현재 스 레 드 가 다시 자 물 쇠 를 가 져 올 때 자물쇠 에 들 어 갈 수 있 을 것 입 니 다.다시 들 어 갈 때마다 수량 을 하나 더 하고 나 올 때 하 나 를 줄 일 수 있 습 니 다.로 컬 은
Expire
또는 직접 사용threadId
으로 실현 할 수 있다.물론 관련 정 보 를ThreadLocal
에 직접 저장 하고Redis
Redisson
스 크 립 트 를 사용 하여lua
정 보 를 기록 하 는 것 이 좋 습 니 다.if (redis.call('exists', KEYS[1]) == 0) then ##
redis.call('hincrby', KEYS[1], ARGV[2], 1); ## , threadId
redis.call('pexpire', KEYS[1], ARGV[1]); ##
return nil;
end;
if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then ## threadId id
redis.call('hincrby', KEYS[1], ARGV[2], 1); ## threadId
redis.call('pexpire', KEYS[1], ARGV[1]); ##
return nil;
end; "
return redis.call('pttl', KEYS[1]);
6.기한 이 지나 면 임무 가 마침 끝나 면 어떻게 되 는 지
일반적으로 우리 가 예상 한 만 료 시간 은 상대 적 으로 임 무 를 수행 하 는 시간 보다 길 기 때문에 임 무 를 수행 한 후에 삭제 작업 을 할 것 이다.
127.0.0.1:6379> del lock
(integer) 1
A 노드 가 가 져 온 자물쇠 가 만 료 되 고 자물쇠 가 삭 제 될 가능성 이 있 습 니까?이때 B 노드 가 자 물 쇠 를 가 져 와 다시
threadId
명령 을 실 행 했 습 니 다.마침 A 노드 작업 이 완성 되 었 고 자물쇠 삭제 명령 을 실 행 했 습 니 다.B 노드 의 자 물 쇠 를 삭제 하면 자물쇠 가 잘못 삭 제 된 상황 이 발생 합 니 다.이러한 상황 은 우리 가 자 물 쇠 를 삭제 할 때 현재 삭 제 된 자물쇠 가 우리 가 전에 얻 은 자물쇠 인지 확인 해 야 한다.
set ex nx
때 유일한set
을 실행 할 수 있다.예 를 들 어 직접 사용value
.이렇게 삭제 할 때 우 리 는 먼저 자물쇠 에 대응 하 는uuid
값 을 가 져 온 다음 에 현재 노드 대상value
과 비교 해 야 일치 해 야 삭제 할 수 있 습 니 다.string uuid = gen(); ## value
set lock uuid ex 5 nx; ##
...... ##
string value = get lock; ## value
if(value == uuid) { ## value uuid
del lock ##
} else {
return; ##
}
7.기한 이 지 났 는데 도 임 무 를 다 수행 하지 못 하면 어떻게 하나
만 료 시간 은 예 상 된 시간 입 니 다.만약 에 특정한 작업 이 실 행 된 시간 이 길 면 마침 만 료 시간 이 되면 자물쇠 가 삭제 되 고 다른 노드 가 자 물 쇠 를 얻 을 수 있 습 니 다.그러면 여러 노드 가 동시에 자 물 쇠 를 얻 는 상황 이 발생 합 니 다.
이런 상황 은 일반적으로 이렇게 해결 된다.
우리 가 자주 사용 하 는 공구 꾸러미
value
는 내부 에 자 물 쇠 를 감시 하 는 문 지 키 는 개 를 제공 했다.그의 역할 은Redisson
사례 가 닫 히 기 전에 자물쇠 의 유효기간 을 계속 연장 하 는 것 이다.내부 사용Redisson
을 타이머 로 정기 적 으로 검사 합 니 다.8.Redis 메 인 노드 가 다운 되 었 습 니 다.노드 에서 동기 화 되 지 않 으 면 어떻게 합 니까?
우 리 는
HashedWheelTimer
주종 동기 화 는 비동기 적 인 것 을 알 고 있다.만약 에 특정한 노드 가 자 물 쇠 를 얻 었 다 면 이때 자물쇠 정 보 는 노드 에서 동기 화 되 지 않 았 고 메 인 노드 가 지연 되 었 으 며 노드 에서 주요 노드 로 업그레이드 되 어 자 물 쇠 를 잃 어 버 렸 다.이러한 상황Redis
작 가 는Redis
알고리즘 을 제 시 했 는데 대체적으로 다음 과 같은 의 미 를 가진다.Redis 의 분포 식 환경 에서 우리 가 N 개의 Redis 호스트 가 있다 고 가정 합 니 다.이 노드 들 은 완전히 독립 된 것 이기 때문에 우 리 는 복사 나 다른 암시 적 조율 시스템 을 사용 하지 않 는 다.
대부분의(N/2+1,여 기 는 3 개 노드)의 Redis 노드 에서 만 자 물 쇠 를 가 져 오고 사용 시간 이 자물쇠 의 실효 시간 보다 적 을 때 만 자 물 쇠 를 성공 적 으로 얻 을 수 있 습 니 다.
redlock
는Redisson
의 지원 을 제 공 했 고 사용 도 간단 하 다.RLock lock1 = redissonClient1.getLock(resourceName);
RLock lock2 = redissonClient2.getLock(resourceName);
RLock lock3 = redissonClient3.getLock(resourceName);
// 3 redis
RedissonRedLock redLock = new RedissonRedLock(lock1, lock2, lock3);
더 보기:redlock
9.레 디 스에 집단 뇌 분열 이 생기 면 어떻게 되 는 지
집단 뇌 분열 이란 네트워크 문제 로 인해 메 인 노드,노드 와
RedLock
가 서로 다른 네트워크 구역 에 있 는 것 을 말한다.sentinel
의 존 재 는 일부 메 인 노드 가 존재 하지 않 기 때문에 노드 를 위주 로 하 는 노드 를 향상 시 킬 수 있다.이때 서로 다른 메 인 노드 가 존재 한다.이때 서로 다른 클 라 이언 트 는 서로 다른 메 인 노드 를 연결 할 수 있다.두 클 라 이언 트 는 같은 자 물 쇠 를 동시에 가 질 수 있다.sentinel
메 인 라 이브 러 리 의 요청 처 리 를 제한 하기 위해 두 개의 설정 항목 을 제공 했다.각각Redis
과min-slaves-to-write
이다.min-slaves-max-lag
메시지 지연 은 N 초 를 초과 할 수 없습니다.그렇지 않 으 면 메 인 라 이브 러 리 에서 클 라 이언 트 의 요청 을 받 지 않 습 니 다.10.어떻게 공평 한 자 물 쇠 를 실현 합 니까?
우 리 는
ACK
ACK
을 통 해 공정 하 게 잠 그 고ReentrantLock
내 부 는 양 방향 대기 열 을 통 해 이 루어 진 다 는 것 을 알 고 있다.Redis 자체 가 목록,질서 있 는 집합 등 여러 가지 데이터 구 조 를 제공 했다.AQS
공평 한 자 물 쇠 를 실현 하 는 것 은 바로 Redis 에 내 장 된 데이터 구 조 를 통 해 이 루어 진 것 이다.총결산
어떤 방식 으로 분포 식 자 물 쇠 를 실현 하 든 우 리 는 자물쇠 의 기능 을 확보 해 야 한다.이 는 상호 배척 성,재 입 성,차단 성 을 포함한다.또한 분포 식 의 존재 로 인해 우 리 는 시스템 의 높 은 사용 가능,고성능 을 확보 하고 모든 자물쇠 가 사라 지고 동시에 자 물 쇠 를 얻 는 상황 을 근절 해 야 한다.