MySQL 샤딩 접근 방식?


88

MySQL 테이블을 샤딩하는 가장 좋은 방법은 무엇입니까? 내가 생각할 수있는 접근 방식은 다음과 같습니다.

  1. 애플리케이션 수준 분할?
  2. MySQL 프록시 레이어에서 샤딩?
  3. 샤딩을위한 중앙 조회 서버?

이 분야에서 흥미로운 프로젝트 나 도구를 알고 있습니까?

답변:


116

완전히 피할 수없는 경우가 아니라면 MySQL 테이블을 분할하지 않는 가장 좋은 방법입니다.

응용 프로그램을 작성할 때 일반적으로 속도와 개발자 속도를 최대화하는 방식으로 작성하려고합니다. 필요한 경우에만 지연 시간 (답변이 준비 될 때까지의 시간) 또는 처리량 (시간 단위당 응답 수)을 최적화합니다.

이러한 모든 파티션의 합계가 더 이상 단일 데이터베이스 서버 인스턴스에 맞지 않을 때만 파티션을 분할 한 다음 다른 호스트 (= 샤드)에 할당합니다. 그 이유는 쓰기 또는 읽기 때문입니다.

쓰기 사례는 a) 쓰기 빈도로 인해이 서버 디스크에 영구적으로 과부하가 걸리거나 b) 너무 많은 쓰기가 진행되어이 복제 계층에서 복제가 영구적으로 지연됩니다.

샤딩의 읽기 사례는 데이터의 크기가 너무 커서 데이터의 작업 세트가 더 이상 메모리에 맞지 않고 데이터 읽기가 대부분의 시간 동안 메모리에서 제공되는 대신 디스크에 도달하기 시작하는 경우입니다.

당신이 경우에만 샤딩하는 당신은 그것을 할.


샤딩하는 순간 여러 가지 방법으로 비용을 지불하게됩니다.

대부분의 SQL은 더 이상 선언적이지 않습니다.

일반적으로 SQL에서는 원하는 데이터를 데이터베이스에 알리고 해당 사양을 데이터 액세스 프로그램으로 전환하기 위해 옵티 마이저에 맡깁니다. 유연성이 있고 이러한 데이터 액세스 프로그램을 작성하는 것은 속도에 해를 끼치는 지루한 작업이기 때문입니다.

분할 된 환경에서는 노드 B의 데이터에 대해 노드 A의 테이블을 조인하거나 노드 A 및 B의 노드보다 큰 테이블이 있고 노드 B 및 C에있는 데이터에 대해 데이터를 조인 할 수 있습니다. 이를 해결하기 위해 (또는 MySQL 클러스터를 재창조하고 있음) 애플리케이션 측 해시 기반 조인 해결을 수동으로 작성하기 시작했습니다. 즉, 더 이상 선언적이지 않지만 절차 적 방식으로 SQL 기능을 표현하는 많은 SQL로 끝납니다. (예를 들어, 루프에서 SELECT 문을 사용하고 있습니다).

많은 네트워크 지연이 발생합니다.

일반적으로 SQL 쿼리는 로컬에서 확인할 수 있으며 옵티마이 저는 로컬 디스크 액세스와 관련된 비용을 알고 비용을 최소화하는 방식으로 쿼리를 해결합니다.

분할 된 환경에서 쿼리는 네트워크를 통해 여러 노드에 대한 키-값 액세스를 실행하거나 (왕복 당 개별 키 조회가 아닌 일괄 키 액세스를 사용하여) WHERE절의 일부를 가능한 노드로 푸시 하여 해결됩니다. 적용 ( '조건 푸시 다운'이라고 함) 또는 둘 다.

그러나 최상의 경우에도 이것은 로컬 상황보다 더 많은 네트워크 왕복을 포함하며 더 복잡합니다. 특히 MySQL 옵티마이 저는 네트워크 대기 시간에 대해 전혀 알지 못하기 때문에 (예, MySQL 클러스터는 천천히 향상되고 있지만 클러스터 외부의 바닐라 MySQL의 경우 여전히 사실입니다).

SQL의 많은 표현력을 잃고 있습니다.

그다지 중요하지 않을 수 있지만 데이터 무결성을위한 외래 키 제약 조건 및 기타 SQL 메커니즘은 여러 샤드를 확장 할 수 없습니다.

MySQL에는 작동하는 비동기 쿼리를 허용하는 API가 없습니다.

동일한 유형의 데이터가 여러 노드에있는 경우 (예 : 노드 A, B 및 C의 사용자 데이터) 이러한 모든 노드에 대해 수평 쿼리를 해결해야하는 경우가 많습니다 ( "90 일 동안 로그인하지 않은 모든 사용자 계정 찾기 이상"). 데이터 액세스 시간은 여러 노드가 병렬로 요청되고 결과가 들어오는대로 집계되지 않는 한 노드 수에 따라 선형 적으로 증가합니다 ( "Map-Reduce").

이를위한 전제 조건은 비동기 통신 API이며, MySQL에는 좋은 작동 형태로 존재하지 않습니다. 대안은 시즌 패스의 세계를 방문하는 자식 프로세스의 많은 포크와 연결입니다.


샤딩을 시작하면 데이터 구조와 네트워크 토폴로지가 애플리케이션의 성능 포인트로 표시됩니다. 합리적으로 잘 수행하려면 애플리케이션이 이러한 사항을 인식해야하며 이는 실제로 애플리케이션 수준 분할 만 의미가 있음을 의미합니다.

문제는 자동 샤딩 (예 : 기본 키를 해싱하여 어떤 행이 어떤 노드로 이동하는지 결정)을 원하거나 수동 방식으로 기능적으로 분할하려는 경우 ( "xyz 사용자 스토리와 관련된 테이블은 master, abc 및 def 관련 테이블은 해당 마스터로 이동합니다. ").

기능적 분할은 사용자 스토리와 관련된 모든 테이블을 로컬에서 사용할 수 있기 때문에 제대로 수행하면 대부분의 개발자에게 보이지 않는다는 장점이 있습니다. 이를 통해 가능한 한 오랫동안 선언적 SQL의 이점을 누릴 수 있으며 네트워크 간 전송 횟수를 최소화하기 때문에 네트워크 지연 시간도 줄어들 것입니다.

기능적 샤딩은 단일 테이블이 하나의 인스턴스보다 클 수 없다는 단점이 있으며 디자이너의 수동주의가 필요합니다.

기능적 샤딩은 너무 크지 않은 많은 변경으로 기존 코드베이스에 비교적 쉽게 수행 할 수 있다는 장점이 있습니다. http://Booking.com 은 지난 몇 년 동안 여러 번 해왔으며 잘 작동했습니다.


모든 것을 말하면서 귀하의 질문을 보면 귀하가 잘못된 질문을하고 있다고 생각하거나 귀하의 문제 진술을 완전히 오해하고 있습니다.


2
이것은 좋은 대답입니다. 그러나 저는 샤딩이 실제로 대용량 애플리케이션에만 필요하며 어떤 종류의 수익을 창출 할 가능성이 있다는 점을 지적하고 싶습니다. 타사 샤딩 응용 프로그램은 조인, 교차 샤드 트랜잭션 등에 대한 모든 문제를 처리합니다. 그리고 좋은 것을 얻으면 "관계형"데이터베이스의 무결성을 유지합니다. 다른 응용 프로그램은 데이터베이스를 키-값 쌍으로 간단하게 전환하여 SQL의 목적을 무력화합니다.
chantheman 2011

3
나는 아직 상업용이든 아니든 데이터가 네트워크에 흩어져 있고 대기 시간으로 인한 대기 시간 부족으로 인해 대기 시간이나 불일치가 발생한다는 사실을 숨기는 데 성공한 샤딩 애플리케이션을 아직 발견하지 못했습니다. 샤딩하는 경우 응용 프로그램이 알림을 받게되며 변경이 필요합니다. 당신이 그것을 직접 제어 할 수도 있습니다. 은색 총알은 없지만 뱀 기름이 많이 있습니다.
Isotopp 2011

1
dbShards를 확인해야합니다. 추가하는 "샤드"수에 따라 선형 적으로 확장하는 것보다 더 잘 확장됩니다. 응용 프로그램 측면에서 변경 사항이있는 경우 거의 필요하지 않으며 응용 프로그램은 그 차이를 알지 못합니다. ODBC 또는 JDBC에서와 동일한 방식으로 트랜잭션을 보내고받습니다. dbShards는 또한 트랜잭션에 대한 더 많은 제어를 원할 경우 샤드 힌트를 허용합니다. dbShards에 읽고 쓰려는 샤드를 정확하게 알릴 수 있습니다.
chantheman

1
@Gigala 글쎄, 광범위함에 관계없이 이와 같이 잘 정의 된 답변을 작성하는 데 시간을 할애하는 것도 필요하지 않지만이 답변이 도움이 되었기 때문에 완료되어 기쁩니다. 사용자가 응답 할 때 "상자 밖에서 생각"하지 않도록 권장하지 마십시오.
mewm

12
  1. 애플리케이션 레벨 샤딩 : dbShards는 "애플리케이션 인식 샤딩"을 수행하는 유일한 제품입니다. 웹 사이트에는 몇 가지 좋은 기사가 있습니다. 정의상 애플리케이션 인식 샤딩이 더 효율적입니다. 응용 프로그램이 트랜잭션을 조회하거나 프록시에 의해 리디렉션되지 않고 트랜잭션과 함께 이동해야 할 위치를 정확히 알고 있다면 자체적으로 더 빠를 것입니다. 누군가가 샤딩을 조사 할 때 속도는 유일한 문제는 아니지만 주요 관심사 중 하나입니다.

  2. 어떤 사람들은 프록시로 "샤딩"하지만 내 눈에는 샤딩의 목적을 무너 뜨립니다. 트랜잭션에 데이터를 찾을 위치 또는 저장할 위치를 알리기 위해 다른 서버를 사용하고 있습니다. 애플리케이션 인식 샤딩을 사용하면 애플리케이션이 자체적으로 어디로 가야하는지 알 수 있습니다. 훨씬 더 효율적입니다.

  3. 이것은 실제로 # 2와 동일합니다.


dbShards가 프로덕션에서 사용되는 곳은 어디입니까? 또한 오픈 소스가 아닙니다.
sheki 2011

또한 프록시가 DB 또는 저장소 대신 해시를 기반으로 조회하는 경우 접근 방식 2와 3이 다를 수 있습니다.
sheki

1
dbShards는 다양한 클라이언트와 함께 생산 중이지만 오픈 소스가 아닙니다. 좋은 오픈 소스 샤딩 제품을 찾을 수 없을 것 같습니다. 그리고 그렇습니다. 해시가 조회로 사용될 수 있다는 것은 맞습니다. 그러나이 경우 트랜잭션을 데이터베이스로 가져 오기 위해 여전히 한 번 더 "중지"해야합니다. 이것이 "애플리케이션 인식"샤딩이 거의 항상 더 빠른 이유입니다.
chantheman 2011

그러나 내가 말했듯이 관계의 무결성을 유지하는 분할 응용 프로그램을 얻을 수 있다면 좋은 상태가 될 것입니다. dbShards는 내가 아는 유일한 사람이기 때문에 언급합니다. 또한 쓰기 및 읽기 속도를 선형 적으로 확장합니다. 4 개의 "샤드"를 추가하거나 하나의 MySQL 서버를 4 개로 분할하면 4 배 빠르게 실행됩니다.
chantheman 2011

7

이 분야에서 흥미로운 프로젝트 나 도구를 알고 있습니까?

이 공간의 몇 가지 새로운 프로젝트 :

  • citusdata.com
  • spockproxy.sourceforge.net
  • github.com/twitter/gizzard/

5

Shard-Query 는 MySQL 용 OLAP 기반 샤딩 솔루션입니다. 분할 된 테이블과 분할되지 않은 테이블의 조합을 정의 할 수 있습니다. 분할되지 않은 테이블 (예 : 조회 테이블)은 분할 된 테이블에 자유롭게 조인 할 수 있으며, 분할 된 테이블이 분할 키로 조인되는 한 분할 된 테이블은 서로 조인 될 수 있습니다 (샤드 경계를 교차하는 교차 분할 또는 자체 조인 없음). OLAP 솔루션이기 때문에 Shard-Query는 일반적으로 간단한 쿼리의 경우에도 최소 응답 시간이 100ms 이하이므로 OLTP에서는 작동하지 않습니다. Shard-Query는 빅 데이터 세트를 병렬로 분석하도록 설계되었습니다.

MySQL 용 OLTP 샤딩 솔루션도 있습니다. 폐쇄 형 소스 솔루션에는 ScaleDB , DBShards가 포함됩니다 . 오픈 소스 OLTP 솔루션에는 JetPants , Cubrid 또는 Flock / Gizzard (Twitter 인프라)가 포함됩니다.


3

물론 응용 수준.

내가이 책에서 찾은 최고의 접근 방식

고성능 MySQL http://www.amazon.com/High-Performance-MySQL-Jeremy-Zawodny/dp/0596003064

간단한 설명 : 데이터를 여러 부분으로 분할하고 각 서버에 최대 50 개의 부분을 저장할 수 있습니다. 두 번째로 큰 샤딩 문제인 재조정을 피하는 데 도움이됩니다. 그중 일부를 새 서버로 옮기면 모든 것이 잘됩니다. :)

나는 당신이 그것을 구입하고 "mysql 스케일링"부분을 읽을 것을 강력히 추천합니다.


추천하신 책은 8 년 전입니다 ... 오늘날의 기술과 관련된 샤딩을 다루나요?
raffian

1
mysql을 확장하는 몇 가지 기본적인 접근 방식을 다룹니다. AFAIK mysql 확장시 변경된 사항이 없습니다. 동일한 앱 수준의 샤딩 및 복제 기술이 오늘날 널리 사용되고 있습니다.
Andrey Frolov

내가 틀렸을 수도 있지만 지난주에 걸쳐 이에 대해 많은 연구를 해왔고 mySQL 자체가 지난 8 년 동안 특히 파티셔닝 및 캐싱과 관련하여 많은 변경을 한 것 같습니다. 올해 출시 된 새 버전이 있습니다. amazon.com/High-Performance-MySQL-Optimization-Replication/dp/… 아직 읽지 않았지만 사용 가능한 새로운 복제 모델을 다루는 것 같습니다.
NateDSaint

4
책 .. 여기에서 설명하지 않는 이유.
DDD '

2

2018 년에는 이에 대한 MySql 네이티브 솔루션이있는 것 같습니다. 실제로 적어도 2 개 -InnoDB 클러스터NDB 클러스터가 있습니다 (상용 및 커뮤니티 버전이 있습니다).

MySql 커뮤니티 에디션을 사용하는 대부분의 사람들은 InnoDB 엔진에 더 익숙하기 때문에 이것이 최우선 순위로 탐색되어야합니다. 즉시 복제 및 파티셔닝 / 샤딩을 지원하며 다양한 라우팅 /로드 밸런싱 옵션을 위해 MySql 라우터를 기반으로합니다.

테이블 생성 구문을 변경해야합니다. 예를 들면 다음과 같습니다.

    CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATETIME) PARTITION BY HASH ( YEAR(col3) );

(이것은 네 가지 파티션 유형 중 하나 일뿐입니다 )

매우 중요한 제한 사항 :

InnoDB 외래 키와 MySQL 파티셔닝은 호환되지 않습니다. 분할 된 InnoDB 테이블은 외래 키 참조를 가질 수 없으며 외래 키가 참조하는 열을 가질 수 없습니다. 외래 키가 있거나 외부 키에 의해 참조되는 InnoDB 테이블은 분할 할 수 없습니다.


그주의 PARTITION BY HASH(YEAR...)스캔 모두 당신이 날짜 범위가있는 경우 파티션을. 왝.
Rick James
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.