Cassandra 특정 노드가 부하가 심해질때 긴급 처리 방법

사용자 삽입 이미지
카산드라 서버를 운영하다 보면 매우 가끔씩 특정 노드가 혼자서 미친듯이 폭주하더니 이내 뻗어버리는 현상이 발생합니다. 이경우 잘 대처하지 않고 방치해 두면 마치 전염병처럼 다른 노드까지 영향을 미치곤 합니다. 매우 간단하게 시도해 볼 수 있는 방법을 정리해 보겠습니다.

문제 파악

1. 특정 노드가 폭주를 하게 될 경우 서버의 로드가 10을 넘어 30혹은 더 높은 수치까지 치솟습니다.
2. /var/log/cassandra/system.log 파일에 다음과 같은 StatusLogger가 지속적으로 출력됩니다.
[code]INFO [ScheduledTasks:1] 2011-08-09 17:52:56,601 StatusLogger.java (line 88) system.NodeIdInfo
INFO [ScheduledTasks:1] 2011-08-09 17:52:56,601 StatusLogger.java (line 88) system.IndexInfo
INFO [ScheduledTasks:1] 2011-08-09 17:52:56,601 StatusLogger.java (line 88) system.LocationInfo
INFO [ScheduledTasks:1] 2011-08-09 17:52:56,601 StatusLogger.java (line 88) system.Migrations
INFO [ScheduledTasks:1] 2011-08-09 17:52:56,601 StatusLogger.java (line 88) system.HintsColumnFamily
INFO [ScheduledTasks:1] 2011-08-09 17:52:56,601 StatusLogger.java (line 88) system.Schema[/code]
3. 구동중인 어플리케이션에서 다음과 같은 접속불가를 나타내는 Thrift 에러가 발생합니다.
[code]TSocket: Could not connect to 123.123.123.123:9160 (Connection timed out [110])[/code]

해결 방법 – 데이터가 꼬여있을(Conflict) 경우

[code]nodetool -h localhost disablethrift
nodetool -h localhost disablegossip[/code]
위와 같은 명령을 사용하여 현재 운영중인 서비스에서 제외시킵니다. thrift를 비활성화 할 경우 어플리케이션에 응답하지 않으면 gossip을 끌 경우 노드들간의 통신을 하지 않으며 결과적으로 다른 노드들에서 보기엔 이 노드가 Down된것처럼 인식이 됩니다.
[code]nodetool -h localhost flush[/code]
위의 명령을 사용하여 현재 메모리에 올라가 있는 데이터를 강제로 SSTable에 쓰기를 합니다. 비정상적인 종료가 일어날 경우 데이터 손실로 이어질수도 있으므로 일단 데이터를 파일형태의 디비로 옮기는 작업을 합니다.
[code]nodetool -h localhost scrub[/code]
위의 명령은 SSTable을 새로 생성을 하는 명령입니다. 모든 데이터를 점검하여 새로운 SSTable을 생성합니다.  /var/log/cassandra/system.log에 데이터 관련된 Fatal에러가 발생할 경우에도 문제가 수정이 됩니다.
[code]nodetool -h localhost enablegossip[/code]
위의 명령을 실행하여 gossip을 구동합니다. 다시 클러스터에 참여를 하게 되며 다른 노드들과의 통신을 시작합니다. 이상태에서 top명령등을 사용하여 노드의 상태를 확인합니다. 정상으로 돌아왔다면 잠시 폭주하는듯 하다가 이내 안정화 됩니다.
[code]nodetool -h localhost enablethrift[/code]
모든것이 정상이라면 다시 서비스에 참여시켜야 겠죠?

해결방법 – 메모리가 부족한 상황

모든 해결 방법이 위의 경우와 동일합니다만 scrub을 사용하지 않고 compact를 사용합니다. 기본적으로 카산드라는 Compaction이라는 과정을 주기적으로 실행하며 SSTable을 병합 및 규모를 축소하는 작업을 지속적으로 하게 됩니다. 하지만 어쩐일인지 정상적으로 정리 정돈이 이루어지지 않아 서버의 부하로 이어지는 경우가 있습니다. 이 경우 튜닝이 필요하겠지만 급한대로 compact명령을 통해 강제로 Compaction을 할 수 있습니다.
[code]nodetool -h localhost disablethrift
nodetool -h localhost disablegossip
nodetool -h localhost flush
nodetool -h localhost compact
nodetool -h localhost enablegossip
nodetool -h localhost enablethrift[/code]

주의할점

별것은 아니지만 서비스 운영중에 왠만하면 피해야 하는 명령이 하나 있습니다.
[code]nodetool -h localhost repair[/code]
노드가 이상해졌다면 위와 같은 명령이 호감이 가게 됩니다. 무언가 지금의 상황을 고쳐줄것만 같은 명령입니다. 하지만 repair는 데이터를 교정해 주는 명령으로 주변 노드들과의 데이터 비교를 통하여 신뢰할 수 있는 값으로 교정을 해주는 명령입니다. 하지만 이 과정에서 메모리를 더 잡아먹게 되며 결과적으로 SSTable이 기하급수적으로 확장되는 과정을 거칩니다. 그냥 결론만 말하자면 서비스중에 이 명령을 사용하지 마십시오. 기본적으로 Cassandra는 기본 운영중에 끊임없이 데이터의 무결성을 검증하고 교정하게 됩니다. 경험상 repair는 정기점검때와 같이 서비스가 중단된 상태가 아닌 데이터가 계속해서 변화하는 상황에서 실행했을때 좋은 상황을 맞이한적이 없군요. 조심하시길 바랍니다.