Redis와 다른 DB를 비교하는 벤치마크가 없는 이유
Redis의 속도는 신규 사용자에게 매력적인 장점이 될 수 있으므로, 비교를 통한 “광고”가 유행하는 흐름을 따른다면 Redis.io에도 몇 가지 비교 자료를 올리는 것이 논리적으로 보일 수 있습니다. 하지만 여기에는 두 가지 문제가 있습니다. 하나는 목표의 문제입니다. 저는 개발자들에게 Redis를 도입하라고 설득하고 싶은 것이 아닙니다. 그저 적합한 제품을 제공하기 위해 최선을 다할 뿐이고, 사람들이 Redis로 일을 해낼 수 있다면 그것으로 만족합니다. 제 마케팅 욕심은 거기까지입니다. 또 한 가지 문제가 있습니다. 서로 다른 시스템을 공정하게 비교하는 일은 거의 언제나 불가능합니다.
두 데이터베이스를 비교해 공정한 수치를 얻으려면 데이터 모델, 정확한 내구성 보장, 데이터 복제의 안전성, 네트워크 파티션 중 가용성 등을 비롯해 정말 많은 부분을 공유해야 합니다. 어떤 시스템이 다른 시스템보다 낮은 점수를 받는 경우가 많은데, 이는 속도를 희생해 덜 “나를 봐 달라”는 식의 특성들을 제공하기 때문일 수 있습니다. 하지만 그런 특성도 여전히 매우 중요합니다. 게다가 서로 다른 데이터베이스 시스템이 정확히 같은 프로토콜로 통신하는 경우가 아니라면 테스트 도구 모음도 복잡한 문제가 됩니다. 클라이언트 라이브러리의 차이만으로도 큰 성능 차이가 발생할 수 있습니다.
그렇지만 이에 동의하지 않는 사람들도 있고, 서로 다른 데이터베이스 시스템의 속도를 비교하는 것이 어쨌든 좋은 생각이라고 믿습니다. 예를 들어 어제 이곳에 Redis와 AerospikeDB의 벤치마크가 게시되었습니다: http://lynnlangit.com/2015/01/28/lessons-learned-benchmarking-nosql-on-the-aws-cloud-aerospikedb-and-redis/.
이 벤치마크를 예로 들어 벤치마크가 어떻게 사람을 오도하는지 보여드리겠습니다. 이 벤치마크에서는 무슨 이유에서인지 244GB의 RAM을 탑재한 거대한 EC2 인스턴스를 사용합니다(!). R3.8xlarge 인스턴스입니다. 제 테스트에서는 좀 더 현실적인 m3.medium 인스턴스를 사용하겠습니다.
이처럼 엄청난 인스턴스를 사용하면 Redis는 단일 노드 환경에서 초당 128k ops를 처리할 수 있는 것으로 나타납니다. 제 EC2 인스턴스는 훨씬 제한적입니다. 다른 EC2 인스턴스에서 Redis benchmark를 사용해 파이프라이닝 없이, 동일하게 100바이트 데이터를 대상으로 테스트했더니 초당 32k ops가 나왔습니다. 즉 단일 프로세스 환경에서 제 인스턴스는 대략 4배 느립니다.
Redis의 INFO 명령으로 이 벤치마크 중 시스템이 CPU를 어떻게 사용하는지 살펴보겠습니다.
# CPU
used_cpu_sys:181.78
used_cpu_user:205.05
used_cpu_sys_children:0.12
used_cpu_user_children:0.87
127.0.0.1:6379> info cpu… 테스트 10초 후 …
# CPU
used_cpu_sys:184.52
used_cpu_user:206.42
used_cpu_sys_children:0.12
used_cpu_user_children:0.87Redis는 시스템 시간으로 약 3초를 사용했고, 사용자 공간에서는 약 1.5초만 사용했습니다. 여기서 일어나는 일은 각 요청마다 가장 큰 작업이 read()와 write() 호출을 수행하는 것이라는 점입니다. 또한 각 클라이언트가 요청 하나에 응답 하나를 받는 작업이므로, 클라이언트별 각 요청마다 전체 RTT를 지불하게 됩니다.
이제 대신 파이프라이닝을 사용하면 어떻게 되는지 확인해 보겠습니다. 파이프라이닝은 Redis 사용자에게 매우 잘 알려져 있고 널리 활용되는 기능입니다. 서버 사용률을 극대화할 수 있는 유일한 방법이기 때문이며, 애플리케이션에는 한 번에 여러 작업을 수행할 수 있는 지점이 대개 여러 곳 있습니다.
32개 작업을 파이프라인으로 묶자 수치가 크게 달라졌습니다. 제 작은 인스턴스는 코어 하나만 사용해 초당 250k ops를 처리할 수 있었습니다. 이는 앞서 언급한 벤치마크에서 더 빠른 코어 32개를 사용해 얻은 최고 결과의 25%입니다.
CPU 시간을 살펴보겠습니다.
# CPU
used_cpu_sys:189.16
used_cpu_user:216.46
used_cpu_sys_children:0.12
used_cpu_user_children:0.87
127.0.0.1:6379> info cpu… 테스트 10초 후 …
# CPU
used_cpu_sys:190.60
used_cpu_user:224.92
used_cpu_sys_children:0.12
used_cpu_user_children:0.87이번에는 실제로 CPU를 사용해 데이터베이스 엔진이 쿼리를 처리하고 있습니다. 단순히 컨텍스트 전환으로 많은 시간을 낭비하고 있는 것이 아닙니다. 시스템 시간은 약 1.5초를 사용했고, Redis 프로세스 자체에서는 8.46초를 사용했습니다.
파이프라인의 작업 수를 줄이면 중간 수준의 결과가 나옵니다. 파이프라인 4개에서는 초당 100k ops가 나오고(벤치마크에서 사용한 더 큰 인스턴스에서는 초당 약 400k ops에 해당해야 합니다), 파이프라인 8개에서는 초당 180k ops가 나오는 식입니다.
따라서 기본적으로 이런 방식으로 Redis와 AerospikeDB를 벤치마크했을 때 놀랄 만큼 비슷한 결과가 나오는 것은 우연이 아닙니다. 대략적으로 말해 데이터베이스를 테스트하는 것이 아니라 네트워크 스택과 커널을 테스트하는 셈입니다. 데이터베이스가 다른 큰 낭비 없이 read와 write 시스템 호출만으로 쿼리를 처리할 수 있다면 이런 결과가 나옵니다. 여기서는 메모리에 들어가는 데이터를 다루므로 실제 쿼리를 처리하는 데 걸리는 시간이 짧습니다. (참고로 Redis에서 100k 크기의 키 1,000만 개를 사용해도 해당 인스턴스에 할당된 메모리의 일부만 사용합니다.)
하지만 여기에는 더 중요한 점이 있습니다. 우리가 수행할 수 있는 작업은 어떨까요? Redis에서 GET/SET만 수행해 테스트하는 것은 비가 올 때 Ferrari가 거울을 얼마나 잘 닦는지 확인해 성능을 평가하는 것과 같습니다.
Redis 아키텍처의 핵심은 성격이 크게 다른 작업들도 비용이 대체로 비슷하다는 점입니다. 그렇다면 대규모 Facebook 게임에서 종료된 게임의 점수를 게시해 리더보드를 만든다면 어떨까요?
쿼리가 ZADD myscores <random-int> <random-int>일 때 동일한 단일 프로세스에서 초당 110k ops를 처리할 수 있습니다.
좀 더 요구해 보겠습니다. HyperLogLog로 카디널리티를 추정하면서 동시에 새 요소를 추가하고, 두 개의 redis-benchmark 프로세스로 현재 추정치를 읽으면 어떻게 될까요? 집합의 크기는 다시 1,000만 개입니다. 이 테스트에서는 집합에서 무작위 요소를 사용해 PFADD를 실행하는 벤치마크 하나와, 같은 HyperLogLog에서 동시에 PFCOUNT를 실행하는 벤치마크 하나를 띄웠습니다. 두 프로세스는 각각 초당 250k ops를 동시에 처리했고, Redis 프로세스 하나에서 총 초당 50만 ops가 나왔습니다.
Redis에서 복잡한 작업을 수행하는 것은 파이프라이닝과 비슷합니다. 한 번의 read/write마다 더 많은 일을 처리해야 합니다. 그렇지 않으면 성능은 I/O에 의해 좌우됩니다.
좋습니다. 여기서 몇 가지 유용한 결론을 정리해 보겠습니다. 1) GET/SET 벤치마크는 서로 다른 데이터베이스 시스템을 비교하는 좋은 방법이 아닙니다. 2) 더 나은 성능 비교 방법은 사용 사례를 기준으로 하는 것입니다. 특정 사용 사례에서 서로 다른 데이터 모델, 스키마, 쿼리, 전략을 사용해 두 데이터베이스 시스템으로 동일한 애플리케이션의 동일한 트래픽을 처리하려면 각각 몇 개의 인스턴스가 필요한지 비교하는 방식입니다. 3) 대부분의 사람이 실제로 사용할 인스턴스 유형으로 테스트해야 합니다. 거대한 인스턴스 유형은 특정 데이터베이스 시스템의 비효율성을 가릴 수 있으며, 어차피 대부분의 사람이 사용하려는 환경도 아닙니다.
앞으로도 Redis를 더 빠르게 최적화해 나가겠지만, 비교 벤치마크를 게시하는 일은 계속 피할 것입니다.
[무료로 EC2에 액세스할 수 있도록 지원해 준 Amazon AWS에 감사드립니다]
글을 무작위로 읽기