임대차 계약 메커니즘 및 hbase에서의 응용

임대차 계약 메커니즘 및 hbase에서의 응용
Lease가 필요한 이유
분포식 시스템에서 왜 임대 계약 메커니즘이 필요한지 분포식 시스템에서 서비스의 높은 가용을 확보하기 위해 서비스가 고장날 때 다른 서비스 실례를 제때에 가동하여 고장 서비스를 교체해야 하기 때문이다.이렇게 하면 서비스 측과 클라이언트 또는 서비스 측과 제어 센터에서 심장 박동 정보를 유지해야 한다. 서비스 프로세스가 제어 센터에 현재 자신의 건강 상태를 보고하는 데 사용된다. 만약에 제어 센터가 한동안 서비스 프로세스에 보고된 심장 박동을 받지 못하면 새로운 프로세스를 시작하여 대외적으로 서비스를 계속 제공할 것이다.
그러나 실제 네트워크 상황의 복잡성 때문에 제어센터가 심장박동을 받을 수 없을 때 서비스가 고장났는지 서비스 프로세스와 제어센터 간의 네트워크가 고장났는지 정확하게 판단할 수 없다.이 경우 컨트롤 센터에서 새 프로세스를 섣불리 사용하면 이중 호스트가 발생할 수 있습니다.
상기 상황을 피하기 위해 임대차 계약 메커니즘을 도입했다. 이때 서비스 노드는 지속적으로 통제센터에 단시간 임대차 계약을 신청한다. 통제센터는 이미 파견된 임대차 계약이 만료되기 전에 새로운 서비스 노드를 사용하지 않고 서비스 노드 임대차 계약이 만료될 때 통제센터에서 새 임대차 계약을 신청할 수 없으면 스스로 고객 링크를 끊는다.
그 밖에 임대차 계약 메커니즘은 클라이언트와 서비스 측 간의 해근에 사용되고 클라이언트 프로세스가 응답을 잃을 때 그가 점용하는 서비스 측 자원이 장기적으로 방출되지 않아 서비스 측의 안정에 영향을 미치지 않도록 한다.
Lease 구현
실제 시스템에서 만약에 하나의 중심 결점에 의존하여 외부에lease를 발표하는 데 큰 위험이 존재한다. 즉, 이 중심 결점에 다운되거나 네트워크 고장이 발생하면 서비스 노드가 새로운 임대차 계약을 받지 못해 전체 서비스 집단이 사용할 수 없는 상태로 들어갈 수 있다.따라서 실제 사용에서 대외적으로lease 서비스를 제공하는 것은 여러 프로세스 실례로 구성된 또 다른 집단이다. 이 집단은 높은 가용성을 가지고 대외적으로lease 서비스를 제공할 수 있다. 예를 들어zookeeper 집단이다.
HREgionServer 임대 계약 Lease 관리
임대차 계약의 초기화
HREgion Server의run 메인 순환에서preRegistration Initialization을 호출하여 그룹 연결 정보 setupCluster Connection (), healthCheckChore,pause Monitor, initialize Zookeeper, initialize Threads () 를 초기화합니다.
그 중에서 initializeThreads()에서 각종 라인을 초기화합니다. 이 라인은 이 RegionServer의lease 라인을 포함합니다.

this.compactionChecker = new CompactionChecker(this, this.threadWakeFrequency, this); //  
this.periodicFlusher = new PeriodicMemstoreFlusher(this.threadWakeFrequency, this);  // memstore flush  
this.leases = new Leases(this.threadWakeFrequency); 
Leases 클래스의 정의는 다음과 같습니다. 이것은 HasThread라는 추상적인 클래스를 계승하고 다음과 같은 몇 가지 주요 구성원 변수를 정의합니다.

public static final int MIN_WAIT_TIME = 100; 
private final Map<String, Lease> leases = new ConcurrentHashMap<String, Lease>(); 
 
protected final int leaseCheckFrequency; 
protected volatile boolean stopRequested = false; 
그 중에서 맵형 구성원 변수leases는 이 지역 서버 프로세스의lease 실례를 관리하는 것을 맡고 있으며, lease 클래스가 어떤 변수를 정의했는지 살펴보자.

private final String leaseName; 
private final LeaseListener listener; 
private int leaseTimeoutPeriod; 
private long expirationTime; 
lease Timeout Period는 임대차 계약 시간입니다. expiration Time은 lease가 생성될 때 시스템 시간과 lease Timeout Period의 합으로 설정됩니다. 이 임대차 계약이 얼마나 사용되었는지 주기적으로 계산하는 데 사용됩니다. 만약에 임대차 계약이 lease Timeout Period가 정의한 만료 시간을 초과하면 expired 이벤트를 촉발합니다. Lease Listener는 이 이벤트를 감청하고 lease Expired 방법을 호출합니다.서로 다른 유형의 Lease는 LeaseListener 인터페이스를 계승하고 자신의 LeaseExpired 방법을 실현한다. 다음과 같이 scan lease가 이 방법에 대한 실현은 다음과 같다.

@Override 
public void leaseExpired() {    //  
  RegionScannerHolder rsh = scanners.remove(this.scannerName); 
  if (rsh != null) { 
   RegionScanner s = rsh.s; 
   LOG.info("Scanner " + this.scannerName + " lease expired on region " 
     + s.getRegionInfo().getRegionNameAsString()); 
   try { 
    Region region = regionServer.getRegion(s.getRegionInfo().getRegionName()); 
    if (region != null && region.getCoprocessorHost() != null) { 
     region.getCoprocessorHost().preScannerClose(s); 
    } 
 
    s.close(); 
    if (region != null && region.getCoprocessorHost() != null) { 
     region.getCoprocessorHost().postScannerClose(s); 
    } 
   } catch (IOException e) { 
    LOG.error("Closing scanner for " 
     + s.getRegionInfo().getRegionNameAsString(), e); 
   } 
  } else { 
   LOG.warn("Scanner " + this.scannerName + " lease expired, but no related" + 
    " scanner found, hence no chance to close that related scanner!"); 
  } 
 } 
클라이언트의 scan 요청은 여러 차례의 RPC 요청으로 분해되어 서버에 보내는 것입니다. 분해 횟수는 scan의 총 데이터 양과 클라이언트 setCache의 비례값입니다.모든scan 요청이 서버에 전송되면 현재scanner를 임대합니다. 현재scan이 끝난 후에 후속scan은 기존의 자원을 직접 복용할 수 있지만, scanner가 장기적으로 서버 자원을 점용하는 것을 방지하기 위해 임대 계약을 통해 더 이상 사용하지 않는 scanner를 닫습니다.
OK, 앞의 Leases 클래스로 돌아가서 RegionServer 프로세스의 각각lease를 어떻게 관리하는지 보십시오. 이 부분의 논리는 덮어쓰는 run 방법에 있습니다.

public void run() { 
  long toWait = leaseCheckFrequency; 
  Lease nextLease = null; 
  long nextLeaseDelay = Long.MAX_VALUE; 
 
  while (!stopRequested || (stopRequested && !leases.isEmpty()) ) { 
 
   //  
 
   nextLease = null; 
   nextLeaseDelay = Long.MAX_VALUE; 
   for (Iterator<Map.Entry<String, Lease>> it = leases.entrySet().iterator(); it.hasNext();) { 
    Map.Entry<String, Lease> entry = it.next(); 
    Lease lease = entry.getValue(); 
    long thisLeaseDelay = lease.getDelay(TimeUnit.MILLISECONDS); 
    if ( thisLeaseDelay > 0) { 
     if (nextLease == null || thisLeaseDelay < nextLeaseDelay) { 
      nextLease = lease; 
      nextLeaseDelay = thisLeaseDelay; 
     } 
    } else { 
     // A lease expired. Run the expired code before removing from map 
     // since its presence in map is used to see if lease exists still. 
     if (lease.getListener() == null) { 
      LOG.error("lease listener is null for lease " + lease.getLeaseName()); 
     } else { 
      lease.getListener().leaseExpired(); 
     } 
     it.remove(); 
    } 
   } 
  } 
  close(); 
 } 
우리는 일부 이상 처리를 생략하고while의 순환 주기에 맵에서 관리하는lease를 하나하나 편리하게 할 것입니다. 각각lease의thisLeaseDelay를 계산해서lease가 만료되었는지 확인합니다.lease가 만료되었는지 판단하는 방법은 매우 간단하다. 바로 현재 시간과lease에서 정의한expirationTime를 꺼내서 나쁘게 하는 것이다. 만약에 차이가 0보다 작으면 이 임대차 계약이 만료되었다는 것을 설명하고lease에서 정의한leaseExpired 방법을 사용한다. 이것은 위에서 말한 것과 관련이 있다.그 중에서thisLeaseDelay는 다음lease 검사가 얼마나 후에 발생할지 결정한다.thisLeaseDelay의 계산 근거는 모든 미기한lease 중leaseDelay가 가장 짧은 것을 선택하여thisLeaseDelay를 통해 toWait 시간을 계산하여 앞의 수면 시간을 결정하는 데 사용한다.
읽어주셔서 감사합니다. 여러분에게 도움이 되었으면 좋겠습니다. 본 사이트에 대한 지지에 감사드립니다!

좋은 웹페이지 즐겨찾기