AWS에서 Cassandra의 확장성 벤치마킹 – 초당 백만 Write 넘기기.

해당 내용은 http://techblog.netflix.com/2011/11/benchmarking-cassandra-scalability-on.html?showComment=1320770246977#c4531619651000909465 을 발번역한 내용입니다. 오역에 주의하세요.

(역자 주: 해당 데이터가 매우 좋은 Article이지만, 컬럼 패밀리가 여기서 사용하는 것보다 많거나( 해당 테스트는 Write당 10개의 Column Famliy를 이용합니다. ) 테스트를 오래 돌리는 경우, GC 발생, 또는 Compaction 으로 인해서 속도가 맞지 않을 수 있습니다. 카산드라를 도입하실려면, 실제 데이터로 BMT를 해보고 해당 속도를 기준으로 용량 산정을 하는 것을 권장해 드립니다.  카산드라 설정뿐만 아니라, GC등의 JVM 설정도 매우 중요합니다. )

Netflix 는 지난 6개월 이상 아파치 Cassandra NoSQL을 사용하고 있습니다.  해당 벤치마크는 최근에 진행하기로 결정된 카산드라의 성능 특성과, 우리의 툴들과 자동 확장성을 검증하기 위한 테스트의 일부분입니다. Adrian 이 지난주에 해당 결과에 대해  High Performance Transaction Systems workshop에서  발표하였습니다.

Write에 집중된 벤치마크로 Cassandra 패키지의 일부인 Standard Cassandra “Stress” Tool 을 선택했습니다. Denis는 Amazon EC2 에서 해당 테스트를 하고, 분석을 하였습니다. Read 벤치마크는 Memory Cache를 이용하는 반면에 Write 부하는 모두 Disk를 이용합니다. 해당 벤치마크의 결과는 누구나 재현할 수 있습니다. 그러나 Netflix cloud paltform automation for AWS는 이런 종류의 테스트를  더욱 쉽고 빠르게 합니다.

Netflix에서 개발한 자동화 툴은 대규모의 Cassandra cluster을 빠르게 배포할 수 있습니다. 이 경우에, 웹페이지에서 단순한 클릭 몇번으로 한 시간에 US-East 지역의 3개의 EC2 availability zones 에 각각 96개의 instance로 구성된    288 개의 중간 규모 장비의 Cassandra cluster를 구성할 수 있습니다. 그리고 초당 110만의 클라이언트 Write의 부하를 만들 테스트 프로그램을 구동하기 위해서 60개의 인스턴스를 추가합니다. 데이터가 자동으로 3개의 Zones 에서 복제되면서 330만의 Write 를 Cluster 내에서 발생합니다. 전체 테스트는 수백 달러에 2시간 정도면 완료할 수 있습니다. 그리고 이 EC2 instance 들은 테스트 기간만 존재합니다. 설정시간도 없고, datacenter의 공간에 대해 IT 관리자와 논의할 필요도 없고, 테스트가 끝나면 추가적인 비용도 들지 않습니다.(역자 주: 완전 EC2 자랑이네요 ㅎㅎ)

확장성을 측정하기 위해서, 48, 96, 144, 288 인스턴스에서 클라이언트는 10,20, 30, 60 순으로 같은 테스트를 진행했습니다.. 각 instance의 로드는 모든 케이스에서 거의 유사합니다.  그리고 처리양은 instance 수에 따라 선형적으로 증가했습니다.  이전 벤치마크와 제품 출시 때는 6대 부터 48대의 instance 로 Cassandra Cluster를 구성한 적이 있었습니다. 그래서 우리의 배포했던 최대 규모보다 6배나 증가된 규모의 결과를 볼 수 있어서 기뻤습니다. 이 벤치마크는 5일동안 다른일을 하는 사이에 비는 시간을 이용해서 Cassandra 0.8.6의 표준  설정과 테스트 계정을 이용해서 기획부터 결과까지 진행하였습니다. EC2에서 288개의 instance를 생성하는데는 전체 66분 중에 15분 정도 걸렸습니다. 나머지 시간은 Linux 실행  자동화 툴을 실행하기 위해 Apache Tomcat을 시작, Cassandra JVM 시작,  Cassandra Data Store의 ring에 참여하기 위해서 사용하였습니다.( 역자 주: Cassandra라는 DHT 방식으로 서버들끼리 Token을 가지고 이 Token 값을 이용하여 데이터의 위치를 결정합니다. 새로운 서버가 추가되면, 이렇게 Ring 을 교환하는 작업이 필요합니다.)  추가로 일반적인 12개의  instance 로 Cassandra Cluster를 구축하는데는 8분이 걸렸습니다.

Netflix cloud systems group 에서는 최근에 Cassandra의 컴포넌트 성능의 특성에 초점을 맞추는 Cloud Performance Team을 신설했습니다. 그리고 타 팀에서 그들의 코드를 작성하게 하고 AWS 사용을 효율적으로 해서 Netflix와 고객의 비용을 줄여주고 있습니다. 현재 해당 팀에서는 엔지니어를 추가로 구하고 있습니다.(http://www.netflix.com/Jobs?id=7563&jvi=oq8xVfwK)

TL;DR

이 문서의 나머지 부분은 무엇을 수행했고, 어떻게 동작했는지에 대한 자세한 내용입니다. AWS에서 Cassandra를 사용하는 다른 퍼포먼스 팀이 우리의 결과를 확장하거나, 따라할 수 있습니다.

EC2 Configuration

테스트에서 Cassandra를 구동하는 EC2 instances는 M1 Extra Large(m1.xl) 모델입니다. 4개의 중간 속도의 CPU, 15GB RAM, 그리고 각각 400GB의 디스크를 4개 가지고 있습니다. CPU의 성능은 아마존의 8Units에 해당합니다. 흔히 Cassandra에서 사용되는 다른 instance type은 m2 quadruple extra large(m2.4xl) 입니다. 빠른 8개의 CPU, 68GB RAM, 그리고 2개의 800GB 디스크를 가지고 있습니다. 총 26개의 CPU unit을 가집니다.  이 장비들은 주로 많은 데이터를 메모리에 저장해서 읽기 특화된 작업을 위해 사용합니다. 그리고 하나의 Gigabit 네트웍을 가지고 있습니다.  Cluster Compute  Quadruple Extra Large(cc.4×1) 은 빠른 8개의 CPU(총 33.5 units), 23GB RAM, 두개의 800GB 디스크를 가지고 하나의 10GigaBit 네트웍을 가집니다.  아직 이 장비는 써본 적이 없습니다. 이번 테스트에, 우리는 주로 우리의 툴을 검증하기 위해서 인스턴트 숫자를 늘리는 것에 관심을 가졌습니다. 그래서 small instance option을 선택했습니다.  4개의 Disk는 CentOS 5.6 md 와 XFS를 이용해서 함께 Stripe 되었습니다.(역자주, 레이드 구성되었다는 뜻입니다.) Cassandra commit Log와 데이터는 모두 이 파일시스템에 저장되었습니다.

client 로 부하를 주기위한 60대의 장비는 Single Availability Zone 에서 구동되는  m2.4xl 타입입니다. 그래서 30대씩 두 조로 나뉘어서 다른 Zone으로 부하를 주었습니다. 이는 client latency가 약간 증가했다는 것을 의미합니다.

모든 instance는 EC2 Auto-Scaler 특성을 이용해서 생성되었습니다.  하나의 요청은 요구한 사이즈의 하나의  Auto-Scale Group(ASG)  로 구성된다. Amazon Machine Image(AMI) 는 Cassandra 0.8.6 과 Netflix의 특별한 도구들로 구성되어 있다. 세 개의 ASG가  각각의 데이터센터가 떨어진, 1 밀리센컨 정도의 Network Latency를 가지는  Availability Zone으로 생성된다.  EC2는 자동적으로 각각의 존에 설정된 레벨만큼  instance를 생성한다. 어떠한 이유라도 instance가 죽으면, ASG는 자동적으로 대체 instance를 생성하고 Cassandra Cluster의 해당 노드를 교체한다. 모든 데이터는 3가지 방식으로 복제된다. 그 중에서 3개의 서로 다른 데이터센터를 이용하는 것이 매우 가용성을 높여준다.

작은 Cassandra ASG 설정 페이지의 스크린샷입니다. size 필드를 수정하고, 어떠한 사이즈의 클러스터도 생성할  있도록 변경 사항을 기록한다.

Netflix Automation for Cassandra -Priam

(카산드라를 위한 Netflix 자동화 – Priam )

Netflix에서는 백업을 하고 이를 S3(Simple Storage Service)에 저장하는 자동화를 구현했습니다. 그리고 다운 타임 없이 새로운 버전의 카산드라로 업그레이드 할 수 있도록 했습니다.  카산드라가 구동되는 중에, 카산드라 클러스터를 효과적으로 2배로 늘리는 것도 가능합니다. 각각의 새로운 노드들이 기존 노드들의 데이터를 나눠가질 때, 너무 많은 재섞임이 일어나지 않도록 합니다. (역자 주: 카산드라의 경우 데이터가 DHT 방식으로 나눠가지게 되는데, 새로운 노드가 들어오면,  데이터가 가야 할 서버의 키가 바뀔 수 있습니다. 이로 인해, 각 서버들이 각각의 데이터를 새로운 서버에 넘겨주는 과정이 발생하게 됩니다. 이로 인해, 여러 서버가 추가되면, 데이터가 새로운 서버에서 다시 이동하는 현상이 일어날 수 있습니다. 이를 reshuffle 이라고 합니다.) 한 노드가 장애가 발생하면, 다른 IP로 교체하게 됩니다. 그러나 우리는 새로운 장비가 같은 토큰을 가지기를 원했고,  원래의 카산드라 교체 메커니즘을 이 케이스를 명확히 다루기 위해서 확장해야만 했습니다.  그리스 신화의 카산드라 아버지의 이름에서 따와 이 자동화를 “Priam” 이라고 명했습니다. “Priam”은 각각의 Apache 톰캣 JVM에서 동작하고,  현재 Netflix 에만 맞는 코드들을 제거하는 중이며,  올해가 지난 뒤에 오픈 소스로 공개할 예정입니다.  이미 GitHub에 Curator 라는 Zpache Zookeeper interface를 공개했습니다.  Astyanax( Hector의 아들이자, 카산드라의 형제입니다. Hector는 Apache Zookeeper 의 자바 클라이언트 이름입니다. ) 라는 자바 클라이언트를 공개할 예정입니다.  우리는 그리스 신화에서 이름을 따옵니다.

Scale-Up Linearity

(선형적인 스케일 업)

선형적 확장성은 아래 차트에서 보여줍니다. 각 클라이언트 시스템은 초당 17,500  Write 요청을 생성합니다. 그리고 트래픽을 늘리는데 병목이 없습니다. 각 클라언트는 200개의 thread를 트래픽을 생성하기 위해서 이용합니다.


P er-Instance Activity

(인스턴스별 활동)

다음 과정은 병목을 찾기 위해서 각 인스턴스별 평균 활동을 살펴보는 것이다.  아래 표에 정리되어 있다.

서버별 Write 는 우리가 기대했던 것과  비슷하다.  평균 Latency는 선형적 확장이 가능하다는 것을 보여준다. 응답시간은 클라이언트에서 대략 11ms 그리고 1.2ms 정도가 네트웍 Latency 와 thrift client library 의 부하 그리고  응답을 위한 thread의 지연된 스케줄링 때문입니다. 우리의 카산드라 Cluster 에서 복잡한 읽기, 쓰기 연산의 서버의 평균 Latency는 대략 1ms 입니다. CPU Load는 가장 큰 288 Nodes의 Cluster 가 조금 높은 편입니다.  테스트를 한번만 수행했기 때문에, m1.x1 instance typ의  디테일한 스펙의 변화나, 큰 Cluster 에서의 컨넥션등의 증가로 인한 단순한 테스트의 변동성 때문입니다. 디스크 Write 는 Commit Log 쓰기와 순차적인 SSTable Writes 때문입니다. 디스크 Read는 백그라운드로  카산드라 SSTable 을 합치는 Compaction 작업 때문입니다. 네트웍 트래픽은  카산드라의 내부 replication 메시지 때문입니다.

Costs of Running This Benchmark

(해당 벤치마크 수행 비용)

벤치마크는 많은 돈과 시간을 사용합니다.  많은 테스트를 수행함에 있어서,  셋업 시간이라든지, 리소스들의 현실적인 제한등많은 테스팅에 영향을 주는 요소가 있습니다. AWS용 Netflix cloud platform 자동화를 이용하면, setup time 을 굉장히 줄여주고, 많은 테스트를 쉽게 수행하는 비용을 절감할 수 있습니다. 아래의 표에서는 테스트 기간동안 AWS 비용을 보여줍니다. 해당 비용은 Spot Instance 를 이용하거나, 안쓰고 있는 예약된 서버를 이용함으로써 낮출 수 있습니다.( 역자 주: Spot Instance 라고 해서 다른 업체에서 예약된 장비를 싼가격에 짧게 대여할 수 있습니다. )

Cassandra 0.8.6 instance 를 위한 사용할 수 있는 스토리지 영역은, 파일 시스템에서 사용할 수 있는 영역의 절반 정도입니다. 이것은 Cassandra의 현재 Compaction Algorithm 이 Compact 시에 디스크를 필요로 하기 때문입니다. Cassandra 1.0 에서 이것은 SSTable들을 디스크에 압축함으로써 좀 더 Compaction 알고리즘이 개선되었습니다. m1.x1 instance의 경우 한시간에 $0.68 정도이고, m2.4xl 은 시간당 $2.00 의 비용이 듭니다. 해당 테스트는 우리의 3개의 Availability Zone 에 복제를 해두는  설정으로, 여기서, zone을 지나는 트래픽당 1G 마다 $0.01 이 부가됩니다.  zone 을 지나는 트래픽은 전체 트래픽의 2~3배 정도,  그리고 대규모 Cluster에서는 실제 시간당 instance 사용 비용보다 네트웍 사용 비용을 더 지불하는 것으로 보입니다.

해당 테스트를 10분 정도 실행했을 때,  명확하게, 증가하는 것을 볼 수 있었습니다. 계정의 셋업 시간까지 포함해서, 가장 작은 테스트는 1시간 이내에 완료되었고, 가장 큰 테스트는 서버에서 두시간이 걸렸습니다.

전통적인 datacenter 테스트와는 다르게, 권한을 요청하거나, 시스템을 설정하는데 필요한 시간, 또는, 작은 규모의 테스트 전용 시스템을 받을 필요가 없었습니다. 동시에, 많은 테스트를 돌려볼 수 있었습니다. Denis는 create, monitor, analyze 와 테스트 결과를 그려주는 스크립트를 개발했습니다. 예를 들어, 다음은 초당 20,000 요청을 하는 클라언트 측면에서의 응답 시간을  그린 것입니다.

Detailed Cassandra Configuration

(자세한 카산드라 설정)

클라이언트의 요청은 하나의 노드에서라만 완료되었다는 메시지를 받으면 되는 Consistency Level “ONE” 을 이용하였습니다. 데이터를 쓴 후에 Consistent 한 Read 를 위해서 “LOCAL QUORUM”을 이용할 수 있습니다.  3개의 노드에서 적어도 과반수(2개 이상) 에서 응답을 받아야 하고, 이로 인해, 응답 시간이 조금 늘어납니다. 그러나 해당 작업은 Cassandra 에서 데이터의 동일함을 보장하기 위해 꼭 필요한 작업입니다. 게다가 Multi-Region 테스트에서 카산드라의 응답시간이 Europe Region이 US East 보다 Network Latency를 낮다라는 것을 발견해습니다. 이 것은 적은 규모의 배포나, 네트웍 하드웨어가 더 최신이라서 생각합니다. 우리는 다른 AWS 에 대한 네트웍 연결이 테스트이 중요한 요소라고 생각하지는 않습니다.

Stress command line
java -jar stress.jar -d “144 node ids” -e ONE -n 27000000 -l 3 -i 1 -t 200 -p 7102 -o INSERT -c 10 -r

클라이언트는 하나의 row 키로 10개의 컬럼을 쓰고, row 키는 2700만개의 ids 중에 랜덤하게 선택합니다. 각 컬럼은 10 bytes로 된 하나의 key를 가지고 있습니다. 하나의 write 에 대한 사이즈는 대략 400 bytes 입니다.

처음 30개의 클라언트는 첫 144 노드와 통신하고,  다른 30개 클라이언트는 두번째 144 노드와 통신합니다. 3개의 replica를 가지며 상세한 keyspace 설정은 다음과 같습니다.

Cassandra Keyspace Configuration
Keyspace: Keyspace1:
Replication Strategy: org.apache.cassandra.locator.NetworkTopologyStrategy
Durable Writes: true
Options: [us-east:3]
Column Families:
ColumnFamily: Standard1
Key Validation Class: org.apache.cassandra.db.marshal.BytesType
Default column value validator: org.apache.cassandra.db.marshal.BytesType
Columns sorted by: org.apache.cassandra.db.marshal.BytesType
Row cache size / save period in seconds: 0.0/0
Key cache size / save period in seconds: 200000.0/14400
Memtable thresholds: 1.7671875/1440/128 (millions of ops/minutes/MB)
GC grace seconds: 864000
Compaction min/max thresholds: 4/32
Read repair chance: 0.0
Replicate on write: true

Data Flows, Latency and Durability

(데이터 흐름과, 지연 그리고 안정성)

지연시간, 안정성을 이해하기 위해서는 카산드라 설정에 따른 데이터 흐름을 알아야 합니다.  카산드라 Client는 어떤 노드가 자신의 데이터를 저장하는지에 대해서 알지 못합니다.  그래서 랜덤으로 하나의 노드를 중재자로 뽑아서,  올바른 노드에 데이터가 복제되도록 합니다.( row key 에 대한 DHT를 통해서 복제될 노드를 선택합니다. )  가장 빠른 Write는 하나의 노드에만 데이터가 쓰여지면 응답을 보내는 것입니다. 이것은 장애가 난 memcache instances와 연관된 cold cache 이슈를 피하려고 할 때, 짧은 수명 주기를 가진 memcached 의 데이터를 카산드라에 저장할 때 유용합니다.  이것은 속도와 이용성이 Consistency 보다 더 중요할 때 사용됩니다. 거디다가 memcached 와 비교하면 추가적인 network hop이 생깁니다. eventually consistency로 인해서 write 직후에 데이터를 읽으면, 이전 데이터를 읽을 수도 있습니다.

카산드라에서 Consistent Write 를 위해서는Quorum Write 를 이용합니다. 3개의 노드 중에 2개의 노드 이상이 클라이언트가 쓰기에 대한 응답을 얻기 전에, Write에 대한 응답을 주어야 합니다. 게다가, Quorum Write 후에 Read 시에도 Quorum Read 를 이용해야 합니다.  이러면 2개 이상의 데이터의 조합으로 항상 최신의 데이터를 볼 수 있습니다.  카산드라에는 마스터 노드라는 개념이 없기 때문입니다. 어떤 노드가 장애가 나더라도 항상 read, write 가 가능합니다.

카산드라의 Commit Log는 기본적으로 매 10초마다 fsync 를 통해서 디스크에 저장됩니다. 이것은 10초 내에는 실제로 저장된 데이터가 디스크에 쓰여지지 않았다는 뜻입니다. 하지만, 해당 데이터는 세 개의 서버의 메모리에 저장되어 있어서,  세 개의 복사된 데이터가 동시에 모두 사라질 확률은 매우 낮아, 충분한 안정성과 높은 High Availabilty 그리고 낮은 지연시간을 보장해 줍니다.  각 카산드라 서버의 지연시간은 Commit Log Writer 에 저장되는 수 microsecond 입니다.

카산드라는 gossip 프로토콜을 이용해서 각각의 노드의 상태를 서로에게 알려줍니다.  만약 특정 서버에 저장되어야 할 데이터가 서버의 다운으로 저장되지 못하면, 중재가 노드가 이를 기억하고 있다가, 서버가 복구되면, gossip 프로토콜을 이용하여 해당 서버에게 데이터를 전달해줍니다. 이것이 “Hinted Handoff” 입니다.

Netflix 는 아일랜드의 AWS Europe 를 이용해서, 영국, 아일랜드의 확장을 지원하기 위한 global 카산드라 Cluster 를 셋팅하고 테스트 중입니다.  데이터에 대한 Global View 가 필요하면, 여분의 카산드라 node 가 설정되고, 각 서버에 쓰여진 모든 데이터의 복제에 대한 비동기적인 업데이트가 제공됩니다.  마스터 복제본은 존재하지 않고, 지역간 연결이 끊어지더라도, read 와 write 에 LOCAL QUORUM을 이용합니다.  외부 지역에 데이터를 보내야 할  때, 그것의 응답을 기다리지 않습니다. HA를 위해서 내부는 Consistent 한 액세스를 이용하고 외부 지역과는 eventually consistent 액세스를 이용하기 때문에, 다른 지역에 대한 지연은 별로 중용하지 않습니다.

Next Steps(다음 스텝)

카산드라 1.0의 성능 특성과 Multi-Region 에서의 reads 와 write 의 성능에 대해서 좀 더 복잡한 쿼리의 조합과 클라언트 라이브러에 대해서 수많은 테스트를 더 해봐야 합니다.

Takeaway(끝으로…)

Netflix 에서는 AWS에서 Cassandra 를 글로벌 분산 스트리밍 시스템의 중요 시스템의 일부로 사용중입니다. 요구 성능을 넘어서는 선형 확장성을 보여주고, 매우 빠르게 자동정으로 배포가 가능하며, 유지하기도 쉽습니다. 클라우드에서의 벤치마킹도 매우 빠르고, 값싸게 , 확장 가능하게 진행되었습니다. 한번 시도해 보면, 당신도 돌아가길 원하지 않을 것입니다.

만약 당신이 성능 최적화 관련 고수이며, 수분내에 거대한 테스트를 수행하는 툴을 만드는 회사의 직원이 되기를 원한다면, 우리에게 전화를 주시기 바랍니다.(역자 주: 구인광고네요 ㅎㅎ)