TiDB (7): 스토리지 기술 인사이더

1. 소개

데이터베이스, 운영 체제, 컴파일러를 총칭하여 3대 시스템이라고 하며, 전체 컴퓨터 소프트웨어의 초석이라고 할 수 있습니다. 그 중 데이터베이스는 애플리케이션 계층에 더 가깝고 많은 비즈니스를 지원합니다. 이 분야에서 수십 년간의 개발 끝에 새로운 발전이 끊임없이 이루어지고 있습니다.

많은 사람들이 데이터베이스를 사용했지만 데이터베이스, 특히 분산 데이터베이스를 구현한 사람은 거의 없습니다. 데이터베이스 구현의 원리와 내용을 이해하는 것은 한편으로는 개인의 능력을 향상시킬 수 있고 다른 시스템을 구축하는 데 도움이 될 수 있으며, 다른 한편으로는 데이터베이스를 잘 활용하는 데에도 도움이 됩니다.

기술을 연구하는 가장 좋은 방법은 오픈 소스 프로젝트 중 하나를 연구하는 것이며 데이터베이스도 예외는 아닙니다. 독립형 데이터베이스 분야에는 좋은 오픈 소스 프로젝트가 많이 있으며 그 중 MySQL과 PostgreSQL이 가장 유명하며 많은 학생들이 이 두 프로젝트의 코드를 보았습니다. 그러나 분산 데이터베이스 측면에서 좋은 오픈 소스 프로젝트는 많지 않습니다. TiDB는 특히 이 프로젝트에 참여하기를 희망하는 일부 기술 애호가들로부터 광범위한 관심을 받았습니다. 분산 데이터베이스 자체의 복잡성으로 인해 많은 사람들이 전체 프로젝트를 잘 이해하지 못하므로 TiDB의 몇 가지 기술적 원리에 대해 위에서 아래로, 얕은 것에서 더 깊은 것으로 기사를 작성하고 싶습니다. 눈에 보이는 기술과 사용자에게 보이지 않는 많은 기술 포인트가 SQL 인터페이스 뒤에 숨겨져 있습니다.

2 세이브 데이터

데이터베이스의 가장 기본적인 기능은 데이터를 저장하는 것이므로 여기에서 시작하겠습니다.

데이터를 저장하는 방법에는 여러 가지가 있지만 가장 간단한 방법은 사용자가 보낸 데이터를 저장하기 위해 메모리에 직접 데이터 구조를 구축하는 것입니다. 예를 들어 배열을 사용하면 데이터 조각이 수신될 때마다 레코드가 배열에 추가됩니다. 이 솔루션은 매우 간단하고 가장 기본적인 요구 사항을 충족시킬 수 있으며 성능은 확실히 좋지만 허점이 가득합니다.가장 큰 문제는 데이터가 완전히 메모리에 있다는 것입니다.일단 서비스가 중지되거나 서비스가 다시 시작하면 데이터가 영구적으로 손실됩니다. .

데이터 손실 문제를 해결하기 위해 데이터를 비휘발성 저장 매체(예: 하드 디스크)에 넣을 수 있습니다. 개선된 솔루션은 디스크에 파일을 만들고 데이터 조각이 수신되면 파일에 한 줄만 추가하는 것입니다. 이제 데이터를 지속적으로 저장하는 솔루션이 생겼습니다. 하지만 충분하지 않습니다. 이 디스크에 불량 트랙이 있으면 어떻게 됩니까? 독립형 중복 스토리지를 제공하기 위해 RAID(Redundant Array of Independent Disks)를 수행할 수 있습니다. 전체 기계가 다운되면 어떻게 됩니까? 예를 들어 화재가 발생하면 RAID가 데이터를 유지할 수 없습니다. 스토리지 대신 네트워크 스토리지를 사용하거나 하드웨어 또는 소프트웨어를 통해 스토리지 복제를 수행할 수도 있습니다. 이 시점에서 우리는 데이터 보안 문제를 해결하고 안도의 한숨을 쉴 수 있는 것 같습니다. 그러나 복사 과정에서 복사본 간의 일관성이 보장될 수 있습니까? 즉, 데이터가 유실되지 않도록 하는 것을 전제로 데이터가 양호한지 확인하는 것도 필요합니다. 데이터가 손실되지 않도록 하는 것은 기본적인 요구 사항일 뿐이며 해결해야 할 더 많은 골칫거리가 있습니다.

  • 데이터 센터 전체에서 재해 복구를 지원할 수 있습니까?
  • 쓰기 속도가 충분히 빠른가요?
  • 데이터를 저장한 후 쉽게 읽을 수 있습니까?
  • 저장된 데이터는 어떻게 수정하나요? 동시 수정을 지원하는 방법은 무엇입니까?
  • 여러 레코드를 원자적으로 수정하는 방법은 무엇입니까?

이러한 각각의 문제는 매우 어렵지만 우수한 데이터 저장 시스템을 만들기 위해서는 위의 각 문제를 해결해야 합니다. 데이터 저장 문제를 해결하기 위해 TiKV 프로젝트를 개발했습니다. 다음으로 TiKV의 몇 가지 디자인 아이디어와 기본 개념을 소개하겠습니다.

3 키-값

데이터 스토리지 시스템으로서 가장 먼저 결정해야 할 것은 데이터 스토리지 모델, 즉 데이터를 어떤 형태로 저장할 것인가입니다. TiKV의 선택은 Key-Value 모델이며 정렬된 순회 방법을 제공합니다. 간단히 말해서 TiKV는 Key와 Value가 모두 원래의 Byte 배열인 거대한 Map으로 볼 수 있으며, 이 Map에서 Key는 Byte 배열의 원래 이진 비트를 비교하는 순서로 배열됩니다. 여기 있는 모든 사람은 TiKV에 대해 두 가지 사항을 기억해야 합니다.

  1. 이것은 거대한 맵입니다. 즉, 키-값 쌍이 저장됩니다.
  2. 이 Map의 키-값 쌍은 키의 이진 순서에 따라 정렬됩니다. 즉, 특정 키 위치를 탐색한 다음 계속해서 Next 메서드를 호출하여 증가하는 이 키보다 큰 키-값을 얻을 수 있습니다. 주문하다

많은 이야기를 하고 나면 여기에서 언급된 스토리지 모델과 SQL의 테이블 사이의 관계는 무엇입니까? 여기서 네 번 말해야 할 중요한 사항이 하나 있습니다.

여기서 스토리지 모델은 SQL의 테이블과 아무 관련이 없습니다! 여기서 스토리지 모델은 SQL의 테이블과 아무 관련이 없습니다! 여기서 스토리지 모델은 SQL의 테이블과 아무 관련이 없습니다! 여기서 스토리지 모델은 SQL의 테이블과 아무 관련이 없습니다!

이제 SQL의 개념은 잊고 TiKV와 같은 고성능 및 고신뢰성을 갖춘 거대한(분산) Map을 구현하는 방법에 집중하겠습니다.

4 RocksDB

영구 스토리지 엔진의 경우 데이터는 결국 디스크에 저장되어야 하며 TiKV도 예외는 아닙니다. 그러나 TiKV는 데이터를 디스크에 직접 쓰는 것이 아니라 RocksDB에 데이터를 저장하는 것을 선택했으며 RocksDB는 특정 데이터 랜딩을 담당합니다. 이러한 선택의 이유는 독립형 스토리지 엔진을 개발하는 것은 많은 작업이 필요하며 특히 고성능 독립형 엔진의 경우 다양하고 세심한 최적화가 필요하기 때문입니다. 독립형 엔진에 대한 다양한 요구 사항이 있으며 Facebook 팀은 지속적인 최적화를 수행하여 매우 적은 노력으로 매우 강력하고 지속적으로 개선되는 독립형 엔진을 즐길 수 있습니다. 물론 우리는 이 프로젝트가 점점 더 좋아지기를 바라며 RocksDB에 몇 가지 코드를 제공했습니다. 여기서 RocksDB는 독립형 키-값 맵이라고 간단히 생각할 수 있습니다.

기본 LSM 트리는 데이터에 대한 증분 변경 사항을 메모리에 저장하고 지정된 크기 제한에 도달한 후 일괄적으로 데이터를 디스크에 플러시합니다. 디스크의 트리는 주기적으로 병합되어 성능을 최적화하기 위해 큰 트리를 형성할 수 있습니다.

5 뗏목

음, 긴 행진의 첫 번째 단계가 시작되었으며 데이터를 위한 효율적이고 안정적인 로컬 스토리지 솔루션을 찾았습니다. 모든 일이 처음도 어렵고 중간도 어렵고 끝도 어렵다는 말이 있습니다. 다음으로 우리는 더 어려운 작업에 직면해 있습니다. 독립 실행형 오류가 발생한 경우 데이터가 손실되지 않고 오류가 발생하지 않도록 하는 방법은 무엇입니까? 간단히 말해서 데이터를 여러 시스템에 복제하는 방법을 찾아 한 시스템이 중단되더라도 다른 시스템에 사본이 남아 있도록 해야 합니다. 복잡한 측면에서 우리는 이 복제 솔루션이 안정적이고 효율적이며 복제본 무효화를 처리할 수 있습니다. 어렵게 들리지만 다행스럽게도 Raft 프로토콜이 있습니다. Raft는 Paxos와 동일하지만 이해하기 쉬운 합의 알고리즘입니다. Raft의 논문, 관심 있으신 분들은 한번 살펴보셔도 좋습니다. 이 문서는 Raft에 대한 간략한 소개만 제공하며 자세한 내용은 해당 문서를 참조할 수 있습니다. 또 하나 언급할 점은 Raft 논문은 기본적인 솔루션일 뿐이며 논문에 따라 엄격하게 구현하면 성능이 저하될 수 있으므로 Raft 프로토콜 구현을 위해 많은 최적화를 수행했습니다.

Raft는 몇 가지 중요한 기능을 제공하는 합의 프로토콜입니다.

  • 지도자 선출
  • 멤버 변경
  • 로그 복제

TiKV는 데이터 복제를 위해 Raft를 사용하며 각 데이터 변경은 Raft 로그로 구현되며 Raft의 로그 복제 기능을 통해 데이터는 그룹의 대부분의 노드에 안전하고 안정적으로 동기화됩니다.

단일 시스템 RocksDB를 통해 데이터를 디스크에 신속하게 저장할 수 있고 Raft를 통해 데이터를 여러 시스템에 복제하여 단일 시스템 오류를 방지할 수 있다는 점을 요약해 보겠습니다. 데이터는 RocksDB에 직접 쓰는 대신 Raft 레이어 인터페이스를 통해 씁니다. Raft를 구현함으로써 우리는 분산된 KV를 가지게 되었고 이제 우리는 더 이상 특정 기계가 끊기는 것에 대해 걱정할 필요가 없습니다.

6 지역

이와 관련하여 우리는 매우 중요한 개념인 지역을 언급할 수 있습니다. 이 개념은 이후 일련의 메커니즘을 이해하기 위한 기초입니다. 이 섹션을 주의 깊게 읽으십시오.

앞서 언급한 바와 같이 우리는 TiKV를 거대하고 정렬된 KV 맵으로 간주하므로 스토리지의 수평적 확장을 달성하기 위해 데이터를 여러 시스템에 분산시켜야 합니다. 여기에서 언급한 데이터는 여러 머신에 분산되어 있고 Raft의 데이터 복제는 개념이 없습니다.이 섹션에서는 Raft를 잊고 모든 데이터가 하나의 복사본만 있다고 가정하여 이해하기 더 쉽습니다.

KV 시스템의 경우 여러 시스템에 데이터를 배포하기 위한 두 가지 일반적인 솔루션이 있습니다: 하나는 키에 따라 해시를 수행하고 해시 값에 따라 해당 스토리지 노드를 선택하는 것입니다. 키는 하나의 스토리지 노드에 저장됩니다. TiKV는 두 번째 방법을 선택하여 전체 키-값 공간을 여러 세그먼트로 나누고 각 세그먼트는 일련의 연속 키이며 각 세그먼트를 지역이라고 하며 각 지역에 저장된 데이터가 특정 범위를 초과하지 않도록 노력합니다. 크기(이 크기는 구성할 수 있으며 현재 기본값은 64mb입니다). 각 지역은 StartKey에서 EndKey까지 왼쪽이 닫히고 오른쪽이 열리는 간격으로 설명할 수 있습니다.

여기서 지역은 SQL의 테이블과 아무 관련이 없습니다! 계속해서 SQL은 잊고 KV에 대해 이야기하십시오. 데이터를 지역으로 나눈 후 두 가지 중요한 작업을 수행합니다.

  • 지역 단위로 클러스터의 모든 노드에 데이터를 분산시키고 각 노드에서 제공되는 지역의 수가 거의 동일하도록 노력하십시오.
  • Region 단위의 Raft 복제 및 구성원 관리

이 두 가지 사항은 매우 중요합니다. 하나씩 이야기합시다.

첫 번째 포인트를 먼저 보면 데이터가 Key에 따라 여러 Region으로 나뉘고 각 Region의 데이터는 하나의 노드에만 저장됩니다. 우리 시스템은 클러스터의 모든 노드에 지역을 가능한 한 균등하게 분배하는 구성 요소를 가지므로 한편으로는 스토리지 용량의 수평 확장을 달성할 수 있습니다(새 노드를 추가한 후 다른 노드의 지역은 자동 스케줄링) 반면에 로드 밸런싱도 달성합니다(한 노드에는 많은 데이터가 있고 다른 노드에는 데이터가 없는 일이 발생하지 않음). 동시에 상위 수준 클라이언트가 필요한 데이터에 액세스할 수 있도록 하기 위해 우리 시스템에는 노드의 지역 분포를 기록하는 구성 요소가 있습니다. 즉, 모든 키를 통해 다음을 수행할 수 있습니다. 키가 있는 리전과 현재 리전이 있는 이 노드를 쿼리합니다.

두 번째 지점의 경우 TiKV는 지역 단위로 데이터를 복제합니다. 즉, 지역에 여러 데이터 사본이 저장되며 각 사본을 복제본이라고 합니다. Raft를 통해 복제본 간에 데이터 일관성이 유지되며, 한 지역의 여러 복제본이 서로 다른 노드에 저장되어 Raft 그룹을 형성합니다. 레플리카 중 하나는 그룹의 리더가 되고 다른 레플리카는 팔로워가 됩니다. 모든 읽기 및 쓰기는 Leader에 의해 수행된 다음 Leader에 의해 Follower로 복사됩니다.

 

우리는 Region을 하나의 단위로 사용하여 데이터를 분산 및 복제하고 특정 재해 복구 기능을 갖춘 분산 KeyValue 시스템을 보유하고 있으므로 데이터 저장 또는 디스크 장애 및 데이터 손실에 대해 걱정할 필요가 없습니다. 멋지지만 완벽하지는 않습니다. 더 많은 기능이 필요합니다.

7 MVCC

많은 데이터베이스가 다중 버전 제어(MVCC)를 구현하며 TiKV도 예외는 아닙니다. 두 개의 클라이언트가 동시에 키 값을 수정하는 시나리오를 상상해보십시오.MVCC가 없으면 데이터를 잠글 필요가 있습니다.분산 시나리오에서는 성능 및 교착 상태 문제가 발생할 수 있습니다. TiKV의 MVCC 구현은 키 뒤에 버전을 추가하여 이루어집니다. 간단히 말해서 MVCC 이전에 TiKV는 다음과 같이 간주할 수 있습니다.

키1 -> 값
키2 -> 값
……
키N -> 값

MVCC에서 TiKV의 키 배열은 다음과 같습니다.

Key1-버전3 -> 값
Key1-버전2 -> 값
Key1-버전1 -> 값

Key2-버전4 -> 값
Key2-버전3 -> 값
Key2-버전2 -> 값
Key2- 버전1 - > 값

> 값
KeyN-Version1 -> 값
......

동일한 키의 여러 버전에 대해 더 큰 버전 번호는 앞에, 더 작은 버전 번호는 뒤에 배치합니다(키-값 섹션에서 소개한 키가 순서대로 정렬되어 있음을 기억하십시오). 사용자는 Key + Version을 통해 Value를 얻습니다. Key와 Version은 Key-Version인 MVCC Key를 구성하는 데 사용할 수 있습니다. 그런 다음 직접 Seek(Key-Version)하여 이 Key-Version보다 크거나 같은 첫 번째 위치를 찾을 수 있습니다.

8건

TiKV의 트랜잭션은 Percolator 모델을 채택하고 많은 최적화를 수행했습니다. TiKV의 트랜잭션은 낙관적 잠금을 사용합니다.트랜잭션 실행 중에 쓰기-쓰기 충돌이 감지되지 않습니다.충돌 감지는 제출 프로세스 중에만 수행됩니다.제출을 일찍 완료한 충돌 당사자 중 쓰기가 성공하고 상대방은 전체 거래를 재실행하려고 시도합니다. 비즈니스의 쓰기 충돌이 심각하지 않은 경우 테이블의 특정 행 데이터를 무작위로 업데이트하는 등 이 모델의 성능이 매우 좋으며 테이블이 매우 큽니다. 그러나 비즈니스 쓰기 충돌이 심각하면 성능이 저하됩니다.극단적인 예로는 카운터가 있습니다.여러 클라이언트가 동시에 적은 수의 행을 수정하여 심각한 충돌과 많은 수의 유효하지 않은 재시도를 초래합니다.

9 기타

지금까지 우리는 TiKV의 기본 개념과 일부 세부 사항을 배웠고 트랜잭션이 있는 이 분산 KV 엔진의 계층 구조와 다중 복사 내결함성을 달성하는 방법을 이해했습니다. 다음 섹션에서는 KV 스토리지 모델 위에 SQL 계층을 구축하는 방법을 소개합니다.

Supongo que te gusta

Origin blog.csdn.net/u013938578/article/details/131553853
Recomendado
Clasificación