Computer Science/Cassandra

[Cassandra] Cassandra Partition에 대해 알아보자

백엔드 규니 2024. 2. 5. 01:23
728x90
반응형

Cassandra Partition에 대해 알아보자

고가용성과 확장성을 위해 설계된 분산형 NoSQL 데이터베이스 시스템인 Cassandra에서 파티셔닝은 중요한 개념입니다.

 

Cassandra는 데이터를 더 작은 파티션으로 나누어 클러스터에 분산하는 과정인 파티셔닝을 통해서 여러 노드에 걸쳐 데이터를 저장합니다.

 

카산드라를 사용할 때 성능을 최적화하고 데이터 분산을 균일하게 하기 위해서는 파티셔닝을 제대로 이해하고 구성하는 것은 아주 중요하고 필수적입니다. (안그러면 카산드라 사용하는 이유 및 효율성이 매우 떨어지는..)

 

본격적인 내용을 들어가기 전에 가볍게 Cassandra Partition Key, Clustering Key, Primary Key에 대해서 살짝만 알아보겠습니다.

image

  • Primary Key = Partition Key + [Clustering Columns]

 

위의 그림을 보면 Cassandra Partition Key, Clustering Key, Primary Key에 대해서 잘 나타내고 있습니다.

Sensor, Date를 Partition Key로 사용하여 노드별로 데이터를 분산시키고, 노드 안에서 파티션 키가 같다면 timestamp를 사용해서 데이터를 정렬하고 있는 것을 알 수 있습니다.

 

Cassandra는 DDL 쿼리에서 Partition Key, Clustering Key, Primary Key를 명시할 수 있는데 이 부분은 해당 글에서 설명하지 않겠습니다. 좀 더 알고 싶다면 여기 글을 참고하면 좋을 것 같습니다.

 

위의 그림을 보면 Partition Key 별로 서로 다른 노드에 저장되고 있는 것을 볼 수 있습니다.

카산드라 읽기 쓰기 작업은 Partition 단위로 진행되는데, 토큰(tokens) (a long value out of range -2^63 to +2^63 -1)을 통해서 데이터를 분산하여 저장합니다.

 

 

Casssandra Token 이란?

image

카산드라 토큰의 범위는 -2^63 to +2^63 -1 입니다. 즉, 노드(서버)별로 토큰의 할당 범위를 가지게 됩니다. (노드가 추가되거나 제거되면 토큰 재할당(데이터 재분배) 과정이 필요함)

 

파티션은 주어진 파티션 키를 토큰으로 변환하기 위해 파티셔너를 사용하고, 카산드라는 파티션 키를 사용하여 노드에 데이터를 분산하여 저장하고 데이터를 읽어올 때 어떤 노드에서 데이터를 찾을지 결정합니다. (즉, 파티션 키가 같다면 같은 노드에 저장됨)

 

참고로 Cassandra Partitioner는 Murmur3Partitioner(default), RandomPartitioner, ByteOrderedPartitioner 3가지를 제공하는데 자세한 것은 여기에서 확인할 수 있습니다.

 

이렇게 말만 들으면 무슨 말인지 이해가 완벽하게 안될 수 있는데요. 좀 더 구체적인 예시를 들어보겠습니다.

 

name age car gender
jim 15 camaro M
carol 23 bmw F
johnny 35   M
suzy 29   F

위처럼 partitionKey가 name인 카산드라 테이블에 데이터가 있다고 가정하겠습니다.

 

 

partition key murmur3 hash value (token)
jim -2245462676723223822
carol 7723358927203680754
johnny -6723372854036780875
suzy 1168604627387940318

파티션 키 name을  murmur3 파티셔너를 사용하여 해싱하면 위의 값처럼 토큰이 만들어지게 될 것입니다.

 

 

 

image

 

그러면 위처럼 노드별로 토큰 할당 범위를 가지고 있어서 데이터가 분산되어 저장되는 것입니다.

 

 

node start range end range partition key hash value
A -9223372036854775808 -4611686018427387904 johnny -6723372854036780875
B -4611686018427387903 -1 jim -2245462676723223822
C 0 4611686018427387903 suzy 1168604627387940318
D 4611686018427387904 9223372036854775807 carol 7723358927203680754

 

예시를 보면 카산드라 토큰과 파티셔닝을 통하여 데이터가 분산되어 저장되는 방식에 대해서 잘 이해할 수 있을 것이라 생각합니다.

 

 

 

image

 

카산드라 토큰과 데이터 분산되는 방식에 대해 한눈에 보기 좋은 그림이 있어서 이것도 같이 참고하면 좋을 것 같습니다.

 

 

 

카산드라 Partition 설계할 때 알아야 할 점

파티션 사이즈

카산드라 실질적인 Partition Size는 20억 셀이라고 하는데 이렇게 큰 것은 비효율적이라 적절한 파티션 수를 가지는 것이 필요합니다.

또한 중요한 것은 카산드라의 최대 파티션 크기는 100MB 이하여야 하는데, 이상적으로는 10MB 이하여야 합니다. 10MB가 넘어가면 데이터를 읽어올 때 성능 저하가 생길 수 있습니다.

 

파티션 데이터 불균형

파티션 키를 잘못 설계하면 특정 파티션으로 데이터가 많이 쏠려서 파티션마다의 데이터가 불균형하게 분배되어 저장될 수 있습니다. 예시를 통해서 좀 더 자세히 알아보겠습니다.

CREATE TABLE server_logs(
   log_hour timestamp,
   log_level text,
   message text,
   server text,
   PRIMARY KEY (server)
)

만약에 server 컬럼 하나만 파티션 키를 지정했다면 어떻게 될까요? 서버의 로그는 시간이 지나면 계속 쌓이게 되는데 이러면 파티션 사이즈도 무한히 증가할 수 있다는 것을 뜻합니다.

 

CREATE TABLE server_logs(
   log_hour timestamp,
   log_level text,
   message text,
   server text,
   PRIMARY KEY ((log_hour, server))
)

이번에는 log_hour, server를 하나의 파티션 키로 지정 했다면 어떻게 될까요? 파티션은 시간 단위로 나뉘어 지게 될테고 파티션 사이즈의 무한한 증가를 막을 수 있습니다.

 

partition skew는 파티션에 할당된 데이터가 다른 파티션에 비해 더 많고 시간이 지남에 따라 파티션이 무한히 증가하는 조건을 의미하는데 이를 조심해서 설계해야 합니다.

CREATE TABLE server_logs(
   log_hour timestamp,
   log_level text,
   message text,
   server text,
   slot int
   PRIMARY KEY ((server, slot))
)

아니면 특정 컬럼을 추가하여, 특정 개수가 되면 파티션을 분배할 수 있도록 slot 이라는 개념을 추가하여 파티션을 분배할 수도 있고.. 등등 다양한 방법이 있을 것입니다.

 

 

Replication Factor

데이터베이스나 Kafka 처럼 데이터를 처리하고 다루는 곳에서 복제본은 내결함성(fault tolerance) 및 고가용성(high availability)을 제공하기 때문에, Replcation Factor 개념은 매우 중요합니다.

 

카산드라에서도 데이터에 대한 Replication Factor를 설정할 수 있으며, 이는 클러스터 전체에 각 파티션의 복제본 수를 몇개 가지고 있을지 결정하는 옵션입니다.

image

만약에 Replication Factor = 3 이라면 위처럼 3개의 노드에 데이터를 복제해서 저장하게 됩니다. 만약에 해당 파티션을 담당하는 메인 노드가 다운되게 되면 복제되어 있는 노드에서 해당 파티션의 데이터를 응답하게 됩니다. 그리고 카산드라는 백그라운드에서 데이터를 비동기적으로 복제합니다.

 

카산드라에서 복제 전략에는 아래와 같이 2가지가 존재합니다.

  • SimpleStrategy: 하나의 데이터 센터와 하나의 rack 을 사용하고 있을 때 사용. 두 개 이상의 데이터 센터를 사용한다면 NetworkTopologyStrategy 전략을 사용해야 함
  • NetworkTopologyStrategy: 향후 카산드라 확장이 필요할 때 여러 데이터 센터로 확장하기가 훨씬 쉽기 때문에 대부분의 구축에 권장되는 옵션

 

 

데이터 복제에 관한 자세한 것은 여기를 참고하면 좋을 것 같습니다.

 

카산드라 클러스터에 미치는 파티션의 영향

위에서 파티션의 크기는 10MB 이하를 유지하는 것이 이상적이라고 하였는데요. 이는 직관적으로? 단순하게? 생각해보아도, 하나의 파티션 점점 커진다면 해당 노드에서 데이터를 가져오는데 빠르게 효율적으로 가져오기 힘들어질 것입니다.

즉, 각 파티션에 저장된 데이터의 크기를 제어하는 것은 클러스터 전체에 데이터를 균등하게 분산하고 I/O 성능을 높이기 위해 필수적입니다.

 

읽기 성능

Cassandra는 Cache, Index, Index summaries 등등 디스크의 SStables 파일 내에서 파티션을 찾아서 데이터를 가져오는 내부적인 동작 과정이 있는데, 큰 파티션은 이러한 데이터 구조를 유지하는데 비효율적이고 성능 저하를 초래합니다. 이는 다른 글에서 다시 정리해보겠습니다.

 

Memory Usage

파티션 크기는 JVM Heap 크기 및 카산드라 Garbage Collection 메커니즘에 직접적인 영향을 미칩니다. 파티션 사이즈가 크다면 Garbage Collection이 비효율적입니다.

 

카산드라의 내부 동작 및 메모리 사용에 대해 좀 더 자세하 알게 되면 더 자세히 이해가 될 것 같습니다. (Link)

 

Casssandra Repair

카산드라 repair는 데이터를 일관성 있게 만들 수 있는 것입니다. (자세한 것은 여기를 참고)

repair는 노드간에 데이터 일관성이 깨졌을 때, 데이터를 스캔하여 다른 노드의 데이터 복제본과 비교한 후 데이텉 싱크를 맞추는 작업이라고 할 수 있습니다.

 

만약에 파티션 크기가 크다면 repair를 통해서 데이터를 복구 및 싱크를 맞추는 작업이 부담이 될 수 있습니다.

 

Tombstone Eviction

카산드라는 데이터 삭제 할 때 바로 삭제하지 않고 tombstone 표시를 남겨놓고, 나중에 삭제를 진행합니다. 이는 Compaction 전략이 적절하게 동작하지 않는다면 큰 파티션이 tombstone 제거할 때 어려움이 있을 수 있습니다.

 

Tombstone이 무엇인지는 여기여기 글을 참고하면 좋을 것 같고 다른 글에서 Compaction 등등 개념들을 다루어 보도록 하겠습니다.

 

마무리 하며

카산드라는 알면 알수록 재밌으면서 어렵고.. 많은 것을 알게되는 것 같습니다. 카산드라 Partition에 대해 가볍게 정리하려 했는데, 파티션과 연결되어 있는 여러가지 개념 및 용어들이 많이 나온거 같습니다. 앞으로 카산드라 용어 및 내부 동작들에 대해서 앞으로 하나씩 계속 정리해보겠습니다.

 

Referenece

반응형