6.1 약어 전쟁: BASE 대. 산
"화학에서 pH는 수용액의 상대적 산도를 측정합니다. pH 척도는 0(강산성 물질)에서 14(강알칼리성 물질)까지입니다. 25°C의 순수한 물은 pH가 7이며 중성입니다. 데이터 엔지니어는 트랜잭션의 신뢰성과 관련하여 데이터베이스를 비교하기 위해 이 은유를 사용했습니다." 아마도 아이디어는 이것이었을 것입니다. pH가 높을수록, 즉 데이터베이스가 "알카라인"("BASE")에 가까울수록 트랜잭션의 안정성이 떨어집니다. |
MySQL과 같은 대중적인 관계형 데이터베이스는 ACID를 기반으로 등장했습니다. 그러나 지난 10년 동안 이 이름으로 매우 다른 여러 유형의 데이터베이스를 결합한 소위 NoSQL 데이터베이스는 ACID 없이도 꽤 잘 작동했습니다. 실제로 NoSQL 데이터베이스로 작업하고 트랜잭션 및 안정성에 대해 전혀 신경 쓰지 않는 많은 개발자가 있습니다. 그들이 옳은지 보자.
NoSQL 데이터베이스는 좋은 추상화일 뿐이므로 일반적으로 말할 수 없습니다. NoSQL 데이터베이스는 데이터 스토리지 하위 시스템의 디자인과 데이터 모델에서 서로 다릅니다. NoSQL은 문서 지향 CouchDB이자 그래프 Neo4J입니다. 그러나 트랜잭션의 맥락에서 이야기하면 모두 한 가지 점에서 유사한 경향이 있습니다. 제한된 버전의 원자성 및 격리를 제공하므로 ACID 보장을 제공하지 않습니다. 이것이 의미하는 바를 이해하려면 다음 질문에 답해 봅시다. ACID가 아니라면 무엇을 제공합니까? 아무것도 아님?
설마. 결국, 그것들은 관계형 데이터베이스와 마찬가지로 아름다운 패키지로 판매되어야 합니다. 그리고 그들은 그들 자신의 "화학"약어 인 BASE를 생각해 냈습니다.
6.2 길항제로서의 BASE
그리고 여기서 다시 문자 순서대로 가지 않고 기본 용어인 일관성부터 시작하겠습니다. 이 일관성은 ACID의 일관성과 거의 관련이 없기 때문에 귀하의 인식 효과를 평준화해야 합니다. 일관성이라는 용어의 문제점은 너무 많은 맥락에서 사용된다는 것입니다. 그러나 이 일관성은 사용의 훨씬 더 넓은 맥락을 가지고 있으며 실제로 이것은 분산 시스템을 논의할 때 논의되는 일관성입니다.
위에서 언급한 관계형 데이터베이스는 서로 다른 수준의 트랜잭션 격리를 제공하며 가장 엄격한 격리는 한 트랜잭션이 다른 트랜잭션의 잘못된 변경 내용을 볼 수 없도록 합니다. 상점의 계산대에 서 있고 그 순간 임대료가 귀하의 계좌에서 인출되었지만 임대료 이체 거래가 실패하고 귀하의 계좌가 이전 가치로 돌아갑니다 (돈은 인출되지 않음) 결제 시 결제 거래는 모든 사람에게 이러한 제스처를 인식하지 못합니다. 결국 해당 거래는 진행되지 않았으며 거래 격리 요구 사항에 따라 일시적인 변경 사항은 다른 거래에서 알 수 없습니다.
많은 NoSQL 데이터베이스는 격리 보장을 포기하고 "최종 일관성"을 제공하므로 결국 유효한 데이터를 볼 수 있지만 트랜잭션이 유효하지 않은 값(즉, 일시적이거나 부분적으로 업데이트되거나 오래된 값)을 읽을 가능성이 있습니다. 데이터를 읽을 때 "지연" 모드에서 데이터가 일관되게 될 수 있습니다("읽기 시간에 지연").
NoSQL은 실시간 분석을 위한 데이터베이스로 인식되었으며 더 빠른 속도를 달성하기 위해 일관성을 희생했습니다. 그리고 BASE라는 용어를 만든 사람인 Eric Brewer는 소위 "CAP 정리"를 공식화했습니다.
분산 컴퓨팅 구현의 경우 다음 세 가지 속성 중 두 개만 제공할 수 있습니다.
- 데이터 일관성 ( 일관성 ) - 서로 다른 노드(인스턴스)의 데이터가 서로 모순되지 않습니다.
- 가용성 ( 가용성 ) - 분산 시스템에 대한 모든 요청은 올바른 응답으로 끝나지만 모든 시스템 노드의 응답이 동일하다는 보장은 없습니다.
- 파티션 공차 (partition tolerance ) - 노드 간에 연결이 없어도 서로 독립적으로 계속 작동합니다.
CAP에 대한 아주 간단한 설명을 원하시면 여기로 가십시오.
CAP 정리가 작동하지 않으며 일반적으로 너무 추상적으로 공식화된다는 의견이 있습니다. 어떤 식으로든 NoSQL 데이터베이스는 다음과 같은 상황을 설명하는 CAP 정리의 맥락에서 일관성을 거부하는 경우가 많습니다. 데이터가 여러 인스턴스가 있는 클러스터에서 업데이트되었지만 변경 사항이 아직 모든 인스턴스에서 동기화되지 않았습니다. 위의 DynamoDB 예를 언급한 것을 기억하십시오. 변경 사항이 지속 가능해졌습니다. 여기 HTTP 200이 있습니다. 하지만 변경 사항은 10초 후에만 확인되었습니다. 개발자의 일상 생활에서 또 다른 예는 도메인 이름 시스템인 DNS입니다. 모르는 사람이 있다면 이것은 http 주소를 IP 주소로 변환하는 "사전"입니다.
업데이트된 DNS 레코드는 캐싱 간격 설정에 따라 서버에 전파되므로 업데이트가 즉시 눈에 띄지 않습니다. 음, 비슷한 시간적 불일치(즉, 결국 일관성)가 관계형 데이터베이스 클러스터(예: MySQL)에서 발생할 수 있습니다. 결국 이 일관성은 ACID의 일관성과 아무 관련이 없습니다. 따라서 이러한 의미에서 SQL 및 NoSQL 데이터베이스는 클러스터의 여러 인스턴스와 관련하여 크게 다를 가능성이 없다는 점을 이해하는 것이 중요합니다.
또한 end-to-end 일관성은 쓰기 요청이 순서에 맞지 않음을 의미할 수 있습니다. 즉, 모든 데이터가 기록되지만 결국 수신될 값은 쓰기 대기열의 마지막 값이 아닙니다. .
Non-ACID NoSQL 데이터베이스는 엔드투엔드 일관성 모델로 인해 이른바 "소프트 상태"를 갖습니다. 즉, 입력 없이도 시스템 상태가 시간이 지남에 따라 변경될 수 있습니다. 그러나 그러한 시스템은 더 큰 접근성을 제공하기 위해 노력합니다. 100% 가용성을 제공하는 것은 사소한 작업이 아니므로 "기본 가용성"에 대해 이야기하고 있습니다. 그리고 이 세 가지 개념인 "기본적으로 사용 가능", "소프트 상태"("소프트 상태") 및 "최종 일관성"이 약어 BASE를 형성합니다.
솔직히 말해서 BASE의 개념은 ACID보다 더 빈 마케팅 래퍼 인 것 같습니다. 새로운 것을 제공하지 않고 어떤 식 으로든 데이터베이스를 특성화하지 않기 때문입니다. 그리고 특정 데이터베이스에 레이블(ACID, BASE, CAP)을 부착하면 개발자를 혼란스럽게 할 수 있습니다. 어차피 이 용어를 소개하기로 한 이유는 데이터베이스를 공부할 때 우회하기 어렵기 때문입니다. 하지만 이제 그것이 무엇인지 알았으니 가능한 한 빨리 잊으셨으면 합니다. 그리고 고립의 개념으로 돌아가 봅시다.
6.3 그렇다면 BASE 데이터베이스는 ACID 기준을 전혀 충족하지 않습니까?
기본적으로 ACID 데이터베이스가 비 ACID와 다른 점은 비 ACID가 실제로 격리를 포기한다는 것입니다. 이것은 이해하는 것이 중요합니다. 그러나 데이터베이스 문서를 읽고 Hermitage 프로젝트의 사람들이 하는 방식으로 테스트하는 것이 훨씬 더 중요합니다. 이 데이터베이스 또는 해당 데이터베이스의 작성자가 ACID 또는 BASE, CAP 또는 CAP가 아닌 아이디어를 정확히 어떻게 부르는지는 그다지 중요하지 않습니다. 중요한 것은 정확히 이 데이터베이스나 저 데이터베이스가 제공하는 것입니다.
데이터베이스 작성자가 ACID 보증을 제공한다고 주장하는 경우 이에 대한 이유가 있을 수 있지만 이것이 사실인지, 어느 정도인지 이해하기 위해 직접 테스트하는 것이 좋습니다. 데이터베이스가 그러한 보증을 제공하지 않는다고 선언하는 경우 이는 다음을 의미할 수 있습니다.
-
DB는 원자성을 보장하지 않습니다. 일부 NoSQL 데이터베이스는 원자적 작업을 위한 별도의 API를 제공하지만(예: DynamoDB);
- DB는 격리 보장을 제공하지 않습니다. 예를 들어, 이는 데이터베이스가 작성된 순서대로 데이터를 쓰지 않음을 의미할 수 있습니다.
내구성 보장과 관련하여 많은 데이터베이스가 성능을 위해 이 점을 절충합니다. 디스크에 쓰는 것은 너무 긴 작업이며 이 문제를 해결하는 방법에는 여러 가지가 있습니다. 나는 데이터베이스 이론에 대해 많이 다루고 싶지는 않지만, 어떤 방식으로 봐야 하는지 대략적으로 이해할 수 있도록 다양한 데이터베이스가 내구성 문제를 해결하는 방법을 일반적인 용어로 설명하겠습니다.
다른 데이터베이스를 비교하려면 무엇보다도 특정 데이터베이스의 데이터 저장 및 검색 하위 시스템의 기반이 되는 데이터 구조를 알아야 합니다. 요컨대, 데이터베이스마다 인덱싱 구현이 다릅니다. 즉, 데이터에 대한 액세스를 구성하는 것입니다. 그들 중 일부는 데이터를 더 빨리 쓸 수 있고 다른 일부는 더 빨리 읽을 수 있습니다. 그러나 일반적으로 일부 데이터 구조가 내구성을 높이거나 낮춘다고 말할 수는 없습니다.
6.4 서로 다른 데이터베이스가 데이터를 인덱싱하는 방법과 이것이 내구성에 미치는 영향 등
데이터 저장 및 검색에는 두 가지 주요 접근 방식이 있습니다.
데이터를 저장하는 가장 쉬운 방법은 로그와 같은 방식으로 파일 끝에 작업을 추가하는 것입니다(즉, 추가 작업이 항상 발생함). CRUD 작업은 단순히 로그에 기록됩니다. 로그 검색은 비효율적이며 데이터가 저장된 정확한 위치에 대한 메타데이터를 저장하는 특별한 데이터 구조인 인덱스가 들어오는 곳입니다. 로그에 대한 가장 간단한 인덱싱 전략은 키와 값을 추적하는 해시 맵입니다. 값은 로그(로그)이며 디스크에 저장되는 파일 내부에 기록된 데이터에 대한 바이트 오프셋에 대한 참조가 됩니다. 이 데이터 구조는 전적으로 메모리에 저장되는 반면 데이터 자체는 디스크에 있으며 LSM 트리(로그 구조 병합)라고 합니다.
당신은 아마도 궁금했을 것입니다. 우리가 항상 저널에 작업을 기록하면 엄청나게 커질까요? 예, 따라서 일부 주기성으로 데이터를 "정리"하는 압축 기술이 발명되었습니다. 즉, 각 키에 대해 가장 관련성이 높은 값만 남기거나 삭제합니다. 그리고 디스크에 하나 이상의 로그가 있고 모두 정렬된 경우 SSTable("정렬된 문자열 테이블")이라는 새로운 데이터 구조를 얻게 되며 이는 의심할 여지없이 성능을 향상시킬 것입니다. 메모리에서 정렬하려는 경우 소위 MemTable이라는 유사한 구조를 얻게 되지만 문제는 치명적인 데이터베이스 충돌이 발생하면 마지막으로 기록된 데이터(MemTable에 있지만 아직 기록되지 않음)입니다. 디스크)가 손실됩니다. 실제로,
인덱싱에 대한 또 다른 접근 방식은 B-트리("B-트리")를 기반으로 합니다. B-트리에서 데이터는 고정 크기 페이지로 디스크에 기록됩니다. 이러한 데이터 블록은 크기가 약 4KB인 경우가 많으며 키별로 정렬된 키-값 쌍이 있습니다. 하나의 B-트리 노드는 페이지 범위에 대한 링크가 있는 배열과 같습니다. 최대 배열의 링크 수를 분기 요인이라고 합니다. 각 페이지 범위는 다른 페이지 범위에 대한 링크가 있는 또 다른 B-트리 노드입니다.
결국 시트 수준에서 개별 페이지를 찾을 수 있습니다. 이 아이디어는 이러한 페이지 참조가 메모리가 아닌 디스크에 저장된다는 점을 제외하면 저수준 프로그래밍 언어의 포인터와 유사합니다. 데이터베이스에서 INSERT 및 DELETE가 발생하면 일부 노드가 분기 요소와 일치하도록 두 개의 하위 트리로 분할될 수 있습니다. 프로세스 중간에 어떤 이유로든 데이터베이스에 오류가 발생하면 데이터 무결성이 손상될 수 있습니다. 이를 방지하기 위해 B-트리를 사용하는 데이터베이스는 모든 단일 트랜잭션이 기록되는 "미리 쓰기 로그" 또는 WAL을 유지합니다. 이 WAL은 손상된 경우 B-트리의 상태를 복원하는 데 사용됩니다. 그리고 이것이 내구성 측면에서 B-트리를 사용하는 데이터베이스를 더 좋게 만드는 것 같습니다. 그러나 LSM 기반 데이터베이스는 기본적으로 WAL과 동일한 기능을 수행하는 파일을 유지할 수도 있습니다. 따라서 이미 말한 내용을 한 번 이상 반복하겠습니다. 선택한 데이터베이스의 작동 메커니즘을 이해하십시오.
그러나 B-트리에 대해 확실한 점은 트랜잭션에 적합하다는 것입니다. 각 키는 인덱스의 한 위치에서만 발생하는 반면 저널 스토리지 하위 시스템은 서로 다른 샤드에 동일한 키의 여러 복사본을 가질 수 있습니다(예: 다음 압축이 수행됩니다).
그러나 인덱스의 디자인은 데이터베이스의 성능에 직접적인 영향을 미칩니다. LSM 트리를 사용하면 디스크에 대한 쓰기가 순차적이며 B-트리는 다중 임의 디스크 액세스를 유발하므로 B-트리보다 LSM에서 쓰기 작업이 더 빠릅니다. 이 차이는 순차 쓰기가 임의 쓰기보다 훨씬 빠른 자기 하드 디스크 드라이브(HDD)에서 특히 중요합니다. 서로 다른 압축 단계에 있는 여러 데이터 구조와 SS 테이블을 살펴봐야 하기 때문에 LSM 트리에서는 읽기 속도가 느립니다. 자세히 보면 이렇게 생겼습니다. LSM으로 간단한 데이터베이스 쿼리를 만들면 먼저 MemTable에서 키를 찾습니다. 거기에 없으면 가장 최근의 SSTable을 살펴봅니다. 거기에 없으면 마지막에서 두 번째 SSTable 등을 봅니다. 요청된 키가 존재하지 않으면 LSM을 사용하여 이를 마지막으로 알 수 있습니다. LSM 트리는 예를 들어 LevelDB, RocksDB, Cassandra 및 HBase에서 사용됩니다.
데이터베이스를 선택할 때 여러 가지 사항을 고려해야 한다는 것을 이해할 수 있도록 모든 것을 자세히 설명합니다. 예를 들어 데이터를 더 많이 쓰거나 읽을 것으로 예상합니까? 그리고 데이터 모델의 차이점에 대해서는 아직 언급하지 않았습니다(그래프 모델이 허용하는 대로 데이터를 탐색해야 합니까? 데이터의 서로 다른 단위 간에 관계가 전혀 있습니까? 그러면 관계형 데이터베이스가 구출될 것입니까?). 및 2가지 유형의 데이터 스키마 - 쓰기(많은 NoSQL에서와 같이) 및 읽기(관계에서와 같이).
내구성 측면으로 돌아가면 결론은 다음과 같습니다. 인덱싱 메커니즘에 관계없이 디스크에 쓰는 모든 데이터베이스는 데이터의 내구성에 대해 좋은 보장을 제공할 수 있지만 각각의 특정 데이터베이스를 처리해야 합니다. , 정확히 무엇을 제공합니다.
6.5 인메모리 DB 작동 방식
그건 그렇고, 디스크에 쓰는 데이터베이스 외에도 주로 RAM에서 작동하는 소위 "메모리 내" 데이터베이스도 있습니다. 즉, 메모리 내 데이터베이스는 일반적으로 더 빠른 쓰기 및 읽기 속도를 위해 낮은 내구성을 제공하지만 일부 응용 프로그램에는 적합할 수 있습니다.
사실 RAM 메모리는 오랫동안 디스크보다 비쌌지만 최근에는 급속도로 저렴해지기 시작하여 RAM에서 데이터를 읽고 쓰는 속도를 고려할 때 논리적인 새로운 유형의 데이터베이스가 생겨났습니다. 그러나 이러한 데이터베이스의 데이터 보안은 어떻습니까? 여기서 다시 구현의 세부 사항을 살펴봐야 합니다. 일반적으로 이러한 데이터베이스 개발자는 다음과 같은 메커니즘을 제공합니다.
- 배터리로 구동되는 RAM을 사용할 수 있습니다.
- 변경 로그를 디스크에 기록하는 것은 가능하지만(위에서 언급한 WAL과 같은 것) 데이터 자체는 기록할 수 없습니다.
- 주기적으로 데이터베이스 상태의 복사본을 디스크에 쓸 수 있습니다(다른 옵션을 사용하지 않으면 보증을 제공하지 않지만 내구성만 향상됨).
- RAM의 상태를 다른 시스템에 복제할 수 있습니다.
예를 들어, 주로 메시지 큐 또는 캐시로 사용되는 인메모리 Redis 데이터베이스는 ACID의 내구성이 부족합니다. 지속성 활성화) 일정한 간격으로 비동기식으로만 가능합니다.
그러나 이것은 모든 응용 프로그램에 중요하지 않습니다. 1-2초마다 플러시되는 EtherPad 협력 온라인 편집기의 예를 찾았으며 잠재적으로 사용자는 거의 중요하지 않은 두 글자 또는 단어를 잃을 수 있습니다. 그렇지 않으면 인 메모리 데이터베이스는 디스크 인덱스로 구현하기 어려운 데이터 모델을 제공한다는 점에서 좋기 때문에 Redis를 사용하여 트랜잭션을 구현할 수 있습니다. 우선 순위 큐를 통해 이를 수행할 수 있습니다.