Google AdSense (text)

hidden logo stop

Moving

거지 같은 이글루스 광고노출 정책이 싫어서,
새 보금자리(http://blog.leocat.kr/)로 이사감.

[HBase] version, delete와 tombstone 문제 Computer & Program

HBase를 쓸 일이 있어서 조사 중.. 헌데 이거 제대로 파악 안 하고 썼다가는 성능도 꽝에다 집어 넣은 데이터가 없어져 버리는 경우도 생길 수도 있을 것 같다. 잘 찾아보고 조심해서 쓰자..


우선은 HBase의 cell version과 삭제(delete)에 관한 얘기이다.
HBase의 cell은 {row, column 그리고 version}으로 나타낸다. 테이블이니 row와 column은 당연한데 version은 먼고?? HBase는 같은 cell에 또 다른 데이터를 넣으면 기존의 데이터를 지우고 그 자리에 새로운 값을 넣는 것이 아니라, 같은 row/column에 또 다른 version을 가진 cell이 추가되는 형태이다.

간단히 예제를 보자. 아래와 같이 테스트 테이블을 생성하고 같은 cell에 version(명령의 마지막 전달인자)을 명시해서 put한다. version은 생략해도 된다. 생략하면 put을 수행한 시간이 사용될 것이다. (Java의 System.currentTimeMillis() 사용)

hbase(main):029:0> create 't1', 'c1'
0 row(s) in 1.0220 seconds

hbase(main):030:0> put 't1', 'r1', 'c1', '111', 10
0 row(s) in 0.0170 seconds

hbase(main):031:0> put 't1', 'r1', 'c1', '222', 20
0 row(s) in 0.0040 seconds

hbase(main):032:0> put 't1', 'r1', 'c1', '333', 30
0 row(s) in 0.0030 seconds


현재 상태에서 cell의 값을 꺼내오면 version이 가장 큰 값인 '333'이 꺼내진다. version을 생략했다면 현재 시간이 들어가게 되니, 가장 큰 version 값은 가장 최근에 put한 값일 것이다.
아래처럼 get 명령에 "VERSIONS=>10" 옵션을 함께 주면 해당 cell에 put된 값 중 version이 높은 순으로 최대 10개의 값을 꺼내온다.

hbase(main):033:0> get 't1', 'r1'
COLUMN                     CELL
c1:                       timestamp=30, value=333
1 row(s) in 0.0100 seconds

hbase(main):034:0> get 't1', 'r1', {COLUMN => 'c1', VERSIONS => 10}
COLUMN                     CELL
c1:                       timestamp=30, value=333
c1:                       timestamp=20, value=222
c1:                       timestamp=10, value=111
3 row(s) in 0.0170 seconds


다시 여기에 '444'를 넣으면 기존에 있던 가장 오래된(version이 낮은) '111'이 안 보이게 된다. 왜냐?? version을 너무 많이 보관할 수 없기 때문에 최대 version 개수까지만 보여주는데 default 설정은 3개이다. 때문에 version을 내림차순으로 정렬하고 3개를 넘어가면 제거되는 것이다.

하지만 직접적으로 version을 지정해 주면 get해 올 수 있다. 단, 이건 major compaction을 수행하면 제거되어 보이지 않을 것이다. 여기서 HBase의 delete 동작을 엿볼 수 있다. HBase는 delete를 수행할 때 삭제할 cell을 바로 제거하지 않고 tombstone이라는 marker를 이용한다. 삭제할 cell을 표시하고, major compaction을 수행할 때 한 번에 모아서 제거하게 된다. tomestamp=10 이라는 cell을 지워야하지만 아직은 그 자리에 두고 묘비(tombstone)만 세워둬서 삭제됨 표시를 하는 것이다. 언제 죽을지 모르니 이 cell은 사용하지 않는게 맞는 것이다.

hbase(main):036:0> put 't1', 'r1', 'c1', '444', 40
0 row(s) in 0.0040 seconds

hbase(main):037:0> get 't1', 'r1', {COLUMN => 'c1', VERSIONS => 10}
COLUMN                     CELL
c1:                       timestamp=40, value=444
c1:                       timestamp=30, value=333
c1:                       timestamp=20, value=222
3 row(s) in 0.0090 seconds

hbase(main):039:0> get 't1', 'r1', {TIMESTAMP => 10}
COLUMN                     CELL
c1:                       timestamp=10, value=111
1 row(s) in 0.0080 seconds


여기서 아래처럼 delete에 version에 timestamp=30을 지정해보자. 그러면 30을 포함한 그 이전의 값들이 삭제된다. 하지만 역시나 tombstone에만 기록되기 때문에 major compaction이 수행되기 전까지는 남아 있다.

hbase(main):043:0* delete 't1', 'r1', 'c1', 30
0 row(s) in 0.0100 seconds

hbase(main):044:0> get 't1', 'r1', {COLUMN => 'c1', VERSIONS => 10}
COLUMN                     CELL
c1:                       timestamp=40, value=444
1 row(s) in 0.0040 seconds


여기서 tombstone을 사용하면서 발생하는 버그가 있다. 위와 같이 timestamp=30을 delete한 다음 아래처럼 put을 했는데, get을 해보니 마지막에 넣은 '555'가 나오지 않는 것이다. 'VERSIONS => 10'을 주어도 보이지 않는 것이다. 앞에서 삭제한 timestamp=30 보다 새로 넣은 cell의 timestamp인 15가 작기 때문에 무시되는 것이다. 이 상태로 major compaction이 수행되면 delete 이후에 put한 cell은 version에 따라 빛도 못 보고 그대로 사라질 수 있는 것이다. 이 문제는 HBase 문서에도 기술되어 있으며, 앞으로는 tombstone이 어떻게 변경될지는 모르겠다. (현재 HBase는 release 버전은 0.92.1, snapshot 버전은 0.95-SNAPSHOT)

hbase(main):045:0> put 't1', 'r1', 'c1', '555', 15
0 row(s) in 0.0200 seconds

hbase(main):046:0> get 't1', 'r1'
COLUMN                     CELL
c1:                       timestamp=40, value=444
1 row(s) in 0.0050 seconds

hbase(main):047:0> get 't1', 'r1', {COLUMN => 'c1', VERSIONS => 10}
COLUMN                     CELL
c1:                       timestamp=40, value=444
1 row(s) in 0.0080 seconds



소스까지 열어보진 않았지만, 여기서 tombstone에 대해 조심스레 예상해 볼 수 있는건..
각 row/column 마다 tombstone에 삭제된 version을 기록한다는 것.
그리고 이 version 이하의 값을 가지는 cell은 삭제 대상으로 보고 무시된다는 것.
요기는 어디까지나 예상이기 때문에 믿거나 말거나~ ㅋㅋ

덧글

  • eizt 2012/07/06 11:57 # 삭제 답글

    검색하다가 들어왔습니다. HBase 안에서 한개의 로우키 안에서 여러 컬럼을 생성하는건 불가능한건가요?

    그러니까 로우키 1에 컬럼123123
    로우키 1에 컬럼 234234
    로우키 1에 컬럼 3234234234
    로우키 1에 컬럼 .......

    아 이거 은근히 골치아프네요 ..
  • Sigel 2012/07/06 20:25 #

    테이블을 생성할 때 column family를 여러개 만들어주시면 될거에요
    create 't1, 'c1', 'c2', 'c3'
    이런식으로..
    잠깐 보고 요즘 못 보고 있어서 정확한지 기억이 -ㅅ-;;;

    1개 column family 아래에 여러개 하위 column들을 만들 수 있고요..
댓글 입력 영역

Google AdSense (text/image)