Redis는 기반 기술이므로 대체 아키텍처를 고려하는 사람들을 종종 봅니다. 몇 년 전 KeyDB에서 이 문제를 제기했으며 최근에는 새로운 프로젝트인 Dragonfly가 가장 빠른 Redis 호환 메모리 내 데이터 저장소라고 주장했습니다. 우리는 이러한 프로젝트가 토론하고 토론할 가치가 있는 많은 흥미로운 기술과 아이디어를 가져올 것이라고 믿습니다. 여기 Redis에서 우리는 Redis가 처음에 디자인된 아키텍처 원칙을 재확인해야 하기 때문에 이런 종류의 도전을 좋아합니다.
우리는 항상 Redis의 성능과 기능을 혁신하고 발전시킬 기회를 찾고 있지만 Redis 아키텍처가 메모리 내 실시간 데이터 저장소(캐시 , 데이터베이스 및 그 사이의 모든 것).
따라서 다음 섹션에서는 비교와 관련하여 속도 및 아키텍처 차이점에 대한 관점을 강조합니다. 이 게시물의 끝에서 우리는 벤치마크와 성능 비교와 Dragonfly 프로젝트에 대한 세부 정보도 제공했으며, 아래에서 논의하고 이를 직접 검토하고 재현하도록 초대합니다.
속도
Dragonfly 벤치마크는 독립 실행형 단일 프로세스 Redis 인스턴스(단일 코어만 활용할 수 있음)와 다중 스레드 Dragonfly 인스턴스(VM/서버에서 사용 가능한 모든 코어를 활용할 수 있음)를 비교합니다. 불행히도 이 비교는 Redis가 실제 세계에서 실행되는 방식을 나타내지 않습니다. 기술 빌더로서 우리는 우리 기술이 다른 기술과 어떻게 비교되는지 정확히 이해하기 위해 노력합니다. 그래서 공정한 비교라고 생각하는 대로 수행했으며 40개의 샤드 Redis 7.0 클러스터(인스턴스 코어의 대부분을 활용할 수 있음)와 Dragonfly를 사용하여 비교했습니다. Dragonfly 팀이 벤치마크에서 사용하는 가장 큰 인스턴스 유형인 AWS c6gn.16xlarge에 대한 성능 테스트 세트. 평가판에서 Redis는 64개 vCore 중 40개만 사용하는 경우에도 Dragonfly보다 18% – 40% 더 높은 처리량을 달성하는 것을 보았습니다.
구조적 차이점
일부 배경
우리는 이러한 다중 스레드 프로젝트의 제작자가 내린 많은 아키텍처 결정이 이전 작업에서 경험한 고충의 영향을 받았다고 생각합니다. 우리는 때때로 수십 개의 코어와 수백 GB의 메모리가 있는 멀티 코어 시스템에서 단일 Redis 프로세스를 실행하는 것이 명확하게 사용 가능한 리소스를 활용하지 않을 것이라는 데 동의합니다. 그러나 이것은 Redis가 사용되도록 설계된 방식이 아닙니다. 이것은 얼마나 많은 Redis 공급자가 서비스를 실행하기로 선택했는지입니다.
Redis는 단일 클라우드 인스턴스의 컨텍스트에서도 다중 프로세스(Redis Cluster 사용)를 실행하여 수평으로 확장됩니다. Redis(회사)에서 우리는 이 개념을 더욱 발전시켰고 사용자가 Redis를 대규모로 실행할 수 있도록 하는 관리 계층을 제공하는 Redis Enterprise를 구축했으며, 기본적으로 고가용성, 즉각적인 장애 조치, 데이터 지속성 및 백업이 활성화되었습니다.
우리는 프로덕션 환경에서 Redis를 실행하기 위한 좋은 엔지니어링 사례를 사람들이 이해할 수 있도록 배후에서 사용하는 몇 가지 원칙을 공유하기로 결정했습니다.
건축 원칙
VM당 여러 Redis 인스턴스 실행
VM당 여러 Redis 인스턴스를 실행하면 다음과 같은 이점이 있습니다.
- 완전히 공유되지 않는 아키텍처를 사용하여 수직 및 수평으로 선형 확장합니다. 이는 수직으로만 확장되는 멀티스레드 아키텍처에 비해 항상 더 많은 유연성을 제공합니다.
- 복제가 여러 프로세스에서 병렬로 수행되므로 복제 속도를 높입니다.
- 새 VM의 Redis 인스턴스가 여러 외부 Redis 인스턴스의 데이터로 동시에 채워지기 때문에 VM 오류로부터 빠르게 복구합니다.
각 Redis 프로세스를 적절한 크기로 제한
단일 Redis 프로세스의 크기가 25GB(플래시에서 Redis를 실행할 때 50GB)를 초과하는 것은 허용되지 않습니다. 이를 통해 다음을 수행할 수 있습니다.
- 복제, 스냅샷 및 AOF(Append Only File) 재작성을 위해 Redis를 분기할 때 큰 메모리 오버헤드에 대한 패널티를 지불하지 않고 기록 중 복사의 이점을 누리십시오. 그리고 '예'하지 않으면 여기에 표시된 것처럼 귀하(또는 귀하의 사용자)가 높은 대가를 치르게 됩니다.
- Redis의 모든 인스턴스가 작게 유지되므로 클러스터를 쉽게 관리하려면 샤드 마이그레이션, 리샤딩, 확장 및 재조정을 빠르게 수행하세요.
가로로 확장하는 것이 가장 중요합니다.
수평적 확장으로 인메모리 데이터스토어를 실행할 수 있는 유연성은 매우 중요합니다. 다음은 몇 가지 이유입니다.
- 탄력성 향상 – 클러스터에서 더 많은 노드를 사용할수록 클러스터가 더 강력해집니다. 예를 들어 3노드 클러스터에서 데이터세트를 실행하고 한 노드가 성능이 저하되면 클러스터의 1/3이 성능이 저하됩니다. 그러나 9노드 클러스터에서 데이터 세트를 실행하고 한 노드가 성능이 저하되면 클러스터의 1/9에 불과합니다.
- 간편한 확장 – 더 큰 노드를 가져와 전체 데이터 세트에 복사해야 하는 수직 확장보다 클러스터에 노드를 추가하고 데이터 세트의 일부만 마이그레이션하는 것이 훨씬 쉽습니다. 이 잠재적으로 긴 프로세스의 중간에 발생할 수 있습니다…)
- 점진적으로 확장하는 것이 훨씬 더 비용 효율적입니다. – 특히 클라우드에서 수직으로 확장하는 것은 비용이 많이 듭니다. 많은 경우 데이터 세트에 몇 GB만 추가하면 되더라도 인스턴스 크기를 두 배로 늘려야 합니다.
- 높은 처리량 – Redis에서는 매우 높은 네트워크 대역폭 및/또는 높은 PPS(Packet Per Second) 요구로 소규모 데이터 세트에서 높은 처리량 워크로드를 실행하는 많은 고객을 봅니다. 1백만 개 이상의 작업/초 사용 사례가 있는 1GB 데이터 세트를 생각해 보십시오. 3노드 c6gn.xlarge 클러스터(8GB, 4 CPU 최대 25Gbps, 각각 $0.1786/hr) 대신 단일 노드 c6gn.16xlarge 클러스터(128GB, 64개 CPU 및 100Gbps, 시간당 $2.7684)에서 실행하는 것이 합리적입니까? ) 비용의 20% 미만으로 훨씬 더 강력한 방식으로? 비용 효율성을 유지하고 복원력을 향상시키면서 처리량을 늘릴 수 있다는 것은 이 질문에 대한 쉬운 대답처럼 보입니다.
- NUMA의 현실 – 수직 확장은 다중 코어와 대용량 DRAM이 있는 2소켓 서버를 실행하는 것을 의미합니다. 이 NUMA 기반 아키텍처는 더 작은 노드의 네트워크처럼 작동하므로 Redis와 같은 다중 처리 아키텍처에 적합합니다. 그러나 NUMA는 다중 스레드 아키텍처의 경우 더 어렵습니다. 다른 다중 스레드 프로젝트에 대한 경험에 따르면 NUMA는 메모리 내 데이터 저장소의 성능을 최대 80%까지 줄일 수 있습니다.
- 스토리지 처리량 제한 – AWS EBS와 같은 외부 디스크는 메모리 및 CPU만큼 빠르게 확장되지 않습니다. 실제로 사용 중인 머신 클래스에 따라 클라우드 서비스 공급자가 부과하는 스토리지 처리량 제한이 있습니다. 따라서 이미 설명한 문제를 피하고 높은 데이터 지속성 요구 사항을 충족하기 위해 클러스터를 효과적으로 확장하는 유일한 방법은 수평적 확장, 즉 더 많은 노드와 네트워크 연결 디스크를 추가하는 것입니다.
- 임시 디스크 – 임시 디스크는 SSD에서 Redis를 실행하고(SSD가 DRAM 교체로 사용되지만 영구 스토리지로 사용되지 않는 경우) Redis 속도를 유지하면서 디스크 기반 데이터베이스의 비용을 즐길 수 있는 훌륭한 방법입니다(방법 참조 Redis on Flash). 다시 말하지만, 임시 디스크가 한계에 도달하면 가장 좋은 방법이며 대부분의 경우 클러스터를 확장하는 유일한 방법은 더 많은 노드와 임시 디스크를 추가하는 것입니다.
- 상품 하드웨어 – 마지막으로 로컬 데이터 센터, 프라이빗 클라우드, 심지어 소규모 에지 데이터 센터에서 실행 중인 많은 온프레미스 고객이 있습니다. 이러한 환경에서는 64GB 이상의 메모리와 8개의 CPU가 있는 시스템을 찾기 어려울 수 있으며, 다시 한 번 확장할 수 있는 유일한 방법은 수평적입니다.
요약
멀티스레드 프로젝트의 새로운 물결이 제공하는 커뮤니티의 신선하고 흥미로운 아이디어와 기술에 감사드립니다. 이러한 개념 중 일부는 미래에 Redis에 적용될 수도 있습니다(예:이미 조사하기 시작한 io_uring, 보다 현대적인 사전, 보다 전술적인 스레드 사용 등). 그러나 가까운 장래에 Redis가 제공하는 비공유, 다중 프로세스 아키텍처의 기본 원칙을 포기하지 않을 것입니다. 이 설계는 최고의 성능, 확장성 및 복원력을 제공하는 동시에 인메모리, 실시간 데이터 플랫폼에 필요한 다양한 배포 아키텍처를 지원합니다.
부록 Redis 7.0 대 Dragonfly 벤치마크 세부정보
벤치마크 요약
버전:
- Redis 7.0.0을 사용하고 소스에서 빌드했습니다.
- Dragonfly는 https://github.com/Dragonfly/dragonfly#building-from-source에서 권장하는 대로 6월 3일(hash=e806e6ccd8c79e002f721a1a5ecb847bd7a06489) 소스에서 빌드되었습니다.
목표:
- Dragonfly 결과가 재현 가능한지 확인하고 검색된 전체 조건을 확인합니다(memtier_benchmark, OS 버전 등에 일부 구성이 누락된 경우) 여기에서 자세한 내용을 참조하세요.
- Dragonfly의 벤치마크와 일치하여 AWS c6gn.16xlarge 인스턴스에서 달성 가능한 최상의 OSS Redis 7.0.0 클러스터 성능 결정
클라이언트 구성:
- OSS Redis 7.0 솔루션은 각 memtier_benchmark 에 따라 Redis 클러스터에 더 많은 수의 개방형 연결이 필요했습니다. 스레드가 모든 샤드에 연결됨
- OSS Redis 7.0 솔루션은 두 개의 memtier_benchmark 벤치마크를 실행하지만 Dragonfly 벤치마크와 일치하도록 동일한 클라이언트 VM에서 프로세스)
리소스 활용 및 최적 구성:
- OSS Redis 클러스터는 40개의 기본 샤드로 최상의 결과를 얻었으며, 이는 VM에 24개의 예비 vCPU가 있음을 의미합니다. 머신이 완전히 활용되지는 않았지만 샤드 수를 늘리는 것이 도움이 되지 않고 오히려 전반적인 성능이 저하된다는 것을 발견했습니다. 이 동작을 계속 조사하고 있습니다.
- 반면, Dragonfly 솔루션은 64개의 VCPU가 모두 사용률 100%에 도달하여 VM을 완전히 채웠습니다.
- 두 솔루션 모두 최상의 결과를 얻기 위해 클라이언트 구성을 다양화했습니다. 아래에서 볼 수 있듯이 Dragonfly 데이터의 대부분을 복제하고 30개 파이프라인에 대한 최상의 결과를 능가하기도 했습니다.
- 이는 Redis로 달성한 수치를 더욱 높일 수 있는 가능성이 있음을 의미합니다.
마지막으로 Redis와 Dragonfly 모두 네트워크 PPS 또는 대역폭에 의해 제한되지 않는다는 것을 발견했습니다. 사용된 2개의 VM(클라이언트 및 서버, c6gn.16xlarge를 사용하는 봇) 사이에서> 10M PPS에 도달할 수 있고 ~300B 페이로드가 있는 TCP의 경우>30Gbps.
결과 분석
- GET 파이프라인 1 sub-ms :
- OSS Redis:4.43M ops/sec, 여기서 avg와 p50은 모두 밀리초 미만의 지연 시간을 달성했습니다. 평균 클라이언트 지연 시간은 0.383ms였습니다.
- Dragonfly는 초당 4백만 작업을 주장했습니다.
- 평균 클라이언트 지연 시간이 0.390ms인 380만 작업/초를 재현했습니다.
- Redis 대 Dragonfly – Redis 처리량이 10% 더 큽니다. 대 Dragonfly 주장 결과 및 18% 대 Dragonfly 결과를 재현할 수 있었습니다.
- GET 파이프라인 30:
- OSS Redis:평균 클라이언트 지연 시간이 2.239ms인 초당 2290만 작업
- Dragonfly는 초당 1,500만 작업을 주장했습니다.
- 평균 클라이언트 지연 시간이 3.99ms인 초당 1,590만 작업을 재현했습니다.
- Redis 대 Dragonfly – Redis가 43% 더 우수합니다. (vs Dragonfly 재현 결과) 및 52% (vs Dragonfly 주장 결과)
- SET 파이프라인 1 sub-ms :
- OSS Redis:4.74M ops/sec, 여기서 avg 및 p50 모두 밀리초 미만의 지연 시간을 달성했습니다. 평균 클라이언트 지연 시간은 0.391ms입니다.
- Dragonfly는 초당 4백만 작업을 주장했습니다.
- 평균 클라이언트 지연 시간이 0.500ms인 초당 400만 작업을 재현했습니다.
- Redis 대 Dragonfly – Redis가 19% 더 우수합니다. (Dragonfly가 주장한 것과 동일한 결과를 재현했습니다)
- SET 파이프라인 30:
- OSS Redis:1985만 작업/초, 평균 클라이언트 지연 시간 2.879ms
- Dragonfly는 초당 1000만 작업을 주장했습니다.
- 평균 클라이언트 지연 시간이 4.203ms인 초당 1,400만 작업을 재현했습니다.
- Redis 대 Dragonfly – Redis가 42% 더 우수합니다. (vs Dragonfly 재현 결과) 및 99% (vs Dragonfly 주장 결과)
memtier_benchmark 각 변형에 사용되는 명령:
- GET 파이프라인 1 sub-ms
- 레디스:
- 2X:memtier_benchmark –ratio 0:1 -t 24 -c 1 –test-time 180 –distinct-client-seed -d 256 –cluster-mode -s 10.3.1.88 –port 30001 –key-maximum 1000000 –hide -히스토그램
- 잠자리:
- memtier_benchmark –ratio 0:1 -t 55 -c 30 -n 200000 –distinct-client-seed -d 256 -s 10.3.1.6 –key-maximum 1000000 –hide-histogram
- 레디스:
- GET 파이프라인 30
- 레디스:
- 2X:memtier_benchmark –ratio 0:1 -t 24 -c 1 –test-time 180 –distinct-client-seed -d 256 –cluster-mode -s 10.3.1.88 –port 30001 –key-maximum 1000000 –hide -히스토그램 – 파이프라인 30
- 잠자리:
- memtier_benchmark –ratio 0:1 -t 55 -c 30 -n 200000 –distinct-client-seed -d 256 -s 10.3.1.6 –key-maximum 1000000 –hide-histogram –pipeline 30
- memtier_benchmark –ratio 0:1 -t 55 -c 30 -n 200000 –distinct-client-seed -d 256 -s 10.3.1.6 –key-maximum 1000000 –hide-histogram –pipeline 30
- 레디스:
- SET 파이프라인 1 sub-ms
- 레디스:
- 2X:memtier_benchmark –ratio 1:0 -t 24 -c 1 –test-time 180 –distinct-client-seed -d 256 –cluster-mode -s 10.3.1.88 –port 30001 –key-maximum 1000000 –hide -히스토그램
- 잠자리:
- memtier_benchmark –ratio 1:0 -t 55 -c 30 -n 200000 –distinct-client-seed -d 256 -s 10.3.1.6 –key-maximum 1000000 –hide-histogram
- memtier_benchmark –ratio 1:0 -t 55 -c 30 -n 200000 –distinct-client-seed -d 256 -s 10.3.1.6 –key-maximum 1000000 –hide-histogram
- 레디스:
- SET 파이프라인 30
- 레디스:
- 2X:memtier_benchmark –ratio 1:0 -t 24 -c 1 –test-time 180 –distinct-client-seed -d 256 –cluster-mode -s 10.3.1.88 –port 30001 –key-maximum 1000000 –hide -히스토그램 – 파이프라인 30
- 잠자리:
- memtier_benchmark –ratio 1:0 -t 55 -c 30 -n 200000 –distinct-client-seed -d 256 -s 10.3.1.6 –key-maximum 1000000 –hide-histogram –pipeline 30
- 레디스:
인프라 세부정보
클라이언트(memtier_benchmark 실행용)와 서버(Redis 및 Dragonfly 실행용) 모두에 동일한 VM 유형을 사용했습니다. 사양은 다음과 같습니다.
- VM :
- AWS c6gn.16xlarge
- aarch64
- ARM 네오버스-N1
- 소켓당 코어:64
- 코어당 스레드:1
- NUMA 노드:1
- AWS c6gn.16xlarge
- 커널:Arm64 커널 5.10
- 설치된 메모리: 126GB