Tag Archives: nodetool

[NoSQL] Cassandra 다중 노드로 구성된 클러스터 구성하기

사용자 삽입 이미지지금까지 카산드라에 대해 글을 꽤나 쓴것 같네요. 이제부턴 몽고디비를 주제로 글을 써봐야 할것 같습니다. 아무튼 각설하고 이번에는 여러 노드로 구성된 클러스터를 구성하는 과정을 정리해 보도록 하겠습니다.

싱글 노드 구성하기

카산드라는 기본적으로 여러대의 노드가 하나의 클러스터를 이루어 동작하는것을 목적으로 만들어졌습니다. 그러나 테스트 또는 체험용의 목적을 위하여 싱글 노드를 구성할 수 있습니다. 지금부터 단일 노드 구성을 시작해 보겠습니다.

1. cassandra.yaml 파일에 다음과 같은 설정을 하여줍니다.
[code]cluster_name: ‘MyClusterName’
initial_token: 0[/code]
2. 위의 설정만으로도 단일 노드 운영에는 문제가 없습니다, 하지만 이후에 지속적으로 노드를 확장해 나갈 예정이라면 다음의 설정을 처음 노드 설정시에 정확하게 해주는 것을 추천합니다. endpoint_snitch설정의 경우에는 기본적으로 SimpleSnitch를 사용하여도 무방합니다만 다음의 두가지를 추천합니다.
[code]seeds: <노드의 IP>
listen_address: <노드의 IP>
rpc_address: 0.0.0.0
endpoint_snitch: RackInferringSnitch | PropertyFileSnitch[/code]

3. 카산드라를 시작합니다. 데비안 패키지 혹은 RPM으로 설치하였다면 다음의 명령을 이용하여 서비스로 구동할수도 있습니다.
[code]# service cassandra start[/code]
일반적인 tar파일로 다운받아 설치하였다면 다음과 같이 직접 실행을 해주시면 됩니다.
[code]$ cd $CASSANDRA_HOME
sh bin/cassandra[/code]

다중 노드 구성하기

정확하게 다중 노드로 구성된 클러스터를 만들기 위하여 다음의 정보를 명확히 정의해 두어야 합니다.

* 클러스터의 이름
* 클러스터를 몇개의 노드로 구성할 것인가
* 각 노드들의 아이피 주소
* 각각의 노드들의 토큰 (뒤에 설명하겠습니다)
* 어떤 노드를 시드 노드로 정의할 것인가? 시드리스트는 리플리케이션그룹당 1개정도면 됩니다.
* 노드들간의 데이터 통신 플랜 설정인 snitch 선택

예를 들어 같은 데이터센터에 6개의 노드로 구성된 클러스터가 있다고 가정해 보겠습니다. 그런데 2개의 랙을 사용하며 3개의 노드가 각각 설치 되어있습니다. 이경우 랙당 하나의 노드를 seed 노드로 정의해 주시면 됩니다.

node0 110.82.155.0 (seed1)
node1 110.82.155.1
node2 110.82.155.2
node3 110.82.156.3 (seed2)
node4 110.82.156.4
node5 110.82.156.5

위와 같이 노드가 정의되어있다고 가정할때 각각의 노드의 cassandra.yaml 설정은 다음과 같습니다. 여기서 사용하는 snitch 설정인 RackInferringSnitch는 노드의 IP주소를 참고하는 플랜입니다. IP주소의 두번째, 세번째 값을 이용하여 같은 그룹임을 자동 인식합니다.

node0
[code]cluster_name: ‘MyDemoCluster’
initial_token: 0
seed_provider:
       – seeds: “110.82.155.0,110.82.155.3”
listen_address: 110.82.155.0
rpc_address: 0.0.0.0
endpoint_snitch: RackInferringSnitch[/code]
node1
[code]cluster_name: ‘MyDemoCluster’
initial_token: 28356863910078205288614550619314017621
seed_provider:
       – seeds: “110.82.155.0,110.82.155.3”
listen_address: 110.82.155.1
rpc_address: 0.0.0.0
endpoint_snitch: RackInferringSnitch[/code]
node2
[code]cluster_name: ‘MyDemoCluster’
initial_token: 56713727820156410577229101238628035242
seed_provider:
       – seeds: “110.82.155.0,110.82.155.3”
listen_address: 110.82.155.2
rpc_address: 0.0.0.0
endpoint_snitch: RackInferringSnitch[/code]
node3
[code]cluster_name: ‘MyDemoCluster’
initial_token: 85070591730234615865843651857942052864
seed_provider:
       – seeds: “110.82.155.0,110.82.155.3”
listen_address: 110.82.155.3
rpc_address: 0.0.0.0
endpoint_snitch: RackInferringSnitch[/code]
node4
[code]cluster_name: ‘MyDemoCluster’
initial_token: 113427455640312821154458202477256070485
seed_provider:
       – seeds: “110.82.155.0,110.82.155.3”
listen_address: 110.82.155.4
rpc_address: 0.0.0.0
endpoint_snitch: RackInferringSnitch[/code]
node5
[code]cluster_name: ‘MyDemoCluster’
initial_token: 141784319550391026443072753096570088106
seed_provider:
       – seeds: “110.82.155.0,110.82.155.3”
listen_address: 110.82.155.5
rpc_address: 0.0.0.0
endpoint_snitch: RackInferringSnitch[/code]

토큰 계산하기

토큰이란 특정 노드에 부여되는 데이터의 범위를 정의하는 값입니다. 기본값인 RandomPartitioner를 사용할 경우 다음의 내용을 참고하시어 모든 노드가 공평한(?) 데이터 분배를 받도록 할 수 있습니다. 이것이 이루어지지 않을 경우 특정 노드에만 부하가 가중된다거나 하는 클러스터상에 안좋은 영향을 끼치는 문제를 일으키는 원인이 될 수 있습니다.

각각의 노드에 토큰을 부여할때는 cassandra.yaml 파일의 initial_token에 값을 정의하여 주시면 되고 노드가 처음 시작 될때 정의 되어있어야 합니다.

1. 토큰 생성을 위한 프로그램을 제작하여 봅시다.
[code]vi tokengentool[/code]
2. 다음의 파이썬(Python) 프로그램을 붙여넣기 합니다.
[code]#! /usr/bin/python
import sys
if (len(sys.argv) > 1):
    num=int(sys.argv[1])
else:
    num=int(raw_input(“How many nodes are in your cluster? “))
for i in range(0, num):
    print ‘token %d: %d’ % (i, (i*(2**127)/num))[/code]
3. 저장하고 만들어진 파일이 실행가능하도록 실행 권한을 부여합니다.
[code]chmod +x tokengentool[/code]
4. 스크립트를 수행합니다.(당연히 시스템에 파이썬이 깔려있어야 합니다.)
[code]./tokengentool[/code]
5. 질문이 뜨면 클러스터를 구성하기 위한 노드의 수를 입력해 줍니다.
[code]How many nodes are in your cluster? 6
token 0: 0
token 1: 28356863910078205288614550619314017621
token 2: 56713727820156410577229101238628035242
token 3: 85070591730234615865843651857942052864
token 4: 113427455640312821154458202477256070485
token 5: 141784319550391026443072753096570088106[/code]
6. 위의 값을 가지고 각각의 노드들의 cassandra.yaml파일의 initial_token값을 설정하도록 합니다.

이미 운영중인 노드의 밸런스 조정하기

1. 다음과 같이 밸런스가 무너진 시스템을 조정하도록 하겠습니다. (다음은 내용을 요약하였습니다.)
[code]# nodetool -h localhost ring
Address        Owns
192.168.0.104  36.65%
192.168.0.103  38.05%
192.168.0.105  9.59%
192.168.0.101  9.60%
192.168.0.102  6.11%[/code]
2. 위에서 사용한 tokengentool을 사용하여 5대의 노드의 토큰을 생성합니다.
[code]How many nodes are in your cluster? 5
token 0: 0
token 1: 34028236692093846346337460743176821145
token 2: 68056473384187692692674921486353642291
token 3: 102084710076281539039012382229530463436
token 4: 136112946768375385385349842972707284582[/code]
3. nodetool의 move명령을 사용하여 위의 노드로 이동을 시킵니다. 노드를 넘나드는 이동의 경우 매우 오래 걸립니다.
[code]// 192.168.0.102 노드의 예
# nodetool -h localhost move 34028236692093846346337460743176821145[/code]
4. 노드간의 밸런스 조정 완료 후(특정노드에만 부하가 가중되던 문제가 해결됨)
[code]# nodetool -h localhost ring
Address        Owns
192.168.0.101  20.00%
192.168.0.102  20.00%
192.168.0.103  20.00%
192.168.0.104  20.00%
192.168.0.105  20.00%[/code]

참고: http://www.datastax.com/docs/0.8/install/cluster_init#cluster-init

[NoSQL] Cassandra 새로운 노드 추가하기/기존의 노드 업그레이드 하기

사용자 삽입 이미지
카산드라에서의 새로운 노드를 추가하거나 기존의 노드를 업그레이드 하는 방법에 대해 간단히 기록을 해볼려고 합니다. 카산드라를 몇달 경험해 보니 도입 자체는 어렵지 않습니다만 운영이 매우 번거롭네요. 잘만들어진 GUI 툴조차 없고 노드의 수가 적을 경우 Consistency를 유지하는것 조차 어렵습니다. 작은 실수에 의해 데이터를 손실하기도 합니다. 백업이나 복구는 쉽지 않고 개발용 서버를 두고 따로 데이터를 완벽히 복제해 오는것도 쉬운일이 아닙니다. 하지만 이 모든것을 만족시킬만한 단 한가지 이유가 있다면 바로 퍼포먼스입니다. 읽기/쓰기가 기존의 RDB에서는 경험하기 힘든 모습을 보여줍니다. SQL류들을 사용하며 쿼리문을 하나짜기 위해 고민할필요도 없습니다. 하지만 그렇다고 마냥 사용하기 쉬운것은 아닌것 같긴 하지만요. 각설하고 정리를 시작해 보겠습니다.

새로운 노드 추가하기

서버의 시스템 준비

서버의 OS는 CentOS 혹은 RHEL이 적당하다고 개인적으로 생각합니다. OS의 경우에는 꼭 64비트 OS를 설치하시기 바랍니다. 메모리의 경우에는 많으면 많을수록 좋습니다. Swap은 사용하지 않습니다. 이미 Swap이 설정되어있는 머신이라면 /etc/rc.d/rc.local의 마지막에 다음의 명령을 추가하여 스왑을 꺼주시기 바랍니다.[code]swapoff -a[/code]
/etc/security/limits.conf 에 다음과 같은 내용을 추가하여 파일오픈 제한을 최대한 해제하여 줍니다.
[code]*                hard    nofile          262144
*                soft    nofile          262144[/code]
카산드라의 데이터 파일이 저장되는 공간(예:/var/lib/cassandra)의 파티션은 사실상 용량 무제한의 파일을 읽고 쓸 수 있는 xfs를 권장합니다. 적용이 힘들경우 ext4 또는 ext3로 하셔도 됩니다. 카산드라가 노드들간의 통신을 위해 사용하는 포트가 매우 동적입니다. 사실상 방화벽을 사용하시면 안됩니다. 레드햇 계열의 리눅스를 사용하실 경우 selinux를 꼭 끄셔야 합니다. 카산드라를 실행하기 위해서는 java가 필요합니다. 최신버전의 64비트용을 설치하시면 됩니다.

새로운 버전의 카산드라 다운받아 설치하기

현재 나와있는 최신버전은 0.8.4입니다. 다음과 같이 Download 페이지에서 알아낸 URL을 이용하여 원하는 바이너리를 다운받도록 합니다.
[code]wget http://mirror.apache-kr.org//cassandra/0.8.4/apache-cassandra-0.8.4-bin.tar.gz
tar -zxvf apache-cassandra-0.8.4-bin.tar.gz[/code]

cassandra-env.sh 설정하기

위의 파일에서 대표적으로 바꾸어야 하는 정보는 다음과 같습니다. [지난번글]에서 언급했듯이 MAX_HEAP_SIZE는 램의 1/2를 적용하면 되고 HEAP_NEWSIZE는 실제적인 코어 * 100M를 하시면 됩니다. java.rmi.server.hostname설정에서는 노드 자신의 아이피를 입력해 주셔야 원격지에서 모니터링 툴들이 접속할때에 발생할 문제를 사전에 차단할 수 있습니다.
[code]MAX_HEAP_SIZE=”4G”
HEAP_NEWSIZE=”400M”
JVM_OPTS=”$JVM_OPTS -Djava.rmi.server.hostname=192.168.0.10″[/code]

cassandra.yaml 설정하기

가장 핵심이 되는 설정 파일입니다. 기본적으로 사용하기 위해서 꼭 설정해야 하는 내용은 다음과 같습니다.
[code]cluster_name: ‘My Cluster'[/code]
모든 노드가 하나로 묶이게 되는 식별자 역할을 하는 클러스터 이름입니다. 하나의 클러스터는 하나의 cluster_name을 가져야만 합니다.
[code]auto_bootstrap: false[/code]
새로운 노드가 기존의 클러스터에 참여할때 주변 노드의 데이터를 빨아들여(?) 성공적으로 클러스터에 짐을 덜어주면서 합류하게 되는데요, 이 과정을 자동으로 수행할지 여부를 결정하는 설정입니다. nodetool을 이용하여 수동으로 합류할수도 있지만 위의 설정을 true로 바꿔서 카산드라를 구동하게 되면 다음에 나올 seed설정에 의거 기존의 노드들과 gossip이라는 프로토콜을 이용하여 가장 부하가 심한 노드의 다음에 알아서 추가가 됩니다. 일단 성공적으로 합류한 이후에는 노드의 재시작과 상관없이 이 설정을 다시 false로 바꿔두시기 바랍니다. 한번 클러스터에 정상적으로 참여를 했다면 이 설정을 필요가 없습니다. 또한 자신이 클러스터의 첫번째 노드라면 이 설정을 true로 하는것은 아무런 의미가 없습니다. false로 하시기 바랍니다.
[code]- seeds: “192.168.0.10, 192.168.0.11, 192.168.0.12″[/code]
위의 설정은 현재 클러스터의 토폴로지를 익히기 위해 소통해야할 노드를 입력합니다. 여러 노드가 구동중이라면 여러노드들을 모두 기입하시면 됩니다. 여기서 주의할 점은 추가되는 노드 자신의 IP가 저기에 들어가서는 안됩니다. 예외가 있다면 자신이 클러스터의 첫번째 노드일때는 자신의 아이피를 넣어주시면 됩니다. auto_bootstrap이 true인 상태에서 seeds설정에 자신의 아이피가 있을 경우 auto_bootstrap이 동작하지 않습니다.
[code]listen_address: 192.168.0.10[/code]
카산드라 노드들과의 통신을 위한 listen주소입니다. 이상하게도 여기에는 자기 자신의 아이피를 꼭 쓰셔야 합니다. 0.0.0.0같은걸 사용하시면 안됩니다.
[code]rpc_address: 0.0.0.0[/code]
이 설정은 클라이언트와 Thrift 프로토콜을 사용하여 통신을 할때 사용할 listen주소입니다. 여기서는 위와같은 네트워크 형태의 아이피를 사용하셔도 됩니다.

jna.jar 라이브러리 추가

카산드라의 lib폴더안에 jna.jar 파일을 추가해 줍니다. 이유는 모르겠지만 라이센스 문제로 카산드라가 포함하여 배포하지 못하는것 같습니다. jna가 없을 경우 카산드라는 정상구동 되지만 일명 OOM(Out Of Memory) 문제가 발생할 수 있습니다.
[code]wget http://java.net/projects/jna/sources/svn/content/trunk/jnalib/dist/jna.jar[/code]

기존의 노드 업그레이드 하기

기존의 노드를 새로운 버전의 카산드라로 업그레이드하기 위해서는 운영중인 서비스를 중단할 필요는 없습니다. 하지만 한대씩 노드를 업그레이드 한다고 할때 클러스터 운영을 위한 최소한의 replication factor를 넘는 숫자의 노드는 운영되고 있어야 합니다. (예: replication factor가 3일 경우 전체 노드가 4대 이상이면 무중단 업그레이드 가능)

운영중인 노드 중단하기

우선 다음과 같이 Thrift 서비스를 우선적으로 중단을 하여  봅니다. 서비스에 별다른 이상이 없는지 확인을 합니다. 이경우 replication factor와 read/write consistency 설정에 대해 이해가 좀 필요한데 다음에 관련 글을 적어보도록 하겠습니다. 다음의 명령으로 Thrift를 종료합니다.
[code]nodetool -h localhost disablethrift[/code]
서비스에 별다른 문제가 발견되지 않는다면(데이터 손실/롤백등) 다음의 명령으로 노드간의 통신을 종료합니다.
[code]nodetool -h localhost disablegossip[/code]
위의 명령을 실행하게 되면 다른 노드에서는 이 노드가 죽어있는것으로 판단하게 됩니다. 여기서 다른 노드중에 특별히 문제를 보이는 노드가 있는지 확인해 봅니다. 클러스터에 문제가 있을 경우 여기서 특정 노드의 부하가 폭주하거나 하는 문제가 발생합니다. 이제 다음의 명령으로 현재 메모리에 있는 모든 정보를 SSTable로 강제 쓰기를 하도록 합니다.
[code]nodetool -h localhost drain[/code]
그리고 카산드라 프로세스를 종료합니다. (그냥 ps명령으로 pid확인후에 kill로 죽이셔도 됩니다)
[code]pkill -f ‘java.*cassandra'[/code]

새로운 버전의 카산드라 설치 후 설정 옮기기

이 부분은 상단의 새로운 노드 추가하기 내용을 참고하시면 될것 같습니다.