소개
대부분 아시다시피, Couchbase는 데이터 상태가 특정 기준이나 보증을 충족하도록 사용자에게 다양한 일관성 및 내결함성 옵션을 제공하는 데이터베이스입니다. 사용자는 다양한 수준의 복제, 지속성, 복제본, 서버 그룹 등을 지정하여 특정 장애 시나리오 및 클러스터 작업에서 데이터의 내구성과 일관성, 정확성을 보장할 수 있습니다. 곧 출시될 6.5.0 릴리즈에서는 다음과 같은 새로운 기능이 향상됩니다. 내구성 레벨은 장애 발생 시 사용자에게 더 많은 안전과 보장을 제공합니다. 보증은 증명된 만큼만 유효하다는 것을 잘 알고 있으므로, 이번 글에서는 업계 표준인 Jespen을 사용하여 Couchbase에서 데이터베이스 내구성을 테스트하는 방법에 대해 자세히 살펴보겠습니다.
Jepsen 프레임워크는 클러스터에서 클라이언트 작업을 실행하는 동시에 네트워크 파티션, 프로세스 종료, 디스크 속도 저하 등과 같은 일종의 혼란을 유발하는 방식으로 작동합니다. 그런 다음 Jepsen은 기본 제공 또는 사용자 지정 작업 이력 검사기를 사용하여 작업 이력을 분석합니다. 가장 주목할 만한 점은 Jepsen은 선형화 가능한 일관성 검사기. 6.5.0에서 새롭게 향상된 내구성 수준을 갖춘 Couchbase는 다음과 같이 주장합니다. 순차적 일관성. 그러나 선형화 가능한 일관성은 순차적 일관성을 의미합니다[1]. 따라서 선형화 가능한 일관성 검사기를 통과했다는 것은 작업 기록이 실제로 순차적으로 일관성이 있다는 것을 의미합니다. 그러나 선형화 가능한 일관성 검사에 실패했다고 해서 작업 기록이 순차적으로 일관되지 않다는 것을 의미하지는 않습니다. 요약하자면, 작업이 선형화 가능 일관성 검사기를 통과하면 Couchbase가 순차적으로 일관성이 있다고 가정할 수 있습니다. 작업이 선형화 가능 일관성 검사기를 통과하지 못하면 Couchbase가 여전히 순차적으로 일관적일 수 있지만, 이를 확인하려면 추가 조사가 필요합니다.
Jepsen의 목표는 Java SDK 클라이언트와 서버 측 KV 엔진이 함께 작동하는지를 다양한 각도에서 테스트하는 것입니다: 1.) 승인된 쓰기가 손실되지 않도록 하고, 2.) 클러스터 운영 및 장애가 시스템에 적용되는 동안 최소한 순차적 일관성 모델을 제공하는 것입니다.
아키텍처
Jepsen은 다음과 같은 추상화를 위한 인터페이스를 제공합니다: 데이터베이스, 클라이언트, 검사기, 네메시스, 생성기 및 워크로드. Jepsen 테스트를 생성하려면 이 모든 것을 Couchbase에 맞게 구현해야 했습니다. 각 테스트는 이러한 추상화와 추가 매개변수의 조합입니다.
데이터베이스
Couchbase 클러스터에 대한 설정, 해체 및 로그 수집 로직을 구현했습니다. 이 로직에는 사용자 정의 버킷 설정, 서버 그룹 및 자동 장애 조치에 대한 지원이 포함됩니다. 가능한 모든 버킷과 클러스터 설정을 완벽하게 지원하는 것은 가능한 클러스터의 수로 인해 모든 퍼머테이션을 테스트하는 것이 불가능하기 때문에 큰 의미가 없습니다. 하지만 가장 중요한 모든 클러스터 구성과 옵션에 대한 지원을 구축했습니다.
클라이언트
저희는 "등록" 클라이언트와 "설정" 클라이언트라는 두 가지 다른 클라이언트를 구현했습니다. 등록 클라이언트는 Couchbase 버킷의 독립된 키에서 값을 쓰고, 읽고, 비교 및 스왑합니다. 설정 클라이언트는 버킷에서 문서만 추가하고 삭제합니다. 버킷을 집합으로, 문서를 해당 집합의 멤버로 생각하면 됩니다. 저희는 문서를 업데이트하지 않기 때문에 선형화 가능성 검사기 대신 사용자 지정 집합 검사기와 함께 이 클라이언트를 사용합니다. 집합 클라이언트와 집합 검사기를 사용하는 테스트는 모두 버킷에 문서를 추가하거나 버킷에서 문서를 삭제하는 단계를 엮어서 작동합니다.
두 클라이언트 모두 제너레이터 프로세스에서 작업을 수신합니다. (자세한 내용은 나중에 설명합니다.)
클라이언트 오류를 처리할 때는 특별한 주의를 기울여야 합니다. 예를 들어, 내구성이 불가능한 예외와 요청 시간 초과 예외는 Jepsen에서 다르게 처리해야 합니다. 전자의 경우 작업이 실패했다는 것을 알 수 있지만 후자의 경우 작업이 성공했을 수도 있습니다. 연산이 실패했는지 성공했는지 구분할 수 없는 경우, Jepsen의 선형성 검사기는 연산이 실패했다고 가정하고 다시 연산이 통과했다고 가정하여 검사를 실행합니다. 그 결과 모호한 각 연산에 대해 대략적으로 두 번 검사하는 효과가 있습니다. 따라서 이러한 작업 결과의 잠재적 수를 제한하는 테스트 시나리오가 필요합니다. 선형화 가능성 검사기는 두 가지 가능한 히스토리 중 하나 이상이 선형화 가능한 경우 통과합니다.
검사기
테스트에는 선형화 가능성 검사기, 세트 검사기, 건전성 검사기 등 세 가지 검사기 중에서 선택할 수 있습니다. 선형화 가능성 검사기는 Jepsen과 함께 제공되며 버킷에 있는 독립 키의 일관성을 검사하는 데 사용됩니다. 세트 검사기를 구현하여 세트 클라이언트를 사용한 테스트가 버킷에 올바른 문서 세트를 가지고 있는지 확인했습니다. 마지막으로, 테스트 자체가 클러스터 상태 변경 시퀀스를 오류 없이 진행했는지 확인하는 건전성 검사기를 구현했습니다. 예를 들어, 테스트가 실패해서는 안 되는 리밸런싱을 포함할 수 있습니다. 이 경우, 설정 검사기 또는 선형성 검사기에 실패한 테스트를 실패한 것으로 표시하기 때문에 건전성 검사기는 테스트를 "실패" 대신 "알 수 없음"으로 표시합니다. 또한 정상 상태 검사기는 적어도 일부 작업이 성공했는지 확인합니다.
네메시스
전통적으로 Jepsen에서 네메시스는 제너레이터 프로세스로부터 작업을 공급받은 후 그에 따라 시스템에 대한 조치를 취하는 프로세스입니다. 예를 들어, 내장된 파티션 네메시스는 네트워크를 파티션하고 두 노드 간에 네트워크를 복원하는 블록 및 복원 작업을 수신할 수 있습니다. 대부분의 기본 제공 네미스는 매우 기본적인 시나리오에 충분하지만, 예를 들어 임의의 서버 그룹에서 임의의 디스크를 느리게 하고 동일한 서버의 멤캐시 프로세스를 종료한 다음 디스크를 복원할 수 있는 추가 시나리오를 테스트하고 싶었습니다.
원하는 모든 시나리오를 테스트하기 위해 초기 상태의 상태 변화를 통해 Couchbase 클러스터를 모델링하는 단일 Couchbase 네메시스를 만들었습니다. 노드와 해당 노드의 네트워크, 서버, 디스크 및 클러스터 상태 맵을 유지합니다. 작업이 발생할 때마다 시스템의 변경 사항을 반영하도록 상태가 업데이트됩니다. 네메시스에 전달된 작업은 노드 타겟팅 옵션, 작업 및 작업 매개변수를 지정합니다. 예를 들어 노드 타겟팅 옵션은 임의의 서버 그룹에 있는 모든 정상 노드 중에서 크기가 2인 임의의 노드 하위 집합을 타겟팅하도록 네메시스에 지시합니다. 이것이 바로 노드 상태를 추적하는 주된 이유이며, 이를 통해 네메시스가 조치를 취할 수 있는 방법을 보다 유연하게 결정할 수 있습니다.
네메시스는 다음과 같은 작업을 지원합니다: 장애 조치(정상 및 하드), 복구(전체 및 델타), 사용자 지정 네트워크 파티셔닝, 네트워크 복구, 자동 장애 조치 대기, 노드 집합에서 리밸런싱, 노드 집합의 리밸런싱, 두 노드 집합의 스왑 리밸런싱, 리밸런싱 실패, 프로세스 죽이기(memcached, 베이비시터, ns_서버) 종료, 노드 집합에서 동일한 프로세스 재시작, dcp 클라이언트 속도 저하, dcp 클라이언트 재설정, 압축 트리거, 노드 집합의 디스크 실패, 노드 집합의 디스크 속도 저하, 노드 집합의 디스크 복구 등입니다. 앞으로 더 많은 네메시스 작업을 지원할 계획입니다.
발전기
젭슨 테스트의 또 다른 핵심 요소는 클라이언트 및 네메시스 연산을 위한 제너레이터입니다. 이러한 제너레이터는 유한 또는 무한한 연산 시퀀스를 생성합니다. 각 테스트에는 고유한 네메시스 제너레이터가 있지만 대부분의 경우 공통 클라이언트 제너레이터를 공유합니다. 예를 들어, 네메시스 제너레이터는 파티션, 절전, 복원의 시퀀스를 무한히 반복하는 것일 수 있습니다. 클라이언트 생성기는 클라이언트 작업의 임의의 무한한 시퀀스와 내구성 수준, 문서 키, 새로 쓸 값 또는 CAS 등과 같은 관련 매개 변수를 지정합니다. 테스트가 시작되면 클라이언트 생성기는 클라이언트 작업을 클라이언트에게, 네메시스 생성기는 네메시스에게 작업을 공급합니다. 테스트는 네메시스 생성기가 지정된 횟수의 작업을 완료하거나 시간 제한에 도달하거나 오류가 발생할 때까지 계속됩니다.
워크로드
젭슨 워크로드는 이전의 모든 구성 요소를 추가 매개변수와 함께 단일 테스트로 묶는 맵입니다. 젭센의 워크로드는 서버 그룹 활성화 및 자동 장애 조치와 같은 입력 매개변수를 기반으로 네메시스 및 클라이언트 생성기 로직을 수정합니다.
도전 과제
이 테스트를 구축하는 동안 직면한 두 가지 주요 과제는 리소스 제약으로 인해 발생했습니다: 1.) 클러스터 설정 순열의 수가 많다는 점과 2.) 선형화 가능성 검사기를 실행하는 데 필요한 시간입니다.
Couchbase는 복잡하고 사용자 정의가 가능한 데이터 플랫폼이므로 조정할 수 있는 설정이 수백 가지에 이릅니다. 일부 설정은 이진(예: 자동 장애 조치 활성화)인 반면, 다른 설정은 연속(KV에 대한 RAM 할당량)입니다. 따라서 테스트할 수 있는 초기 클러스터 상태가 매우 많이 생성됩니다. 그리고 거의 무한대에 가까운 방법으로 네메시스 작업을 구성할 수 있기 때문에 테스트 공간이 너무 커서 완전히 커버할 수 없습니다.
선형화 가능성 검사기는 매우 유용하고 훌륭한 연구의 산물이지만 몇 가지 한계가 있습니다. 검사기가 기록을 분석하는 데 걸리는 시간은 연산 횟수에 따라 기하급수적으로 증가합니다. 게다가 모호한 연산도 기하급수적으로 증가합니다. 따라서 테스트 기간 동안 클라이언트를 최대한 밀어붙이고 싶지만 클라이언트를 너무 세게 밀어붙이면 검사기의 메모리가 부족해져 히스토리 분석에 실패할 수 있다는 문제가 있습니다. 이는 또한 테스트가 최대한 빨리 실행되기를 원하지만 버그를 발견할 수 있는 표면적이 줄어든다는 것을 의미합니다.
솔루션
이러한 문제를 해결하기 위해 고객에게 가장 중요한 테스트 매개변수의 하위 집합에 집중하고, 테스트를 가능한 한 짧게 유지하며, 테스트를 가능한 한 자주 실행하기로 결정했습니다. 버킷 복제본, 새롭게 향상된 모든 내구성 수준, 자동 장애 조치 등과 같은 일반적인 매개변수만 테스트함으로써 내구성 보증을 입증하기 위한 견고한 기반이 될 관리 가능한 테스트 세트에 집중할 수 있습니다.
새로운 기능이 추가되고 고객의 요청에 따라 새로운 서비스 및 구성(쿼리, 인덱스, xdcr 등)을 추가할 계획으로 먼저 중요한 KV 구성에 중점을 두었습니다. 그 다음에는 절전 시간 단축, 운영 상태 폴링, 운영 횟수 제한, 문서 사전 로드 제로화 등을 통해 최대한 빠르게 작동하도록 네메시스를 조정했습니다. 테스트를 시작할 때 버킷을 비워두면 테스트 중 후속 재조정 속도가 빨라집니다. 하지만 버킷에 많은 양의 데이터가 있고 버킷당 RAM 용량이 상대적으로 적은 시나리오를 테스트해야 합니다. 현재 작업 중인 이러한 고밀도 데이터 시나리오는 실행하는 데 훨씬 더 많은 시간이 소요될 것입니다. 리밸런싱 작업이 선형성 검사기의 메모리 부족을 유발하지 않을 만큼 충분히 빠를 수 있도록 초기 데이터 로드 크기를 조정해야 합니다. 또한 클라이언트 작업의 속도 제한으로 인해 테스트를 여러 번 실행해야 합니다. 클라이언트 작업 속도가 느리면 두 작업이 겹치거나 버그가 발생할 확률이 줄어들지만 테스트를 여러 번 실행하면 겹치는 작업의 총 수를 늘려서 버그를 발견할 수 있습니다.
테스트를 최대한 자주 실행하기 위해 테스트 세트의 계층 구조를 만들었습니다. 테스트 스위트는 정상, 일일, 주간, 전체 등 네 가지 범주로 나뉩니다. 정상 테스트 스위트는 새 커밋이 들어온 후 실행해야 하는 테스트의 작은 하위 집합으로, 완료하는 데 1시간 미만이 걸립니다. 대규모 일일 테스트 스위트는 실행하는 데 12시간을 넘지 않아야 하며 주간 테스트 스위트는 이틀 이내에 완료해야 합니다. 전체 테스트 스위트는 모든 테스트의 목록이며 완료하는 데 약 1주일이 걸립니다. 테스트 스위트를 만들려면 커버리지를 최대로 유지하면서 유사한 테스트를 제거하여 전체 테스트 스위트를 줄입니다. 현재 전체 테스트 스위트는 612개, 주간 테스트는 396개, 일일 테스트는 227개, 정상 테스트는 6개입니다. 또한 이전 릴리스(4.6.x, 5.0.x, 5.5.x, 6.0.x)의 버그가 더 이상 제품에 존재하지 않는지 확인하는 데 사용하는 버그 모음도 있습니다. 이러한 유형의 버그의 예는 다음과 같습니다. MB-29369 그리고 MB-29480.
결과
젭슨 테스트를 통해 Couchbase 내에서 여러 버그를 발견하는 데 성공했습니다. 이러한 버그는 일반적인 제품 버그와 데이터 내구성 및 일관성 버그의 두 가지 범주에 속합니다. 내구성과 일관성 버그는 우리가 젭센 테스트를 시작한 이유이므로 일반적인 제품 버그를 잡아내는 전체 기능 회귀 제품군을 보유하고 있기 때문에 더 중요하다고 생각합니다. 저희가 발견한 내구성 및 일관성 버그의 몇 가지 예는 다음과 같습니다. MB-35135, MB-35060및 MB-35053.
초기 Jepsen 작업과 이를 통해 발견한 버그를 통해 다양한 장애 시나리오와 클러스터 운영에서 데이터를 안전하게 보호하는 Couchbase의 기능에 대한 신뢰가 높아졌습니다. 그러나 Jepsen은 수백 번 실행한 후에도 버그를 발견할 수 있으므로 지속적인 테스트가 필요합니다. 저희는 매일 및 매주 Jepsen 테스트를 계속 실행하는 동시에 더 많은 시나리오에 대한 지원을 구축해 나갈 것입니다. 데이터 일관성과 내구성이 보장되는 시스템을 구축할 때 Jepsen은 없어서는 안 될 도구이며, 앞으로도 지속적으로 활용하고 그 기능을 확장해 나갈 것입니다.
링크:
[1] http://courses.csail.mit.edu/6.852/01/papers/p91-attiya.pdf
[3] https://jepsen.io/consistency/models/linearizable
[4] https://jepsen.io/consistency/models/sequential
[5] https://github.com/jepsen-io/jepsen
추가 리소스
다운로드
문서
블로그
블로그 Couchbase Server 6.5 GA 발표 - 새로운 기능 및 개선 사항