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에 직접 저장 하고RedisRedisson스 크 립 트 를 사용 하여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 노드 에서 만 자 물 쇠 를 가 져 오고 사용 시간 이 자물쇠 의 실효 시간 보다 적 을 때 만 자 물 쇠 를 성공 적 으로 얻 을 수 있 습 니 다.redlockRedisson의 지원 을 제 공 했 고 사용 도 간단 하 다.
    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메 인 라 이브 러 리 의 요청 처 리 를 제한 하기 위해 두 개의 설정 항목 을 제공 했다.각각Redismin-slaves-to-write이다.
  • min-slaves-to-write:메 인 라 이브 러 리 에서 데이터 동기 화 를 할 수 있 는 최소 라 이브 러 리 수량
  • 을 설정 하 였 습 니 다.
  • min-slaves-max-lag:라 이브 러 리 에서 데 이 터 를 복사 할 때 라 이브 러 리 에서 메 인 라 이브 러 리 로 보 내 는 최대 지연(초 단위)
  • 설정 항목 조합 후 메 인 라 이브 러 리 연결 을 요구 하 는 라 이브 러 리 에서 최소한 N 개가 라 이브 러 리,메 인 라 이브 러 리 에서 데 이 터 를 복사 할 때min-slaves-max-lag메시지 지연 은 N 초 를 초과 할 수 없습니다.그렇지 않 으 면 메 인 라 이브 러 리 에서 클 라 이언 트 의 요청 을 받 지 않 습 니 다.
    10.어떻게 공평 한 자 물 쇠 를 실현 합 니까?
    우 리 는ACKACK을 통 해 공정 하 게 잠 그 고ReentrantLock내 부 는 양 방향 대기 열 을 통 해 이 루어 진 다 는 것 을 알 고 있다.Redis 자체 가 목록,질서 있 는 집합 등 여러 가지 데이터 구 조 를 제공 했다.AQS공평 한 자 물 쇠 를 실현 하 는 것 은 바로 Redis 에 내 장 된 데이터 구 조 를 통 해 이 루어 진 것 이다.
  • 목록 을 스 레 드 대기 열 로 사용 하고 새로운 대기 열 을 목록 의 끝 에 추가 합 니 다.
  • 대기 스 레 드 를 질서 있 게 집합 하여 저장 하 는 순서 입 니 다.점수 score 는 스 레 드 를 기다 리 는 시간 초과 스탬프 입 니 다.

  • 총결산
    어떤 방식 으로 분포 식 자 물 쇠 를 실현 하 든 우 리 는 자물쇠 의 기능 을 확보 해 야 한다.이 는 상호 배척 성,재 입 성,차단 성 을 포함한다.또한 분포 식 의 존재 로 인해 우 리 는 시스템 의 높 은 사용 가능,고성능 을 확보 하고 모든 자물쇠 가 사라 지고 동시에 자 물 쇠 를 얻 는 상황 을 근절 해 야 한다.

    좋은 웹페이지 즐겨찾기