2011년 7월 7일 목요일

Cassandra (6/12)

6. 카산드라 설정하기

이 챕터에서 카산드라를 어떻게 설정하는지 살펴본다. 우리는 keyspace, 복사본 셋업을 생성해보고 적당한 복사본 거치 전략을 살펴본다.
카산드라는 설정을 하지 않아도 잘 작동한다. 단지 다운로드하고 압축을 풀고 그리고 디폴트 설정으로 작동하도록 프로그램을 돌려 서버를 시작하면 된다.
우리는 클러스터 안의 노드의 행동에 영향을 미치는 면을 살펴본다. 그것은 퍼포먼스 그리고 복사, 파티셔닝, 고발과 같은 메타 동작이다. 퍼포먼스 튜닝은 11장에서 별개의 주제로 자세히 살펴본다.

6.1. Keyspaces

키스페이스는 XML 설정화일에 정적으로 설정이 되기는 하였으나 0.7 버전에 오면서 API를 사용하여 키스페이스와 컬럼군을 생성할 수 있다.
카산드라 0.6과 그 이전 버전에서 당신의 클러스터와 컬럼군을 위한 설정은 storage-conf.xml이라는 파일에 저장이 되었다. 그리고 XML에서 YAML로 변환되었다. 그래서 storage-conf.xml과 Cassandra.yaml 로의 참조를 볼 수 있다. 그러나 버전 0.7 은 다이나믹 로딩이 되면서 키스페이스와 컬럼군 정의의 모든 생성과 수정은 Thrift API을 통하거나 command line interface (CLI)를 통하게 되었다.
버전 0.7 카산드라에서부터 당신은 당신의 스키마에 변경을 하기 위해서 API를 사용할 수 있다. 이것은 당신이 SQL 에서 CREATE TABLE, ALTER TABLE 과 같은 Data Definition Language (DDL) 을 쓰던것과 매우 유사하다.
일단 당신의 스키마가 당신 시스템의 키스페이스에 로드되면 스키마에 대한 모든 변경은 Thrift 인터페이스를 통해야 한다. 이 메서드들은 모두 system에 의해 앞에 이름이 붙는다. 이것은 당신에게 이것들이 매우 영향력이 강한 스키마 변경 동작으로서 시스템 키스페이스를 수정한다는 것을 상기시킨다.
- System_add_keyspace
키스페이스를 생성한다.
- System_rename_keyspace
키스페이스의 이름을 변경한다. 이 메서드는 모두 끝날때까지 블록한다는 것을 주의한다.
- System_drop_keyspace
모든 키스페이스를 지운다.
- System_add_column_family
컬럼군을 생성한다.
- System_drop_column_family
컬럼군을 지운다.
- System_rename_column_family
컬럼군의 이름을 바꾼다. 이 메서드는 완료될 때까지 블록된다는 것을 주의한다.
예를 들어 0.7 버전의 CLI를 사용하여 새로운 키스페이스를 만들 때 당신은 아래와 같은 command-line 클라이언트를 런치할 수 있다.
[default@unknown] connect 127.0.0.1/9160
Connected to: "Test Cluster" on 127.0.0.1/9160
[default@unknown] create keyspace Test1 with replication_factor=0
610d06ed-a8d8-11df-93db-e700f669bcfc
[default@unknown] describe keyspace Test1
Keyspace: Test1

default@unknown 이라는 것은 MySQL과 비슷하다. 이것은 username을 인증하고 현재 사용하는 키스페이스 이름이 프롬프트 처럼 행동하게 한다. 그래서 우리는 키스페이스 커맨드를 사용하여 다른 키스페이스로 스윗치 할 수 있다.
use [ 'password']
이제 CLI에서 다른 새 키스페이스로 스윗치했으니 컬럼군을 추가할 수 있다.
[default@Test1] create column family MyCF
4105a82f-ad51-11df-93db-e700f669bcfc
당신은 with flag를 이용해 키스페이스와 컬럼군을 생성할 때나 and flag를 사용해 더 많은 셋팅을 만들 때 추가 적인 설정을 지정할 수 있다.
[default@MyKeyspace] create keyspace NewKs with replication_factor=1
당신이 필요에따라 쓸 수 있는 다른 키스페이스 관련 CLI 커맨드도 있다.
drop keyspace
drop column family
rename keyspace
rename column family
API를 사용해 이것을 할 수 도 있는데 아래와 같다.
package com.cassandraguide.config;
import java.util.ArrayList;
import java.util.List;
import org.apache.cassandra.thrift.Cassandra;
import org.apache.cassandra.thrift.CfDef;
import org.apache.cassandra.thrift.KsDef;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
public class ConfigAPI {
private static final String HOST = "localhost";
private static final int PORT = 9160;
/**
* Creates a new keyspace and CF.
*/
public static void main(String... args) throws Exception {
String keyspaceName = "DynamicKeyspace";
System.out.println("Creating new keyspace: "+ keyspaceName);
//Create Keyspace
KsDef k = new KsDef();
k.setName(keyspaceName);
k.setReplication_factor(1);
k.setStrategy_class("org.apache.cassandra.locator.RackUnawareStrategy");
List cfDefs = new ArrayList();
k.setCf_defs(cfDefs);
//Connect to Server
TTransport tr = new TSocket(HOST, PORT);
TFramedTransport tf = new TFramedTransport(tr);
TProtocol proto = new TBinaryProtocol(tf);
Cassandra.Client client = new Cassandra.Client(proto);
tr.open();
//Add the new keyspace
client.system_add_keyspace(k);
Keyspaces | 101
System.out.println("Added keyspace: "+ keyspaceName);
}
}
당신이 새로운 키스페이스를 생성하기 위해 해야 할 것은 이름을 정하고, 복사 거치 전략, 그리고 복사본 팩터, 그리고 한정된 컬럼 군을 만들어 그 키스페이스를 정한다. 이제 당신은 새 MyCF 컬럼군에 값을 입력할 준비가 되었다.

6.2. 컬럼 군 만들기

컬럼군을 만들기 위해서는 CLI나 API를 사용해야 한다. 여기 컬럼군을 만들 때 사용가능한 옵션들이 있다.
- Column_type
Super 이거나 Standard
- Clock_type
오직 가능한 값은 Timestamp
- comparator
가능한 옵션은 AsciiType, BytesType, LexicalUUIDType, LongType, TimeUUIDType, UTF8Type 이다.
- Subcomparator
column type이 super일 때 subcolumn에 사용되는 비교자의 이름이다. 가능한 옵션은 비교자(comparator)와 같다.
- Reconciler
컬럼 버전이 충돌하는 것을 해결해주는 클래스의 이름이다. 오직 가능한 값은 Timestamp이다.
- Comment
스트링으로 표시되는 사람이 읽기 가능한 커멘트이다.
- Row_cached
캐쉬하기 위한 행의 수이다.
- Preload_row_cache
행 캐쉬를 자동으로 로드하기 위해 이 값을 true로 셋팅한다.
- Key_cache_size
캐쉬로 끌어들여오기 위한 키의 개수
- Read_repair_chance
가능한 값은 0.0과 1.0 사이의 값이다
[default@Keyspace1] create column family MyRadCF with
column_type='Standard' and comparator='UTF8Type' and rows_cached=40000
3ae948aa-ae14-11df-a254-e700f669bcfc

6.3. 0.6에서 0.7로의 전환

conf디렉토리의 Cassandra.yaml 파일은 storage-conf.xml 파일의 대체로 보인다. 이것은 0.6 이전 버전의 설정화일이다. 그러나 이 YAML 파일은 XML에서 YAML로 자신들의 설정파일을 업그레이드 하려는 사용자들을 위해 있다. 이전에 보여진 것처럼 대신Thrift API를 system_ prefix가 붙은 것들을 호출해서 사용할 수도 있다.
만약 당신이 0.6 버전을 사용하여 storage-conf.xml 이 있다면, 이것을 bin/config-converter를 써서 YAML로 변환할 필요가 있다. 이것은 storage-conf.xml에서 Cassandra.yaml 을 만들어 낸다. Org.apache.cassandra.service.StorageServiceMBean 에는 loadSchemaFromYAML 이라는 것이 있어서 JMX를 통해 노출되는 동작이다. 이것은 당신의 seed 노드에서 Cassandra.yaml 에서 당신의 스키마 변경을 로드하도록 카산드라에게 시킬수 있다. 당신 클러스터의 새로운 노드는 시작하자마자 스키마 업데이트를 가져올 것이다. Seed 노드도 다르지는 않다. 당신은 이 메서드를 어느 한 노드에 실행할 수 있고 모든 노드는 스키마 변경을 받고 그것에 대해서 알려줄 것이다. 이것은 카산드라 시스템의 키스페이스의 정의를 저장하는 동작이다. 당신은 이것을 실행한 후에 YAML을 변경하기 원치 않게 된다. 이후의 변경에 대해서는 당신은 API나 CLI를 사용할 필요가 있다. 이 동작은 변환이 완료된 후에는 필요없게 된다.
디폴트를 사용하는 것은 간단한 테스팅이 되지만 복사 거치 전략, 복사본 factor, end point snitch 등을 설정하는 것을 살펴본다. 이 설정들은 키스페이스 안에서 설정가능하다. 그래서 다른 키스페이스는 다른 설정을 각각 가질 수 있다.

6.4. 복사본

복사본 거치 전략은 당신이 클러스터에 노드를 추가할수록 더욱 중요해지고 있다. 카산드라에서 노드라는 용어는 가장 일반적인 케이스를 지칭한다. 그것은 카산드라 소프트웨어를 구동시키는 서버를 말한다. 그리고 한 개나 그 이상의 카산드라 서버들의 링에 참여하여 움직인다.
모든 카산드라 노드는 무언가의 복사본이다. 주어진 키의 범위에서 그 범위내의 복사본이 아닌 카산드라 노드가 있을 수도 있다. 만약 replication factor가 1로 셋팅되어 있으면 한 싱글노드로만 쓰여지게 되어있다. 만약 그 노드가 다운되면 그 노드에 저장되어 있는 값은 접근할 수 없게 된다. Replication factor가 2로 셋팅되어 있으면 당신 클러스터의 두 개 노드가 그 값을 가지고 각각 서로의 복사본이 되게 된다. 그래서 당신의 replication factor가 N으로 설정되어 있으면 각 노드는 N 범위의 복사본처럼 행동하게 되고 N이 1로 셋팅되어 있어도 마찬가지 이다.
카산드라 클러스터, 즉 호스트들의 모임은 여기서 보듯이 ring 이라고 보통 불린다. 링의 각 노드들은 고유한 각 한 개의 토큰이 할당된다. 각 노드는 이전 노드의 토큰으로부터 또다시 토큰을 갖고 값의 범위 만큼 주도권을 주장한다. Org.apache.cassandra.dht.Range 클래스에 이것들이 담겨있다. 정확히 한 토큰이 어떻게 표현되는지는 당신이 사용하는 partitioner에 달려있다. (partitioner에 대한 정보는 이장의 후에나오는 partitioner 를 참조한다.)
복사본을 만들 때 첫 복사본은 그 토큰의 key 범위를 주장하는 노드에게 거치된다. 모든 남아있는 복사본은 설정가능한 복사본 전략에 따라서 분산된다. 우리는 이것에 대해서 지금 살펴보겠다.

6.5. 복사본 거치 전략

가장 간단한 용어로서 설정 파일에 대한 복사본 거치 전략을 만족하기 위해서는 당신은 단지 org.apache.cassandra.locator.AbstractReplicationStrategy 를 확장하는 자바 클래스 이름을 제공하기만 하면 된다. 이 설정의 목적은 node picker가 작동하는 방식을 셋팅하기 위한 것이다.
인터페이스는 구현을 해야하는 11개의 public 메서드를 제공한다. 만약 당신의 전략이 추상적인 부모가 제공할 수 있는 메서드 구현을 사용할 수 있다면 당신은 당신이 원하는 메서드만을 오버라이드 할 수 있다. 당연히 당신은 이것을 당신이 직접 구현해야 하지는 않는다. 카산드라는 이 인터페이스의 세가지 구현을 제공한다. Rack-Aware 전략, Rack-Unaware 전략, Data Center Shard 전략.
올바른 복사 전략을 고르는 것은 전략이 어느 노드가 어느 키 범위에 대하여 책임이 있는지 결정하기 때문에 중요하다. 여기서 의미하는 바는 당신은 어느 쓰기 동작이 어느 노드에 받아져야 하는지 결정하는 것이며 각 다른 시나리오에 대우 큰 영향을 가지고 있다. 당신이 만약 당신의 클러스터를 모든 쓰기가 두 개의 데이터 센터에 가도록 한다면 퍼포먼스가 떨어질 것이다. 다양한 전략은 더 큰 유연성을 주어 카산드라를 당신의 네트워크 토팔러지나 필요에 따라 튜닝할 수 있게 해준다.
첫번째 복사본은 항상 토큰이 해당하는 범위를 주장하는 노드이지만 복사본의 나머지는 당신이 사용하는 복사본 거치 전략에 따라 위치될 것이다.

6.6. 간단한 전략

간단한 전략은 Rack-Unware 전략의 새로운 이름이다.
설정 파일에서 디폴트로 쓰이는 전략은 org.apache.cassandra.locator.RackUnawareStrategy 이다. 이 전략은 단지 추상 부모 구현에서calculateNaturalEndpoints 메서드를 오버라이드한다. 이 전략은 데이터 센터에서 자신의 위치를 모르는 방식으로 한 데이터 센터의 복사를 위치한다. 이것은 구현이 이론적으로 빠르다는 것을 의미하고 주어진 키를 가진 다음 노드가 다른 랙에 위치한다는 것을 의미한다. 이것은 아래 그림에 보여졌다.

그림6-1. 간단한 전략은 토팔러지에 상관없이 한 데이터센터에 복사본을 둔다.
여기서 링의 다음 N 노드는 복사본을 갖도록 선택되어 지고 전략은 데이터 센터에 대한 것이 없다는 것을 본다. 두번째 데이터 센터는 다이어그램에서 전략은 그것을 모른다는 것을 강조한다.

6.7. 오래된 네트워크 토팔러지 전략

카산드라가 제공하는 두번째 복사본 거치 전략은 org.apache.cassandra.locator.RackAwareStrategy 로서 현재 Old Network Topology Strategy라고 불린다. 이것은 같은 데이터 센터에서 다른 랙에 데이터를 분산시키기 위해서 쓰였던 것이다. RackUnawareStrategy처럼 calculateNaturalEndpoints 의 추상 부모 구현을 단지 오버라이드 하는 것이다. 이 클래스는 원래의 이름이 말하듯이 정말 데이터 센터 랙의 거치를 알고있다.
당신이 두개의 데이터 센터를 가지고 있다고 해보자. DC1 과 DC2이다. 둘 다 카산드라 서버이다. 이 전략은 DC1에 복사본을 두고 각각 다른 가용한 랙에 둔다. 이것은 마찬가지로 다른 랙 DC2 에는 다른 복사본을 둔다. Rack-Aware 전략은 특히 당신이 같은 카산드라 클러스터에 노드들을 가지고 두 개의 데이터 센터가 있으며 복사본 factor 3을 쓰는 것이다. 이 전략은 그림 6-2에 표현되어 있다.
이 전략은 당신이 대체할 데이터 센터의 세번째 노드가 접근 될 때 추가적인 latency 의 잠재적 가격에도 더 높게 보장하고 싶을 때 사용한다. 당신이 단지 한 데이터 센터에서 카산드라를 운영한다면 Rack-Aware 전략을 사용하는 것은 의미가 없다. 카산드라는 다른 데이터 센터에서 운영하는데 최적화 되어 있다. 그러나 그 높은 가용성을 사용하는 것도 당신에게는 중요한 고려사항일 것이다. 만약 당신의 카산드라 클러스터가 여러 개의 데이터 센터에 걸쳐있다면 이 전략을 사용하는 것을 고려해보라.
그림6-2. Old Network Topology Strategy 가 두번째 복사본을 다른 데이터 센터에 두고 다른 것은 같은 데이터 센터의 다른 랙에 둔다.

당신이 Rack-Aware 전략을 사용한다면 Rack-Aware Snitch도 사용해야 하는데 Snitch는 뒤에 설명되어 있다.


6.8. 네트워크 토팔러지 전략

이 전략은 카산드라의 0.7 버전부터 포함되었다. RackAwareStrategy보다 데이터 센터에서 복사본들이 어떻게 거치될지 더 공정하게 보여주게 된다. 이것을 사용하기 위해서는 각 데이터 센터에서 복사본 전략을 어떻게 할지 정해주는 파라미터를 넣으면 된다. 이 파일은 org.apache.cassandra.locator.DataCenterShardStrategy 클래스에 의해서 읽혀지고 수행된다. 그래서 구현은 좀 유동적이다. 데이터 센터의 조각 전략은 그림 6-3에서 볼 수 있다.
이 전략은 datacenter.properties라는 파일을 사용했었다. 그러나 0.7버전에서 이 메타데이터는 키스페이스와 설정 옵션이라고 할 전략에 직접 붙었다.

그림6-3. 네트워크 토팔러지 전략은 복사본을 다른 데이터센터에 둔다. 그리고 나머지는 첫번째 데이터 센터의 다른 랙에 지정했듯이 둔다.


6.9. Replication Factor

Replication Factor는 카산드라 클러스터에서 얼마나 많은 각 데이터의 복사본이 저장되고 분산되는지 지정한다. Replication_factor 라는 셋팅에서 지정된다.
아마 클러스터에서 더 많은 노드를 가지고 있을수록 replication factor를 늘리고 싶은 것은 직관적일 것이다. 그러나 무조건 이 법칙을 따르지는 않는다. 그 대신 당신이 요구하는 서비스 레벨을 맞추기 위해서 replication factor를 증가시킬 것이다.
Replication factor를 1로 했을 때 당신의 데이터는 클러스터 안의 한 노드에서만 존재할 것이다. 그 노드가 이상이 있다면 데이터가 가용하지 않게 되는것이다. 이것은 카산드라가 노드들간에 조정을 하기 위해 더 많은 일을 한다는 것을 의미한다. 만약 주어진 키에 대해 모든 데이터가 노드 B에 있다면 모든 클라이언트는 그 키에 대해서 요청하고 노드 A는 재전송 되기를 필요로 할 것이다.
당신은 이 값을 당신 클러스터안 노드개수보다 크게 잡아서는 안된다. 이것은 아무 의미가 없기 때문이다. 그러나 당신은 이 셋팅으로 카산드라는 튜닝하기를 원치않는다. 카산드라는 읽는 복사본 카운트와 쓰는 복사본 카운트가 replication factor보다 커야 높은 일관성을 보여준다.
그래서 당신이 클러스터 안에 10개의 노드를 가지고 있다면 당신은 맥시멈으로 10을 replication factor로 정해줄 수 있다. 하지만 그렇게 하기를 원치 않을 수 있다. 그것이 카산드라가 그 가용성을 방해하지 못하도록 하기 때문인데 왜냐하면 한 개의 노드가 다운되면 높은 일관성을 갖지 못하기 때문이다. 그 대신 replication factor를 적당한 값으로 정해준후에 일관성 레벨을 높였다 낮추었다 하며 튜닝을 한다. 일관성 레벨은 당신이 replication factor에 의해서 정의된 노드의 개수보다 더 쓰게 하지는 않을 것이다. 여기서 적당한 숫자란 상당히 낮을 것이다. 1이란 가장 낮은 숫자이다. 그러나 ANY는 1과 비슷하거나 오히려 일관성이 없다. 이것은 당신이 쓰고 긴시간 후에 쓰여진 값을 보지 못하기 때문이다. 만약 클러스터의 어느 노드가 살아있다면 ANY는 성공할 것이다.

6.10. Replication Factor 증가하기

Replication factor는 서버가 실행중에 바뀌기를 원하지는 않고 시작하기 전에 정해지기 바란다. 그러나 당신의 애플리케이션이 커지고 노드를 증가할 필요가 생기면 replication factor를 증가 시켜야 한다. 이것을 할 때 따라야 할 간단한 가이드라인이 있다. 첫째로 replication factor 값을 증가시킨 후에는 노드를 재시작 시켜주어야 한다. 카산드라는 이것을 재시작한 후에 데이터를 재분배하는 등 고치는 동작을 한다. 이 고치는 과정동안에 어떤 클라이언트들은 데이터를 아직 가지지 않은 복사본에 연결이 되었다면 데이터가 존재하지 않는다는 통지를 받는다.
Replication factor 를 1에서 2로 증가시키는 더 빠른 방법은 노드 툴을 사용하는 것이다. 첫째로 원래의 노드에 빨아들이는 동작을 하여 모든 데이터가 SSTable에 배출되었는지 확실히 한다. 그리고 더 이상의 쓰기 동작을 받아들이지 않게 노드를 멈춘다. 다음으로 키스페이스로부터 데이터 파일을 복사한다. 카산드라 내부 키스페이스의 값들을 복사하지는 않게한다. 그 데이터 파일들을 새 노드에 붙인다. Replication factor가 2가 되도록 양쪽 노드의 설정을 바꾼다. Autobootstrap 이 양쪽 노드에서 false로 설정되게 한다. 양쪽 노드를 재시작한 후에 노드 툴을 실행한다. 이 과정들은 클라이언트가 잠재적인 그른 빈 읽기를 하지 않도록 보장한다.
이것을 보여주기 위해 IP주소가 1.5, 1.7 그리고 1.8로 끝나는 세 개의 노드를 가지고 replication factor는 1로 설정했다. 노드 1.5에 연결하고 이전에 존재하지 않던 컬럼에 쓰기를 한다.
cassandra> connect 192.168.1.5/9160
Connected to: "TDG Cluster" on 192.168.1.5/9160
cassandra> set Keyspace1.Standard2['mykey']['rf']='1'
Value inserted.
이제 노드 1.5를 닫고 1.7에 연결한후 여기 설정한 값을 읽어오도록 한다.
cassandra> connect 192.168.1.7/9160
Connected to: "TDG Cluster" on 192.168.1.7/9160
cassandra> get Keyspace1.Standard2['mykey']['rf']
Exception null
나는 replication factor가 1이어서 1.5 노드에만 값이 씌어졌고 그 노드를 잃어버렸을 때 클러스터의 다른 노드들은 값을 가지지 못했다. 아무 클라이언트도 1.5가 다시 온라인이 될 때까지 rf컬럼에서 값을 읽어오지 못했다.
그러나 replication factor를 업데이트하는 영향을 알아보자. 우리는 노드 1.5와 1.7에서 1에서 2로 바꾸고 재시작하였다. 우리는 노드 1.7에서 rf 컬럼에 새 값을 넣어보자.
cassandra> connect 192.168.1.7/9160
Connected to: "TDG Cluster" on 192.168.1.7/9160
cassandra> get Keyspace1.Standard2['mykey']['rf']
Exception null
cassandra> set Keyspace1.Standard2['mykey']['rf']='2'
Value inserted.
Exception null 응답이 예제 중에 나오는 것은 값이 1.7 노드에 이전에는 존재하지 않았다는 것을 알려준다. 1.7 노드를 닫고 1.5에 연결하여 값을 보자. 왜냐하면 우리의 replication factor때문에 1.7에 값을 쓰고 1.5로 복사되었다.
cassandra> connect 192.168.1.5/9160
Connected to: "TDG Cluster" on 192.168.1.5/9160
cassandra> get Keyspace1.Standard2['mykey']['rf']
=> (column=rf, value=2, timestamp=1279491483449000)
일반적인 가이드라인으로써 당신은 쓰기 능력은 노드의 숫자를 replication factor로 나눈 값이라고 예상할 수 있다. 10개 노드를 가진 클러스터에서 일반적으로 10000 의 초당 쓰기는 replication factor 1이다. 당신이 replication factor를 2로 증가하면 초당 5000 쓰기를 예상할 수 있다.

6.11. Partitioners

Partinioner의 목적은 행 키가 어떻게 정렬될지 정하게 하는 것이고 이것은 데이터가 어떻게 노드들 간에 분산이 되는지에 큰 영향이 있다. 그것은 또한 행의 범위에 대해서 쿼리하는 옵션에 대해서도 영향이 있다. 거기에는 몇 가지 다른 partinioner가 있고 우리가 여기서 살펴본다.
당신은 설정파일의 Partitioner 요소의 값을 업데이트 하거나 API를 통해서 Partitioner를 설정할 수 있다. Org.apache.cassandra.dht.IPartitioner 인터페이스를 구현하는 클래스의 이름으로 값을 처리한다. 카산드라는 세 가지를 제공한다. Random partitioner 는 디폴트이고, order-preserving partitioner와 collating order-preserving partitioner이다. 카산드라의 플러거블한 디자인 때문에 당신의 고유의 partitioner를 org.apache.cassandra.dht.IPartitioner 클래스를 구현해서 만들수도 있고 그것을 카산드라 클래스패스에 두어야 한다.

6.12. Random Partitioner

랜덤 partitioner는 org.apache.cassandra.dht.RandomPartitioner에 의해 구현되고 카산드라의 디폴트이다. BigIntegerToken을 사용하고 MD5 해쉬가 적용되며 노드 링에서 어디에 키를 두어야 할 지 결정한다. 이것은 당신의 키를 클러스터 전반에 고르게 뿌리는 장점이 있고 분산이 랜덤이기 때문에 그렇다. 이것은 효율적이지 않은 범위 쿼리라는 단점이 있는데 특정한 범위에서 키는 다양한 위치에 링안에서 위치될 수 있기 때문이다. 키 범위 쿼리는 근본적으로 랜덤 순서로 데이터를 반환한다.

6.13. Order-Preserving Partitioner

Order preserving partitioner 는 org.apache.cassandra.dht.OrderPreservingPartitioner에 의해 구현되고 IPartitioner을 구현한다. 이런 타입의 partitioner를 사용하면 토큰은 키에 기반한 UTF-8 스트링이다. 행은 그래서 키 순서에 따라 저장되고 정렬 순서와 함께 물리적 데이터의 구조로 정렬된다.
Order-preserving partitioning(OPP)를 사용하기 위해 당신의 컬럼군을 설정하는 것은 범위 분할을 수행하게 한다.
OPP가 random partitioning보다 범위 쿼리에 더 효과적이지는 않다는 것을 알아둘 필요가 있다. 단지 순서를 정할 뿐이다. 그것은 현실 세계에서 데이터는 일반적으로 고르게만 쓰여지지 않기 때문에 잠재적으로 균형이 매우 균형이 안잡힌 링을 만들수 있다는 단점이 있다. 예를 들면 스크래블 게임에서 글자에 할당된 값을 고려해보자. Q와 Z는 잘 이용되지 않는다. 그래서 높은 값을 가지고 있다. OPP로는 어떤 노드에서 많은 데이터 그리고 다른 노드에는 적은 데이터를 가지고 끝날 수 있다. 많은 데이터가 저장된 노드에는 링이 균형이 안잡히게 하고 hot spot으로 종종 불린다. 순서정렬 면 때문에 사용자는 OPP에 사로잡히게 된다. 그러나 OPP사용은 당신의 동작 팀이 노드툴의 loadbalance와 move 동작을 써서 노드를 주기적으로 수동적 재균등화를 해주어야 한다는 것을 의미한다.
만약 당신이 당신의 클라이언트에서 범위 쿼리를 수행하기 원한다면 order-preserving partitioner를 사용해야 하거나 order-preserving partitioner 를 순서대로 모아야 한다.

6.14. Order-Preserving Partitioner를 모으기

이 partitioner 순서 키는 United States English locale (EN_US) 을 따른다. OPP처럼 키가 UTF-8인 것을 요구한다. 이름으로는 OPP를 확장하는 것처럼 보이지만 그렇지 않다. 그 대신 이 클래스는 AbstractByteOrderedPartitioner 를 확장한다. 이 partitioner는 사용성이 제한되어 잘 사용되지 않는다.

6.15. Byte-Ordered Partitioner

0.7 버전에서 새롭게 ByteOrderedPartitioner가 추가되었다. 이것은 order-preserving partitiner 이고 데이터를 로우 byte로 다룬다. 그대신 order-preserving partitioner와 collating order-preserving partitioner가 하는 것처럼 그것을 스트링으로 변환한다. 당신이 당신의 키가 스트링이 되고 검사하지 않는 order-preserving partitioner를 필요로 한다면 BOP 가 퍼포먼스 향상을 위해서 추천하고 싶다.

6.16. Snitches

Snitch의 일은 관련 호스트의 근접성을 단순히 결정하는 것이다. Snitch는 당신 네트워크 토팔러지의 어떤 정보들을 모아 카산드라가 효과적으로 요청을 전달할 수 있게 한다. Snitch는 어떤 노드가 다른 노드와 어떻게 위치상 관계가 있는지 알아낸다. 데이터 센터를 추론하는 것은 replication strategy의 할일 이다.

6.17. 간단한 Snitch

디폴트로 카산드라는 org.apache.cassandra.locator.EndPointSnitch를 사용한다. 이것은 단지 각 노드의 IP주소의 다른 octet을 비교함으로써 작동한다. 만약 두 개의 호스트가 IP주소의 두번째 octet에서 같은 값을 가진다면 같은 데이터 센터에 있는 것으로 된다. 만약 두개의 호스트가 IP주소의 세번째 octet에서 같은 값을 가진다면 그들은 같은 랙에 있는것으로 된다. “Determined to be” 는 카산드라가 당신의 서버가 다른 VLAN 이나 subnet에 위치해 있다는 가정에 기반한다.
당신은 설정 파일에서 요소의 값을 업데이트 함으로써 endpoint snitch 구현을 사용할 지 설정하게 된다. 다른 선택은 PropertyFileSnitch 이다.

6.18. PropertyFileSnitch

Org.apache.cassandra.locator.PropertyFileSnitch 는 contrib. 안에 있었다 그러나 0.7에 오면서 메인 코드 베이스로 옮겨졌다. 이 snitch는 당신이 cassandra-rack.properties라고 불리는 파일에 표준 키/값 프로퍼티의 위치를 명시하여 Rack-Aware Strategy 를 사용하는데 콘트롤 할 수 있게 해준다.
이 snitch는 Digg에 의해서 공헌이 있었다. 그것은 카산드라를 사용하고 정기적으로 그 개발에 공헌해왔다. 이 snitch는 카산드라가 두개의 IP가 같은 데이터센터 혹은 같은 랙에 있는지 확실하게 알게 해준다. 왜냐하면 당신이 거기에 있다고 말해주기 때문이다. 이것은 아마도 당신이 서버를 많이 옮긴다면 가장 유용할 것이다. 동작이 그렇듯이 당신이 상속된 IP scheme을 가지고 있다면 그렇다.
Cassandra-rack.properties의 디폴트 설정은 아래와 같다.
# Cassandra Node IP=Data Center:Rack
10.0.0.10=DC1:RAC1
10.0.0.11=DC1:RAC1
10.0.0.12=DC1:RAC2
10.20.114.10=DC2:RAC1
10.20.114.11=DC2:RAC1
10.20.114.15=DC2:RAC2
# default for unknown nodes
default=DC1:r1

여기서 두 개의 랙에 두개의 데이터 센터가 있는 것을 볼 수 있다. 카산드라는 좋은 퍼포먼스로 동등한 배분을 결정할 수 있다.
어떤 랙이 그 IP의 노드를 가지고 있고 어떤 데이터 센터에 있는지 명시하기 위해 이 파일안의 클러스터안 각 노드의 값을 기록하여 업데이트 하라. 만약 당신이 노드를 추가하고 제거하는 것을 자주한다면 이것은 관리하기 어렵게 느껴질수 있지만 이것은 하나의 차선책이라는 것을 기억하라. 이것은 당신에게 좀더 많은 컨트롤과 좋은 실행시의 퍼포먼스를 위해 작은 유연성과 관리의 용이함은 없앤것이다. 대신에 당신은 그것들이 어디에 있는지 말해준다.

6.19. 클러스터 생성

당신은 카산드라를 한 개의 기기에서 실행할 수도 있다. 이것은 읽기와 쓰기 등 어떻게 하는지 배우기 위해서는 좋다. 그러나 카산드라는 여러 개의 기기의 클러스터에서 동작하도록 만들어졌다. 이 섹션에서 링에서 여러 개의 카산드라 객체가 어떻게 서로 통신하는지 등을 보게 될 것이다.
여기서 하려는 것은 링에서 여러 개의 기기를 가지고 샘클 키스페이스를 가지고 해보는 것이다. 그래서 디폴트 설정파일로 시작하며 키스페이스 정의 등 간단한 클러스터를 만들기 위하여 설정을 조금 바꾸어 본다.
이것을 위해서 우리는 192.168.1.5 그리고 192.168.1.7 두개의 카산드라를 가지고 클러스터를 만들어본다. 카산드라를 시작할 때 설정파일을 읽어 현재 노드가 어떻게 브로드캐스트하기 원하는 지 결정한다. 어떤 호스트에 어떤 IP 주소를 쓰고 어떤 포트를 사용할 것인지 등등.
당신은 현재 노드에게 다른 노드를과 어떻게 참여하여 함께 링을 만들지를 말해주어야 한다. 이것은 설정 파일을 텍스트 에디터에서 열어서 여기서 보듯이 몇 개의 설정을 조정해주는 간단한 일이다.
클러스터에 추가된 새 노드는 seed node라는 것이 필요하다. 만약 노드 A가 노드 B를 위한seed node로 작동하면 노드 B가 온라인 되면 노드 A를 데이터를 가져오기 위한 참조 포인트로 사용할 것이다. Seed node는 AutoBootstrap설정을 무시하는데 이는 그것이 클러스터의 첫번째 노드라고 가정하기 때문이다.

6.20. 클러스터 이름 변경

카산드라 클러스터는 한 기기가 다른 클러스터에 가입하지 않도록 하기 위해 이름이 주어진다. 디폴트 클러스터의 이름은 설정파일에 “Test Cluster”이다. 당신은 그 이름을 바꿀수 있는데 을 업데이트하면 된다. 당신이 클러스터에 참여시킬 각 노드에 이것을 하면된다.

6.21. 클러스터에 노드를 추가하기

설정파일에는 디폴트로 false로 설정되어 있는 값들이 있다. 당신이 클러스터를 한 개의 노드로 운영을 하고 있다가 데이터를 추가하고 더 많은 노드를 추가한다고 하자. 이것은 autobootstrap 요소를 사용함으로써 할 수 있다. 나는 1.5로 끝나는 IP주소를 가진 한 개의 카산드라 서버를 NodeTool에서 본대로 가지고 있다.
$ bin/nodetool -h 192.168.1.5 ring
Address Status Load Range Ring
192.168.1.5 Up 433.43 MB 126804671661649450065809810549633334036 |<--|
이 서버는 자신의 주소를 seed로 가지고 있다. 이 노드가 seed로 행동하기 때문에 우리는 설정에서 autobootstrap을 false로 놔둔다. Seed에 새로운 노드를 추가하고 싶으면 autobootstrap을 우선 해야하고 seed로 변경해야 한다. 노드 B가 노드 A를 seed로 사용하려면 노드 B는 노드A를 설정파일에서 seed로 참조하도록 해야한다. 그러나 노드A는 스스로 seed로 선언하지 않아도 된다.
이제 업무를 나누기 위해 다른 노드를 추가하겠다. 이 노드의 주소는 1.7 로 끝난다. 우선 새로운 노드가 데이터를 받아들일수 있도록 클러스터에서 모든 노드가 같은 이름과 같은 키스페이스 정의를 가지고 있는지 확인한다. 두번째 노드의 설정 파일을 에디트해서 첫번째것이 seed로 행동한다고 기록한다. 그리고 autobootstrap을 true로 설정한다.
두번째 노드가 시작했을 때 이것은 바로 첫번째 노드를 감지한다. 그러나 90초 동안 잠들면서 노드들이 얼마나 많은 데이터를 로컬로 저장하고 있는지 정보를 gossip하게 만든다. 그리고 첫번째 노드에서 bootstrap 토큰을 가져오고 어떤 섹션의 데이터를 가져와야 하는지 안다. Bootstrap 토큰은 가장 부하가 걸린 노드의 부하를 반으로 나누는 것이다. 다시 두번째 노드는 30초를 잠들고 bootstrapping을 시작한다.
INFO 11:45:43,652 Starting up server gossip
INFO 11:45:43,886 Joining: getting load information
INFO 11:45:43,901 Sleeping 90000 ms to wait for load information...
INFO 11:45:45,742 Node /192.168.1.5 is now part of the cluster
INFO 11:45:46,818 InetAddress /192.168.1.5 is now UP
INFO 11:45:46,818 Started hinted handoff for endPoint /192.168.1.5
INFO 11:45:46,865 Finished hinted handoff of 0 rows to endpoint /192.168.1.5
INFO 11:47:13,913 Joining: getting bootstrap token
INFO 11:47:16,004 New token will be 41707658470746813056713124104091156313 to a
ssume load from /192.168.1.5
INFO 11:47:16,019 Joining: sleeping 30000 ms for pending range setup
INFO 11:47:46,034 Bootstrapping
당신이 얼마나 많은 데이터를 가졌는지에 따라서 당신은 새로운 노드를 보게된다. Nodetool의 streams명령을 사용하여 bootstrap을 위하여 전환되는 데이터를 볼수 있다. Logfile을 보는것은 노드가 bootstrap을 끝내는 것을 결정하는 좋은 방법이다. 그러나 그것이 실제 일어나는 동안에 보는것이다. 마지막으로 새로운 노드는 첫번째 노드로부터 받아들이고 새로운 노드가 시작하였다는 성공적인 표시를 보게된다.
INFO 11:52:29,361 Sampling index for /var/lib/cassandra/data\Keyspace1\Standard
1-1-Data.db
INFO 11:52:34,073 Streaming added /var/lib/cassandra/data\Keyspace1\Standard1-1
-Data.db
INFO 11:52:34,088 Bootstrap/move completed! Now serving reads.
INFO 11:52:34,354 Binding thrift service to /192.168.1.7:9160
INFO 11:52:34,432 Cassandra starting up...
당신이 볼수 있듯이 전환하는데 4분 정도 걸린다.
Bootstrapping 동안 첫번째 seed노드는 이것과 같다.
INFO 11:48:12,955 Sending a stream initiate message to /192.168.1.7 ...
INFO 11:48:12,955 Waiting for transfer to /192.168.1.7 to complete
INFO 11:52:28,903 Done with transfer to /192.168.1.7
이제 다시 node tool을 작동하여 모든 것이 제대로 셋업이 되었는지 확실히 한다.
$ bin/nodetool -h 192.168.1.5 ring
Address Status Load Range Ring
126804671661649450065809810549633334036
192.168.1.7 Up 229.56 MB 41707658470746813056713124104091156313 |<--|
192.168.1.5 Up 459.26 MB 126804671661649450065809810549633334036 |-->|
카산드라는 이전 노드(1.5)로부터 절반의 데이터를 보냄으로써 1.7 노드의 자동 bootstrapping을 한다. 우리는 이제 클러스터에 두개의 노드를 가졌다. 잘 돌아가는지 보기위해 1.5 노드에 값을 추가해보자.
cassandra> connect 192.168.1.5/9160
Connected to: "TDG Cluster" on 192.168.1.5/9160
cassandra> set Keyspace1.Standard2['mykey']['col0']='value0'
Value inserted.
이제 두번째 CLI 클라이언트를 열어서 1.7 노드에서 그 값을 읽어본다.
cassandra> connect 192.168.1.7/9160
Connected to: "TDG Cluster" on 192.168.1.7/9160
cassandra> get Keyspace1.Standard2['mykey']['col0']
=> (column=col0, value=value0, timestamp=1278878907805000
당신은 추가적인 노드를 클러스터에 더하기 위해 이 과정을 반복할 수 있다.
만약 클러스터에서 한 개의 노드가 이상이 있다면 node tool에서 ?를 볼수있다.
$ bin/nodetool -h 192.168.1.5 ring
Address Status Load Range Ring
112711146095673746066359353163476425700
192.168.1.5 Up 459.26 MB 27647275353297313886547808446514704912 |<--|
192.168.1.7 ? 229.53 MB 112711146095673746066359353163476425700 |-->|

6.22. 여러 개의 seed node
카산드라는 당신이 여러 개의 seed node를 정할수 있게 해준다. Seed node는 다른 노드와의 컨택트 포인트 역할로 사용되고 카산드라는 어떤 호스트가 어떤 범위를 가지는지 알수 있도록 클러스터의 토팔러지를 배우게 된다.
디폴트로 설정파일은 한 개의 seed 값을 가진다.
seeds:
- 127.0.0.1
당신의 링에 더많은 seed node를 추가하기 위해서는 다른 seed 엘레먼트를 추가하면 된다. 두 개의 서버를 시드로 추가하려면 IP주소와 호스트 이름을 적어주고 두번째 인스턴스를 추가하면 된다.
seeds:
- 192.168.1.5
- 192.168.1.7
다음으로 이 기기의 듣는 주소를 업데이트 해야한다. 듣는 주소는 노드들이 서로를 어떻게 인지하는지이며 내부적인 커뮤니케이션에 사용된다.
listen_address: 192.168.1.5
마지막으로 RPC클라이언트가 어느 주소에 브로드캐스트하는지 변경해야 하는데 이는 다른 노드들이 이것을 어떻게 바라보는지 이다. 디폴트로 설정 파일은 rpc_address 를 가지고 있어서 로컬 호스트를 사용한다. 이 값을 각 기기의 실제 IP주소로 바꾸어 준다.
rpc_address: 192.168.1.5
rpc_address 셋팅은 클라이언트가 카산드라 노드들과 맺는 연결을 위해서만 쓰인다.
이제 카산드라를 재시작해서 다른 기기들에서 인스톨을 시작할수 있다. 당신의 클러스터에 여러 개의 노드를 추가했다면 이것과 비슷한 출력을 볼 것이다.
INFO 15:45:15,629 Starting up server gossip
INFO 15:45:15,677 Binding thrift service to /192.168.1.5:9160
INFO 15:45:15,681 Cassandra starting up...
DEBUG 15:45:16,636 GC for ParNew: 13 ms, 12879912 reclaimed leaving 11233080 used;
max is 1177812992
DEBUG 15:45:16,647 attempting to connect to /192.168.1.7
DEBUG 15:45:17,638 Disseminating load info ...
INFO 15:45:19,744 Node /192.168.1.7 is now part of the cluster
DEBUG 15:45:19,746 Node /192.168.1.7 state normal, token
41654880048427970483049687892424207188
DEBUG 15:45:19,746 No bootstrapping or leaving nodes -> empty pending ranges
for Keyspace1
INFO 15:45:20,789 InetAddress /192.168.1.7 is now UP
DEBUG 15:45:20,789 Started hinted handoff for endPoint /192.168.1.7
DEBUG 15:45:20,800 Finished hinted handoff for endpoint /192.168.1.7
DEBUG 15:46:17,638 Disseminating load info ...
이 출력은 내가 클러스터에서 두개의 노드를 가지고 있다는 것을 보여준다. 내가 지금 시작한 노드는 192.168.1.5를 듣고 있고 이미 시작하여 동작하고 있는 것은 192.168.1.7을 듣고 있다.

6.23. 다이나믹 링 참가

카산드라 클러스터에서 노드들은 다른 것들에게 방해를 주지 않고 다운되었다가 다시 돌려질 수도 있다. 우리가 이전에 설명했듯이 두개의 노드를 가지고 클러스터를 시작하였다고 하자. 우리는 둘 중의 한 노드가 다운되도록 에러를 유발할수 있다. 그리고 클러스터의 나머지가 아무이상 없다는 것을 확인한다.
INFO 15:34:18,953 Starting up server gossip
INFO 15:34:19,281 Binding thrift service to /192.168.1.7:9160
INFO 15:34:19,343 Cassandra starting up...
INFO 15:45:19,396 Node /192.168.1.5 is now part of the cluster
INFO 15:45:20,176 InetAddress /192.168.1.5 is now UP
INFO 16:13:36,476 error writing to /192.168.1.5
INFO 16:13:40,517 InetAddress /192.168.1.5 is now dead.
INFO 16:21:02,466 error writing to /192.168.1.5
INFO 16:21:02,497 error writing to /192.168.1.5
에러 메시지는 1.5 노드가 되돌아 올때까지 되풀이 된다. Nodetool을 동작해보면 한 노드가 다운되었고 다른 것은 아직 이상없음을 볼 수 있다.
그래서 우리는 다시 되돌리고 1.7 에서 로그를 확인한다. 분명히도 카산드라는 자동적으로 다른 참여자는 클러스터로 되돌아와서 다시 비즈니스를 열었다.
INFO 16:33:48,193 error writing to /192.168.1.5
INFO 16:33:51,235 error writing to /192.168.1.5
INFO 16:34:20,126 Standard2 has reached its threshold; switching in a fresh Mem
table at CommitLogContext(file='/var/lib/cassandra/commitlog\CommitLog-127759165
782.log', position=752)
INFO 16:34:20,173 Enqueuing flush of Memtable(Standard2)@7481705
INFO 16:34:20,251 Writing Memtable(Standard2)@7481705
INFO 16:34:20,282 LocationInfo has reached its threshold; switching in a fresh
Memtable at CommitLogContext(file='/var/lib/cassandra/commitlog\CommitLog-127759
658782.log', position=752)
INFO 16:34:20,298 Enqueuing flush of Memtable(LocationInfo)@24804063
INFO 16:34:20,579 Completed flushing c:\var\lib\cassandra\data\Keyspace1\Standa
d2-1-Data.db
INFO 16:34:20,594 Writing Memtable(LocationInfo)@24804063
INFO 16:34:20,797 Completed flushing c:\var\lib\cassandra\data\system\LocationI
fo-2-Data.db
INFO 16:34:58,159 Node /192.168.1.5 has restarted, now UP again
INFO 16:34:58,159 Node /192.168.1.5 state jump to normal
상태는 1.5 노드에 대해서 다시 정상으로 돌아오고 그것이 클러스터의 일부라고 다시 나타낸다.
eben@morpheus$ bin/nodetool -host 192.168.1.5 ring
Address Status Load Range Ring
41654880048427970483049687892424207188
192.168.1.5 Up 1.71 KB 20846671262289044293293447172905883342 |<--|
192.168.1.7 Up 2 KB 41654880048427970483049687892424207188 |-->|

6.24. 시큐리티

디폴트로 카산드라는 네트워크상의 어느 클라이언트도 당신의 클러스터에 연결할 수 있게한다. 이것은 아무 시큐리티가 설정이 되어있지 않는 것을 의미한다기 보다는 카산드라가 아무에게도 credential을 요청하지 않고 연결되는 인증방식으로 설정이 되어 있는 상태라고 봐야한다. 시큐리티 매커니즘은 플러그인 식으로 사용할수 있고 이는 인증메커니즘이 다른 것으로 사용할 수도 있고 당신 고유의 것을 작성할수도 있음을 말한다.
디폴트로 플러그인 되어있는 인증방식은 org.apache.cassandra.auth.AllowAllAuthenticator 이다. 만약 당신이 클라이언트가 credential을 제공하도록 하고 싶다면 카산드라에서 다른 방법은 org.apache.cassandra.auth.SimpleAuthenticator 이다. 이 섹션에서 이 두번째 인증을 어떻게 쓰는지 살펴본다.

6.24.1. SimpleAuthenticator 사용하기

Config 디렉토리에 두개의 파일이 있다. Access.properties와 passwd.properties이다. access파일은 키/값 쌍을 어떤 사용자가 어떤 키스페이스에 접근이 허용되었는지 알려주고 comma-separated 리스트에 기록되어있다. 예는 아래와 같다.
Keyspace1=jsmith,Elvis Presley,dilbert
이것은 세명의 사용자가 Keyspace1에 접근이 가능하도록 되어있고 사용자 이름으로 키스페이스에 접근허가 되어있다.
Passwd.properties 파일은 이 사용자의 리스트를 가지고 있고 각 사용자의 패스워드를 담고있다. 여기 passwd.properties 파일의 예이다.
jsmith=havebadpass
Elvis\ Presley=graceland4evar
dilbert=nomoovertime
사용자 Elvis Presley에는 사용자이름에 스페이스가 있기 때문에 백슬래쉬로 표시되었음에 유의하라.
Simple Authentiucator를 사용하기 위해서 Cassandra.yaml에 있는 authenticator 요소의 값을 다른 것으로 대치하라. Org.apache.cassandra.auth.AllowAllAuthenticator로부터 변경하여 로그인이 필요한 구현 클래스의 이름으로 바꾸라. Org.apache.cassandra.auth.SimpleAuthenticator.
만약 인증 파일을 적당히 설정하지 않았다면 아래와 같은 에러를 보게된다.
ERROR 10:44:27,928 Fatal error: When using org.apache.cassandra.auth.SimpleAuth
enticator
access.properties and passwd.properties properties must be defined.
그것은 거기 한가지 과정이 더 있기 때문이다. 우리는 스크립트가 있는 bin/Cassandra.in.sh 파일을 사용하여 카산드라에게 access와 password 파일의 위치를 말해주어야 한다. 우리는 이파일의 밑에 아래 코드를 붙여넣어서 JVM에 그 파일 위치들을 넘긴다. 나의 인크루드 파일은 이제 아래와 같이 보이며 파일 풀 패스를 나타낸다.
JVM_OPTS="
-Dpasswd.properties=/home/eben/books/cassandra/dist/
apache-cassandra-0.7.0-beta1/
conf/passwd.properties
-Daccess.properties=/home/eben/books/cassandra/dist/
apache-cassandra-0.7.0-beta1/
conf/access.properties"
만약 당신이 이 파일들의 잘못된 위치나 이름을 썼을 경우에 서버 로그가 알게해준다.
ERROR 11:13:55,755 Internal error processing login
java.lang.RuntimeException: Authentication table file given by property
passwd.properties
could not be found: /somebadpath/my.properties (No such file or directory)
이제 우리는 사용자이름과 패스워드를 가지고 command-line interface로 로그인한다.
[default@unknown] connect localhost/9160
Connected to: "Test Cluster" on localhost/9160
[default@unknown] use Keyspace1 jsmith 'havebadpass'
Authenticated to keyspace: Keyspace1
[jsmith@Keyspace1]
만약 당신이 잘못된 패스워드를 입력하면 CLI가 말해준다.
[default@unknown] use Keyspace1 jsmith 'havebadpassfdfdfd'
Exception during authentication to the cassandra node: verify keyspace exists,
and you are using correct credentials.
만약 당신이 존재하지 않는 사용자 이름을 입력하거나 허가되지 않은 키스페이스에 인증하려고 하면 아래와 같은 메시지를 볼 것이다.
[default@unknown] use Keyspace1 dude 'dude'
Login failure. Did you specify 'keyspace', 'username' and 'password'?
[default@unknown]
약간 혼동되게도 당신이 단지 접근 권한이 없는 키스페이스를 사용하려고 하면 당신은 인증 메시지를 보게될 것이다. 하지만 그리고 어떤 동작을 수행할 수는 없다. 아래의 예에서 우리는 인증이 필요한 키스페이스로 갈 것이다. CLI가 우리가 그것을 하게 하지만 우리는 컬럼을 읽을 수 없다.
[default@Keyspace1] get Standard1['user123']['name']
Your credentials are not sufficient to perform READONLY operations
[default@Keyspace1]
우리가 이 사용자에게 ‘name’ 값을 설정했다면 적당한 credential을 주면 동작을 수행할 수 있다.
[default@Keyspace1] use Keyspace1 eben 'pass'
Authenticated to keyspace: Keyspace1
[eben@Keyspace1] get Standard1['user123']['name']
=> (column=6e616d65, value=bootsy, timestamp=1284316537496000)
[eben@Keyspace1]
우리는 또한 사용자이름, 패스워드 조합을 우리가 CLI에서 접속할 때 보여줄수있다.
eben@morpheus:~/books/cassandra/dist/apache-cassandra-0.7.0-beta1$
bin/cassandra-cli --host localhost --port 9160
--username jsmith --password havebadpass --keyspace Keyspace1
Connected to: "Test Cluster" on localhost/9160
Welcome to cassandra CLI.
Type 'help' or '?' for help. Type 'quit' or 'exit' to quit.
[jsmith@Keyspace1] get Standard1['user123']['name']
=> (column=6e616d65, value=bootsy, timestamp=1284316537496000)
[jsmith@Keyspace1]
쿼리를 실행시키면 이제 우리에게 결과를 반환할 것이다.

6.25. Programmatic Authentication

당신이 당신의 키스페이스에 인증을 하였다면 당신의 클라이언트 애플리케이션 코드는 로그인 할 필요가 있다. 아래 예를 가이드로 삼을 수 있다.
package com.cassandraguide.config;
import java.util.HashMap;
import java.util.Map;
import org.apache.cassandra.thrift.AccessLevel;
import org.apache.cassandra.thrift.AuthenticationRequest;
import org.apache.cassandra.thrift.Cassandra;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
/**
* How to connect if you've set up SimpleAuthenticator
*/
public class AuthExample {
public static void main(String[] args) throws Exception {
TTransport tr = new TSocket("localhost", 9160);
TFramedTransport tf = new TFramedTransport(tr);
TProtocol proto = new TBinaryProtocol(tf);
Cassandra.Client client = new Cassandra.Client(proto);
tr.open();
AuthenticationRequest authRequest = new AuthenticationRequest();
Map credentials = new HashMap();
credentials.put("username", "jsmith");
credentials.put("password", "havebadpass");
authRequest.setCredentials(credentials);
client.set_keyspace("Keyspace1");
AccessLevel access = client.login(authRequest);
System.out.println("ACCESS LEVEL: " + access);
tr.close();
}
}
이 케이스에서 프로그램은 FULL을 프린트 아웃하는데 이것은 사용자의 접근 레벨이다.
여기 몇가지 주의해야 할 점있다. 첫째, credential 맵은 username과 password를 키로서 사용하고 username 은 키가 아니고 password는 값이 아니다. 둘째, 당신은 set_keyspace를 불러야 하는데 어떤 키스페이스를 인증하려고 하는지 말해주어야 하기 때문이다.

6.26. MD5 Encryption 사용하기

SimpleAuthentication 클래스는 패스워드를 명시하기 위한 두가지 모드를 가지고 있다. 평이한 텍스트와 MD5 암호화이다. 여태까지 우리는 디폴트를 이용했으며 그것은 평이한 텍스트이다. 이제 MD5를 사용해서 시큐리티를 향상 시켜보자. MD5는 “Message-Digest algorithm version5” 라는 암호화 알고리즘이다. 이것은 널리쓰이는 입력으로 128bit 해쉬 값을 만들어내는 일방향 해쉬 펑션이다.
당신은 Cassandra.in.sh에서 MD5를 활성화 시키는데 passwd.mode 를 전환하여 JVM에 넘김으로써다.
JVM_OPTS=" \
-da \
//other stuff...
-Dpasswd.mode=MD5"
이제 만약 암호화되지 않은 암호를 인증하려한다면 아래와 같은 에러를 보게된다.
Exception during authentication to the cassandra node, verify you are using correct
credentials.
당신은 일방향 해쉬로 평이한 텍스트의 사용자 이름과 암호를 MD5 버전으로 만들어내려면 다양한 도구들을 사용할 수 있다. 여기 짧은 Python 프로그램이 있어 MD5 해쉬를 평이한 스트링에서 만들수 있다.
$ python
Python 2.6.5 ...
>>> from hashlib import md5
>>> p = "havebadpass"
>>> h = md5(p).hexdigest()
>>> print h
e1a31eee2136eb73e8e47f9e9d13ab0d
이제 jsmith를 위한 암호를 passwd.properties 파일에서 암호화된 값으로 대치할 수 있다.

6.27. 당신 고유의 인증을 제공하기

당신은 Keberos ticket이나 암호화 아니면 암호를 LDAP 디렉토리 같은 다른 곳에 저장하고 싶거나 하면 당신 고유의 인증을 카산드라에 제공할 수 있다. 당신의 인증을 만들기 위하여는 단지 IAuthenticator를 구현하면 된다. 이 인터페이스는 두 개의 메서드를 요구하는데 아래와 같다.
public AccessLevel login(String keyspace, AuthenticationRequest authRequest)
throws AuthenticationException, AuthorizationException;
public void validateConfiguration() throws ConfigurationException;
로그인 메서드는 Thrift AccessLevel 객체를 반환해야 한다. 이는 사용자가 어느 정도 레벨의 인증을 받았는지 알려준다. validateConfiguration 메서드는 단순히 인증 메커니즘이 제대로 셋업되었는지 확인한다. 예를 들어 SimpleAuthenticator 와 그것은 단지 필요한 access와 passwd 파일이 명시되었는지 검사한다.

6.28. 그밖의 셋팅

일반적인 셋팅이지만 여타 특정 카테고리에 속하지 않는 셋팅들이 있다. 그래서 여기에 따로 모아 놓았다.
- Column_index_size_in_kb
이것은 컬럼이 인덱스되기 전에 행이 커질수 있는 킬로바이트 사이즈를 명시한다. 당신이 만약 매우 큰 컬럼 값을 가진다면 이 값을 증가시키기 원할 것이다. 수퍼 컬럼은 인덱스되지 않는다. 그래서 이 셋팅은 오직 인덱스된 컬럼을 참조한다. 당신은 모든 읽는 인덱스 데이터가 읽는 억세스를 위한 것이기에 이 셋팅이 매우 크지는 않기를 원한다. 그래서 필요한 이상을 읽는다면 카산드라가 느려지게 된다. 이것은 만약 당신이 부분적인 행을 자주 읽는다면 특별히 중요할 수 있다.
- In_memory_compaction_limit_in_mb
이 값은 메모리안에 압축되어야 하는 행의 사이즈 제한을 표시한다. 만약 행이 이보다 크면 디스크에 옮겨지고 느린 두단계에 의해서 압축된다. 셋팅 값은 64MB가 디폴트이다. 카산드라 0.7 이전에는 이것은 row_warning_threshold_in_mb 라고 불렸다.
- Gc_grace_seconds
이것은 garbage collecting 이 되기위해 기다리는 시간을 초로 나타낸다. Tombstone은 값이 지워졌다는 것을 나타내며 쓰레쉬 홀드 값을 만날 때까지 기다린다. 디폴트로 864,000으로 셋팅되어 있고 이것은 10일이다. 이것은 비정상적으로 긴시간같지만 tombstone이 클러스터의 모든 복사본으로 퍼져가도록 충분한 시간이 필요하다. 이것은 아직도 긴 시간 같기는 하지만 당신은 하드웨어 오류가 있을 수도 있고 tombstone이 이들이 다시 돌아오고 작동가능해져서 복사가 되어야 한다는 것이다. 만약 다운된 노드가 tombstone이 실제로 지워진 후에 tombstone 노티피케이션을 받지 못했다면 read repair는 지워지지 않은 데이터가 클러스터에 천천히 다시 받아들여지도록 할 것이다. 물론 만약 당신이 많은 지우기를 한다면 당신은 이 설정을 깔끔하게 하기위하여 다시 돌릴수는 있지만 아마도 큰 차이가 나지는 않을 것이다.
- Phi_convict_threshold
이것은 서버가 다운되었다는 최종 판결을 내릴수 있도록 카산드라가 도달해야 하는 Phi 값을 나타낸다. 디폴트로 8로 셋팅되어 있다. 일반적으로 이 값을 바꾸지는 않는다. 그러나 네트워크가 최적화되어 동작하고 있지 못하고 카산드라가 잘못된 읽기를 한다면 값을 증가시켜 노드가 실제로 다운되었는지 결정하는 latency를 더할 수 있다.

6.29. 추가적인 도구들

이 섹션에서 카산드라가 설정하도록 돕는 그밖의 도구들을 논의해 보자.


6.29.1. 키를 보여주기

당신은 sstablekeys 라는 스크립트를 사용하여 어떤 키가 당신의 SSTables에 있는지 볼 수 있다. 이것을 실행하기 위해 키를 보기 위한 SSTable의 위치를 사용한다. 아래와 같다.
eben@morpheus$ bin/sstablekeys /var/lib/cassandra/data/Hotelier/Hotel-1-Data.db
WARN 10:56:05,928 Schema definitions were defined both locally and in cassandra.yaml.
Definitions in cassandra.yaml were ignored.
415a435f303433
415a535f303131
4341535f303231
4e594e5f303432

6.29.2. 이전 설정을 받아들이기

만약 당신이 0.6 버전에서 설정파일에 정의된 키스페이스를 0.7 이나 그 이상에서 임포트하기 원한다면 JMX 동작, StorageService.loadSchemaFromYaml()을 사용할 수 있다. 이것은 두가지 중요한 경고를 가지고 있다. 첫째, 오직 한 번만 사용이 된다. 둘째, 버전 0.8에서는 없어질 것이다.
0.7 버전부터 시작하여 사용자 키스페이스는 Cassandra.yaml에 정의되어 있고 서비스가 시작할때 디폴트로 로드되지 않는다. 그래서 카산드라가 처음으로 시작할 때 아래와 같은 메시지를 보게 될 것이다.
INFO config.DatabaseDescriptor: Found table data in data directories.
Consider using JMX to call org.apache.cassandra.service.StorageService.
loadSchemaFromYaml().
로드하기 위하여 loadSchemaFromYaml 이라는 JMX 동작을 해야한다. 그러나 이명령을 하기 위하여 당신은 몇 가지를 해야한다. 첫째, mx4j-tools.jar를 Sourceforge.net에서 받아라. ZIP 파일을 받아서 압축을 아무 디렉토리에 풀어라. 그리고 mx4j-tools.jar라는 JAR파일을 카산드라 lib 디렉토리에 푼다. 이는 카산드라와 통신하기 위하여 JMX 연결을 만들게 해준다. 우리는 카산드라와 함께 JMX를 사용하는 것을 후에 보겠지만 지금은 키스페이스를 테스트하기 원한다. JAR를 추가한 후에 카산드라를 재시작한다.
다음으로 터미널을 새로 연후에 jconsole 명령을 친다. GUI가 시작되고 JConsole 도구를 로드하여 자바를 장착한다. 이 도구는 Java Virtual Machine을 보고 실행시 데이터를 보고 JMX로 나타내진 동작들을 수행하게 한다.
Cassandra.yaml에 정의된 키스페이스를 로드하기 위해 JConsole GUI에 있는 MBeans탭을 클릭한다. Org.apache.cassandra.service 빈을 펼쳐서 StorageService 그리고 동작이다. loadSchemaFromYaml을 클릭하고 버튼을 클릭한다. 이것은 카산드라 서비스에서 명령을 실행하고 Cassandra.yaml파일에서 당신의 스키마를 로드한다.
한번만 가능한 동작을 0.6 설정을 0.7으로 임포트하려면 loadSchemaFromYaml 동작을 StorageService MBean에 실행한다. 이것은 그림 6-4에 보여진다.
이제 당신의 로그에서 아래와 같은 출력을 보게된다.
17:35:47 INFO thrift.CassandraDaemon: Cassandra starting up...
17:35:48 INFO utils.Mx4jTool: mx4j successfuly loaded
HttpAdaptor version 3.0.2 started on port 8081
17:40:43 INFO config.DatabaseDescriptor: UTF8Type
17:40:43 INFO config.DatabaseDescriptor: BytesType
17:40:43 INFO config.DatabaseDescriptor: UTF8Type
17:40:43 INFO config.DatabaseDescriptor: TimeUUIDType
17:40:43 INFO config.DatabaseDescriptor: BytesType
17:40:43 INFO config.DatabaseDescriptor: BytesType
17:40:43 INFO config.DatabaseDescriptor:
데이터베이스 로그는 동작이 스키마를 잘 로드했는지 보여주는 좋은 것이다.

그림6-4. jconsole도구를 사용하여 Cassandra.yaml에 정의된 오래된 키스페이스를 로드한다.

당신은 org.apache.cassandra.config.Converter클래스를 사용하여 storage-conf.xml을 Cassandra.yaml로 변환할 수 있다. 만약 0.6에서 0.7로 업그레이드 한다면 이것이 첫번째 단계일것이다. 변환기를 실행하기 위하여 config-converter 스크립트를 bin 디렉토리에서 사용한다. 이것은 오래된 파일을 읽어서 변환하고 내용을 덤프한다.

댓글 없음:

댓글 쓰기