- Cassandra 란?
- scalability 와 high-availability 에 최적화된, 대표적인 "분산 데이터 저장소".
- Consistent Hashing을 이용한 Ring형태의 Multi-Master 구조.
- DHT(Disgtributed Hash-Table) 으로 Ring Topology 지원한다고 봄.
- 분산된 환경에서 Hash-Table을 동적으로 관리하것은 쉽지 않기 때문에... 미리 정해놓는 전략임.
- 여러대의 Virtual-Node를 으로, Hashing의 범위를 아주 잘게 고르게 만듬.
- Ring에 속한 Node들간, 지속적인 Gossip-Protocol으로~ Virtual-Node 변화를 자동 rebalance 처리함.
- 새로운 Node 추가가 용이해, 수평적 확장이 손쉬움.
- 결과적으로, 서버를 늘리고 줄이는 비용이 낮아지는 강점을 갖게 됨.
- 모든 Node가 동일한 Master 역할을 함.
- 각 Node마다 coodinator가 있고, 특정 data를 Replication-Factor 맞게 해당 Master를 찾아 처리해줌.
- 이 결과, 서버간의 Consistancy에는 약점을 갖게 됨.
- Tuneable-Consistency : StrongConsistency <-> EventualConsistency 선택 및 조정 가능
- DHT(Disgtributed Hash-Table) 으로 Ring Topology 지원한다고 봄.
- 단순 equl쿼리는 매우 강력하지만... join 및 transaction 지원않고, index도 매우 단출~ paging도 구현 힘듬.
- 전체데이터(Keyspace) -> Table단위(Column-Family) -> Row단위 -> Column단위 -> (Name-Value)
- 각 서버에 Column-Family이라는 Table들로 분산되어서 저장.
- 각 데이터는 Row-Key 으로 Hashing되어, 각 Table에 Row로 저장
- 따라서, 특정 Row-Key 으로 range쿼리나 sort쿼리가 되지 않는것.
- 그래서, 특정 Row의 내부 Column으로만 처리가 될수있도록 설계 필요.
- (Row의 모든 Column은 쭉~ 정렬되어 Flat-Wide-Row 식으로 제공)
- 예) 특정 sensorId를 Row-Key로 하고, 날짜별 데이터를 Column 정렬
- Row-Key 기준으로 데이터가 잘 분산 될 수 있기 때문에~ "Write 성능"이 좋음.
- Write Operation
- 사용자 -{write request}-> coordinator -> ('RowKey해싱' 및 '해당Node상태확인' 및 'hint hand off 백업')
- coordinator -{write operation}-> CommitLog(disk) -{add value to}-> MemTable(memory) -{flush}-> SSTable1,2,3
- (http://docs.datastax.com)
- CommitLog : disk에 기록이 되면, 'Write Operation' 성공으로 간주. (최종 flush를 판단하는 bitFlag 보유)
- MemTable : disk에 기록 --(데이터)--> memory로 기록. (threshold 도달하면, flush 한뒤, 다시 new 생성)
- SSTable : immutable하며 sequential하고, 주기적 compaction 관리 됨. (순차적 빠른 Write 성능 제공)
- Delete Operation
- Cassandra는 기본적으로 모든 데이터를 sequencial하게 저장하고, 삭제도 tumbstone 표시만되고 남아있음.
- 그래서 빈번한 Delete를 하면서, Read를 하면~ 데이터를 sequencial하게 찾기때문에... 성능저하.
- // TODO : ...
- Compaction
- SSTable는 immutable 함. 즉, 절때 수정이 불가능함.
- 여러게의 SSTable를 -> 하나의 SSTable으로 꽉채우는 관리.
- (즉, 파편화 되있는 데이터들을 Row-Key 기반으로 정렬 및 병합하여~ 저장공간을 확보하는 처리과정)
- "Delete Operation"는 'tumbstone-marker' 표시로 비동기 처리 됨.
- "Update Operation"도 내부적으로 Delete 및 Write 으로 처리 됨.
- 'GarbageCollection이벤트' 나 'Compaction이벤트'에서 'tumbstone'이 실질적으로 제거되는 것.
- 대량의 Delete 상황에 안좋음.
- cassandra.yaml 설정
- cluster_name : 클러스터의 모든 Node에 동일하게 지정.
- seed_provider : 초기 Hash-Table을 Gossip-Protocol으로 분배 하는 놈.
- class_name :
- parameters :
- num_tokens : 하나의 Node에 몇대의 Virtual-Node를 운영할지 정함.
- listen_address : 각 Node의 IP
- rpc_address : 0.0.0.0
- *partitioner* : Row-Key를 Hashing 하는 모듈.
- // RandomPartitioner : MD5사용.
- // Murmur3Partitioner : Murmer3사용. (디폴트 Partitioner)
- // ByteOrderedPartitioner : 단순 16진수 변환. (Row-Key 순서가 썩이지 않아, range쿼리 가능) (but, HotSpot 위험)
- snitch : 데이터의 효과적인 복제 및 라우팅이 이루어 질수있도록~ 네트워크 토폴로지 설정
- SimpleSnitch, RackInferringSnitch, PropertyFileSnitch, EC2Snitch, ...
- data_file_dir :
- commitlog_dir :
- saved_caches_dir :
- gc_grace_seconds :
- Cassandra-cli : // TODO : ...
- Column-Family 생성
- Column의 메타 지정. (스키마를 강제하는 의미는 아님!!!)
- Column에 관한 Validator를 지정하는 목적
- key_validation_class : Row-Key의 타입 지정
- comparator : column-key의 타입 지정
- validation_class : value의 타입 지정
- Dynamic Column-Family 처럼 메타 지정을 하지않아도 됨.
- Light-Weight Transaction
- Insert 나 Update 를 'IF 특정조건'에 맞추어 동작하도록 하는 기능.
- 예) INSERT INTO keyspace.table (id, name, desc) VALUES ('id_1', 'name_1', 'desc_2') IF NOT EXISTS;
- 예) UPDATE keyspace.table SET desc='desc_3' WHERE id = 'id_1' IF name = 'name_1';
- 별도의 applied컬럼으로 적용여부 받음. (쿼리 자유도가 낮고, 성능이슈가 있음.)
- Secondary-Index
- 간단한 검색을 위해서 추가된 기능.
- Cassandra는 기본적으로 Row-Key(Partition-Key)으로 분산 , Column-Name(Cluster-Key)으로 내부정렬 임.
- 그래서 검색을... 데이터 비정규화로 해왔고, 이를 보완하고자~ 해당 Column으로 Column-Family(table)가 따로 관리됨.
- 예) CREATE INDEX secnd_idx ON keyspace.table (name);
- 물론 여전히 제약이 많고, range쿼리 및 sort쿼리 지원하는건 아님. (성능이슈도 당연히 존재)
- 해당 Column-Value를 Row-Key으로 잡고, "실제Row-Key"를 포인팅 하는 구조.
- 예) row-key:busan
- (name=user_id_1, value=)
- 예) row-key:seoul
- (name=user_id_2, value=)
- (name=user_id_3, value=)
- 예) row-key:busan
- 따라서, Column-Value를 잡못잡으면... 모든 Node를 바쁘게 만든다...
- Column Index Expire
- column-name를 복!합!적!으로 "city:seoul" 식으로 하면, 정렬이 활용되어 좋음.
- column-name을 고유하게 "sensor:timeuuid타입" 식으로 하면, UPSERT 유실 방지.
- 툴
- DataStax Studio : CQL만을 지원하는, 카싼드라 GUI 클라이언트. (구버전 : DataStax DevCenter)
- OpsCenter : 웹기반의 관리 및 모니터링.
-끝-