본문 바로가기

IT for developer/Hadoop+Nosql

BLENDING TIME IN HBASE

원문: http://outerthought.org/blog/417-ot.html

HBase에 타임스탬프에 관한 글이다.

발번역~ 차라리 구글번역이 낫겠지만. 개인적으로 공부한다고 생각으로 발번역중

BigTable 과 같은 HBase는 흔치않고, 분산, 영구적인 다차원 정렬맵이다. (흠냐.)

이 맵은 row 키, 컬럼 키 그리고 타입 스탬프로 색인되어 있고 맵안에 각 값은 바이트의 배열로 되어있다. 좀 더 자세히 보면, Hbase에는 테이블과 컬럼 패밀리라는 또 다른 차원을 가지고 있다.

그 차원들은 모두 동일하지 않다. 예를 들어, row 차원은 조각날 수 있고 매우 커질수 있다. 컬럼은 조각되지 않지만 row들과 비교하여 하나의 row 안에 다중 컬럼이 원자적으로 put 또는 delete 될수 있다.
(put and delete는 원자적으로 처리할 수 없다. put  or delete 단일 오퍼레이션만 원자적 수행가능), 이 문서에서는 우리는 시간 차원(Time Dimension) 세부사항에 집중할 것이다.

시간 차원을 HBase에서 자동 버전화 되는 것으로 간주할 수 있다. 그래서 이게 필요하지 않다면 무시할 것이다. 시간 지정없이 get, put, delete와 같은 오퍼레이션을 수행할 수있고 기대한대로 일반적으로 수행될 것이다. 그러나, 현재 구현되어 있는 몇몇 톡특한 요소들은 시간 차원을 이해하면 더 좋을 것이다.

Basics



용어
BigTable 논문에서, {로우키, 컬럼키} 쌍은 하나의 셸(cell)을 가르키고 각 셸은 타임스탬프로 색인되어 있는 다중 버전을 포함하고 있다고 설명하고 있다.

시간/버전 차원에 키

row 키들과 컬럼 키들은 바이트s인 반면에 시간 차원에 키는 long 정수형이다. 전형적으로 java.util.Date.getTime() 또는 System.currentTimeMillis()에 의해 리턴된 값과 같은 것을 포함하고 있다.

시간 차원은 내림 정렬로 저장된다, 그래서 저장 파일로 부터 읽을 때 가장 최근의 값을 먼저 찾는다.

우리는 기본 오퍼레이션들에 대해 시간 차원의 행동을 살펴볼 것이다. get, put and delete


Get

디폴트로 get을 수행하면 각 셸마다 가장 큰 타입스탬프를 가진 버전이 리턴된다.
디폴트 행동은 두가지 방법으로 변화를 줄 수 있다.
Get.setMaxVersions() 함수를 통해 하나의 버전이상을 리턴하게 할 수 있다.
Get.setTimeRange() 함수를 통해 최근 것들과 다른 버전들을 리턴할 수 있다.
지나칠수 있는 흥미로은 옵션한가지는 주어진 타임스탬프보다 작거나 같은 최신버전을 가져올 수 있는 것이다.
가장 최근것이 아니라 특정시점에서 최근 것을 가져온다는 개념이다.
setMaxVersions(1), setTimeRange(0, 특정시점) 이렇게 설정하면되겠다.


Put

Put을 수행하는 것은 특정 타임스탬프에서 항상 셸의 새로운 버전을 생성한다. 디폴트로 시스템은 currentTimeMillis를 사용하지만 각 컬럼 레벨로 특정 타임스탬프를 지정할 수도 있다. 이는 과거 또는 미래의 시간을 지정할 수 있다는 의미이거나 시간과 무관한 의미로 long 값을 사용할 수도 있다.

저장소 아키텍쳐 깊숙하게 까지 가지 않는다면, HBase는 기본적으로 데이터를 overwrite 하지 않고 append 한다. 데이터 파일들은 compaction 프로세스에 의해 한번씩 다시 써진다. 데이터 파일은 기본적을 키-값 쌍들의 리스트이고 키는  {로우 키, 컬럼 키, 시간} 이다. 존재하는 셸에 대해 새로운 값을 쓰는 put을 수행하면, 새로운 키-값 쌍이 append 된다. 설령 존재하는 타임스탬프를 지정하였더라도 같다. 짧은 시간에 같은 row를 많이 업데이트하는 것은 저장소에 많은 키-값 쌍이 있게만든다. 가비지 컬렉션셋팅에 의존하여 다음 compaction동안 제거될 것이다.

Delete

delete와 시간 차원에 대하여 말할게 많다.

가비지 컬렉션

무엇보다도, 버전들을 자동으로 가지치기 하는 두 가지 방법이 있다.

  • 최대 버전 수를 지정할 수 있다. 지정한 버전수 이상이면 가장 오래된 것이 제거된다. 디폴트 값은 3이다.
    이는 HColumnDescriptor.setMaxVersions(int versions)를 통해 컬럼 패밀리를 생성할 때 설정된다. 실제 삭제는 , major compaction에서 수행된다. get과 scan을 수행할 때도 그 결과는 항상 최대 버전을 어떻게 설정했느냐에 따라 달라진다. 그래서 최대 버전 셋팅을 1로 하는것은 진짜로 버저닝을 비활성화하는것이 아니다. 새로운 버전을 생성하고 최근것만 유지하는 것이다.
  • TTL(time-to-live)를 지정할 수 있다. 만약에 TTL보다 예전 버전이 있다면 이는 삭제될 것이다.  디폴트 TTL이 '영원히'이고 HColumnDescriptor.setTimeToLive(int seconds)를 통해 설정된다. 다시, 버전들의 실제 삭제는 major compaction에서 수행된다, 하지만 get과 scan은 TTL이 지난 버전들을 리턴하는 것을 즉시 멈출 것이다. TTL이 row의 모든 셀들에 전달될 때 그 row는 없어진다. Hbase는 row의 명시적인 생성이나 삭제가 없다. 단지 셸안에 값이 있으면 존재하는 것이다.

 경험적으로 이러한 행동들을 증명하는 흥미로운 행동은 다음과 같다. maximun-version을 2로 세팅하여 t1, t2, t3 세가지 버전이 셸을 생성한다고 가정하자. 모든 버전을 얻을 때 t2와 t3만 리턴할 것이다. 그러나 t2 또는 t3 버전을 지운다면 t1이 다시 나타날 것이다. 명백히, major compaction이 동작하면 그러한 행동은 더이상 일어나지 않을 것이다. (그래서 major compaction은 사용자들에게 완전히 투명하지 않다)


Manual delete
 
HBase에서 delete 오퍼레이션을 수행할 때  지우는 버전을 명시하는 두 가지 방법이 있다.

  • 특정 타임스탬프 보다 오래된 모든 버전을 지우기
  • 특정 타입스탬프의 버전만 지우기
 delete가 완전한 row, 완전한 컬럼 패밀리 또는 컬럼 하나에 적용할 수 있다. 이는 컬럼을 지우는 경우에 특정 타임스탬프의 버전만 지우기가 가능하며 로우 또는 패밀리안에 모든 컬럼을 지우는 것에 대해서는 특정 시간보다 오래된 모든 셸을 지우도록 행동한다.

Delete create tombstone markers

예를 들어, 하나의 row를 지우길 원한다고 가정하자. 이를 위해 특정 타임스탬프를 지정하거나 디폴트로 현재 시간이 사용될 수도 있다. 이 타임스탬프보다 같거나 작은 타임스탬프를 가진 모든 셸들을 삭제하라는 것은 무슨 의미일까? HBase는 결코 그곳에 데이터를 수정하지 않는다. tombtone 이라는 것은 마크 지울 값들을 표시하는 것이다. HBase가 major comaction을 수행했을 때, tombstone은 tombstone 자신과 함께 죽은 값들을 실제적으로 처리할 것이다.
만약에 당신이 지정한 타임스탬프가 row의 어떤값의 타임스탬프보다 크다면 완전한 row가 지워지는 것을 고려해야한다.

타임 차원은 버전 
키값을 long 값을 가지는 컬럼으로 유사하게 처리할 수 있지만 현재 버그로 인해 추천되어지지 않는다.
타임스탬프에 관한 Jira issues - 생략

Limitations

Overwriting values at existing timestamps.(0.90 버전에서 해결함) - 이해 안됨;

Delete mark puts :delete는 마크를 남긴다 --> delete후 만약 TTL보다 오래된 타임스탬프를 가지고 put 하면 이는 major compaction 때 삭제된다.

-------------------------------------------------------------------------
노드들의 시간 동기화는 상당히 중요하다.

rdate를 이용하여 동기화하기

/usr/bin/rdate -s time.bora.net && /sbin/clock -w