난 아직까지 완전히 해결 못 한 문제가 있어서 대규모 분산 처리에 관심이 좀 있다. 작년에는 제한된 조건 (단일 노드, 순서 일관) 하에서 문제를 해결하긴 했는데, 아직 원하는 것을 얻으려면 풀어야 될 것이 많이 남았다.
요새 Hadoop이라든지 Cassandra 같은 NoSQL 시스템들이 인기인지라 뒤늦게 (..) Cassandra를 들여다봤는데.. 며칠 지나면 분명 까먹을 것이라 메모를 해둔다. 아직 뭐 복잡하게 써보거나 오래 들여다본게 아니니 내용이 틀리면 아무나 알려주시길.. 아무튼 내가 생각한 접근법이랑 비슷한 면이 많아서 좀 놀랐다.
Cassandra는 CouchDB와 유사한 접근법(crash-only design)을 사용한다. 간단히 얘기하자면 Append만 줄창 하고 중간의 내용을 수정하지 않으면 장애가 나도 복구가 매우 쉽다는 그런 얘기다. 일단 커밋 로그를 먼저 쓰고 (WAL), 메모리에 정렬된 상태로 유지하다가, 꽉 차면 디스크에 플러시한다. 이렇게 하면 쓰기는 매우 빨라진다. Append only는 쓰는 동안에 여러 읽기 스레드가 몰려도 잠금 하나 걸 필요도 없이 스케일링 할 수 있는 편안함이 있다.
쓰기를 상대적으로 빠르게 하는 대신에 읽기는 상당히 손해봐야 한다. 플러시 할 때마다 정렬된 파일이 하나씩 떨어져 나오는데, 전체를 정렬된 상태로 액세스하려면 미리 병합 과정을 거치거나 모든 파일을 읽어야 한다. 파일 여는게 원래 고달픈 일이라 파일이 많아지면 정말 급격하게 느려진다. 뭐 정렬 안 된 것들을 파일 하나로 붙여놓을 수는 있겠지만 근본적으로 이런 관계가 바뀌는 것은 아니고 흠흠.. 아무튼 지속적으로 많은 양의 쓰기가 들어오면 쓰기도 병합하느라 성능이 점점 내려가게 된다.
아래 링크에서 보여주는 성능 저하 그래프를 보자 -_- 뚝뚝 떨어진다..
분산시스템은 CAP theorem에 의해, 둘을 선택하면 하나는 포기해야 하는데 카산드라는 Consistency를 포기하는 방향(Eventual Consistency)을 택했다. 동일 시점에 여러 노드에서 값을 다르게 가지고 있는 난감한 상황이 발생하는데 대충 클라이언트에서 읽기 모드를 이것저것 선택할 수 있게 해서 해결(땜질?)해놨다. 여러 노드에게 물어봐서 과반수가 특정 값을 지지하면 그게 맞다고 생각하는 식으로.. (투표 수가 동일하면 타임스탬프가 큰 쪽으로..)
NoSQL 분류는 아래 블로그에서 만든 도표가 잘 되어있다.
검색할 때 키를 기준으로 해서 찾는 것은 빠르게 처리할 수 있다. 원래 정렬 안 된 상태라 플러시로 만들어진 블럭들을 전부 뒤지고 있어야 하지만 블룸필터를 앞에 깔아서 키 존재 여부를 확인하고 블럭을 스캔하도록 만들어져 있다. 물론 이런 배려는 범위 검색 들어오면 아무 소용없고 그냥 망한다. 대부분의 블럭이 병합되기 전에는 이렇게 된다.
참 씁씁하지만 Btree 없이 야매(?)로 하다보면 어쩔 수 없는 결과인 것이다. 처음부터 끝까지 정렬된 상태가 유지되지 않으면 원래 다 뒤지는 수 밖에 없다. 아무리 그래도 이건 좀 처참한 수준인 것 같다. (무려 한 손으로 셀 수 있네 -_-)
이렇게 만능 솔루션은 없다는 것을 다시 한 번 확인하고.. 스마트하게 문제를 해결하려면 도메인의 특성을 잘 익스플로잇 하는 수 밖에 없다는 뭐 그런 뻔한 결론 되시겠다.. 뭐 여러가지 생각해놓은 트릭은 있는데 언젠가 다 만들고 정리되면.. 과연 올해 안에는 어떻게든 될까..?
NoSQL 시끄러워도 수십년 짬 먹은 RDBMS에 비하면 별 대단한 기술 아니라고 생각한다..
뱀발.
이런걸로 incremental inverted index 만들면 오버헤드가 엄청날텐데 hbase 같은건 데이터 구조가 다른건가 nutch가 hbase로 갈아탔다는걸 보면.. 구글도 incremental 하게 만든건 그리 오래 되진 않았다고 하니 이것도 풀빌드라고 생각해야 되는건지 흠.. 아무튼 이해가 잘 안 된다..
최근 덧글