카산드라는 복제본을 동기화 상태로 유지하기 위해 여러 메커니즘을 사용한다. 데이터 복구 작업은 일반적으로 세 가지 범주로 나뉜다.


* Synchronous read repair : 데이터를 읽으면서 여러 개의 복제본을 비교할 때, 카산드라는 다른 노드에 체크섬(checksum)을 요청한다. 체크섬이 일치하지 않으면 전체 복제본에 요청을 보내 로컬 버전과 비교한다. 최신 타임 스탬프의 데이터가 반환되고 모든 복제된에 해당 데이터를 복제되도록 전달된다. 요청을 받을 때 오래된 데이터가 복구된다.(일명 read repair라 불린다)


* Asynchronous read repair : 카산드라는 읽기 작업 중에 나머지 복제본도 복구할 수 있게 한다. 카산드라의 각 테이블에는 read_repair_chance (기본 값은 0.1, 즉 10%) 설정이 있다. 설정은 데이터를 읽을 때 비교되지 않는 복제본을 얼마나 처리할지를 결정한다. 


consistency level이 one이면 비교할 대상이 없기 때문에 read repair가 발생되지 않는다. 그리고 quorum이면 모든 노드가 아니라 질의를 받은 노드만 복구된다.


* nodetool repair 직접 수행 : 전체적으로 복구를 수행한다. 최소한 테이블 스키마에 설정된 gc_grace_seconds(기본 10일)안에 한 번 실행해야 하지만, 운영 노하우가 필요하다. 


카산드라의 모든 수정(변경 내용)은 immutable인데 반해 delete는 클라이언트에 주지 말라는 마커(tombstone)만 있다. 따라서 compaction이 호출될 때에만 실제 삭제된다. 그리고 gc가 발생한다.





<운영 노하우>


데이터 consistency가 낮아 있는 cassandra에 node repair를 하다가 gc가 늘어나 서버가 hang이 되지 않도록 운영 작업을 고민했다.


cassandra에 read/write를 모두 quorum(java driver에서 consistency level의 기본값은 one이다)으로 바꿔 consistency를 높였고(이전에는 되어 있지 않았다) 자연스럽게 read operation 시 asynchronous read repair가 발생되도록 해놨다.


기본 consistency level를 결정한다. 


     QueryOptions queryOptions = new QueryOptions();

queryOptions.setFetchSize(QueryOptions.DEFAULT_FETCH_SIZE);

queryOptions.setConsistencyLevel(ConsistencyLevel.QUORUM);


private Cluster cluster;

..

cluster = Cluster.builder().addContactPoints(contactPoints).

withQueryOptions(queryOptions).

withPoolingOptions(poolingOptions).

withSocketOptions(socketOptions).build();





테이블의 성격에 따라 consistency level을 정할 수 있다. 이것은 테이블의 성격이 가장 우선시 된다. 테이블 성능과 cql 쿼리, compaction간의 고민이 필요하다. 


Statement statement = QueryBuilder.select().from(CASSANDRA_KEY_SPACE, CASSANDRA_TABLE_ACTIVITY_ACTION_COUNT)

.where(QueryBuilder.eq("profile_id", actorId)).and(QueryBuilder.eq("guid", id))

.setConsistencyLevel(ConsistencyLevel.ONE);





특정 테이블에서는 consisteny level을 quorum으로 했더니 timeout이 발생했다.


데이터가 크고 secondary index도 쓰고.. timeout이 발생하기 때문에 consisteny level을 one으로 수정했다(성능 이슈)


 com.datastax.driver.core.exceptions.NoHostAvailableException: All host(s) tried for query failed



테이블의 성격에 따라 다르게 node repair를 실행하는 것이 좋다.  



Posted by '김용환'
,