Các phương pháp tiếp cận sharding với MySQL?


88

Cách tiếp cận tốt nhất cho các bảng Sharding MySQL là gì. Các cách tiếp cận tôi có thể nghĩ đến là:

  1. Sharding cấp ứng dụng?
  2. Làm sắc nét ở lớp proxy MySQL?
  3. Máy chủ tra cứu trung tâm cho sharding?

Bạn có biết bất kỳ dự án hoặc công cụ thú vị nào trong lĩnh vực này không?

Câu trả lời:


115

Cách tốt nhất để phân tích các bảng MySQL là không nên làm điều đó trừ khi hoàn toàn không thể tránh khỏi việc làm đó.

Khi bạn đang viết một ứng dụng, bạn thường muốn làm như vậy theo cách tối đa hóa tốc độ, tốc độ của nhà phát triển. Bạn chỉ tối ưu hóa độ trễ (thời gian cho đến khi câu trả lời sẵn sàng) hoặc thông lượng (số câu trả lời trên một đơn vị thời gian) khi cần thiết.

Bạn phân vùng và sau đó chỉ định phân vùng cho các máy chủ khác nhau (= shard) khi tổng của tất cả các phân vùng này không còn phù hợp với một phiên bản máy chủ cơ sở dữ liệu duy nhất - lý do cho việc ghi hoặc đọc.

Trường hợp ghi là a) tần suất ghi đang làm quá tải các đĩa máy chủ này vĩnh viễn hoặc b) có quá nhiều lần ghi đang diễn ra khiến việc sao chép bị trì hoãn vĩnh viễn trong hệ thống phân cấp sao chép này.

Trường hợp đọc đối với sharding là khi kích thước của dữ liệu quá lớn đến mức tập hợp làm việc của nó không còn phù hợp với bộ nhớ và các lần đọc dữ liệu bắt đầu đánh vào đĩa thay vì được cung cấp từ bộ nhớ trong hầu hết thời gian.

Chỉ khi bạn phải chia nhỏ, bạn mới làm điều đó.


Thời điểm bạn chia nhỏ, bạn đang trả tiền cho điều đó theo nhiều cách:

Phần lớn SQL của bạn không còn mang tính khai báo nữa.

Thông thường, trong SQL, bạn đang cho cơ sở dữ liệu biết dữ liệu nào bạn muốn và để nó cho trình tối ưu hóa để biến đặc tả đó thành một chương trình truy cập dữ liệu. Đó là một điều tốt, bởi vì nó linh hoạt, và bởi vì việc viết những chương trình truy cập dữ liệu này là một công việc nhàm chán gây hại cho vận tốc.

Với môi trường phân đoạn, bạn có thể đang tham gia một bảng trên nút A với dữ liệu trên nút B hoặc bạn có một bảng lớn hơn một nút, trên các nút A và B và đang kết hợp dữ liệu từ nó với dữ liệu trên nút B và C. Bạn đang bắt đầu viết các độ phân giải tham gia dựa trên băm phía ứng dụng theo cách thủ công để giải quyết điều đó (hoặc bạn đang phát minh lại cụm MySQL), nghĩa là bạn kết thúc với rất nhiều SQL không còn mang tính khai báo nữa, nhưng đang thể hiện chức năng SQL theo cách thủ tục (ví dụ bạn đang sử dụng câu lệnh SELECT trong các vòng lặp).

Bạn đang phải chịu nhiều độ trễ mạng.

Thông thường, một truy vấn SQL có thể được giải quyết cục bộ và trình tối ưu hóa biết về chi phí liên quan đến truy cập đĩa cục bộ và giải quyết truy vấn theo cách giảm thiểu chi phí cho việc đó.

Trong môi trường phân đoạn, các truy vấn được giải quyết bằng cách chạy các truy cập khóa-giá trị trên mạng tới nhiều nút (hy vọng với các truy cập khóa theo đợt chứ không phải tra cứu khóa riêng lẻ trên mỗi chuyến khứ hồi) hoặc bằng cách đẩy các phần của WHERE mệnh đề về phía trước đến các nút mà chúng có thể được áp dụng (được gọi là 'điều kiện đẩy xuống') hoặc cả hai.

Nhưng ngay cả trong những trường hợp tốt nhất, điều này liên quan đến nhiều chuyến đi vòng quanh mạng hơn mà một tình huống cục bộ, và nó phức tạp hơn. Đặc biệt là vì trình tối ưu hóa MySQL không biết gì về độ trễ mạng (Ok, cụm MySQL đang dần trở nên tốt hơn, nhưng đối với MySQL vani bên ngoài cụm thì điều đó vẫn đúng).

Bạn đang mất rất nhiều sức mạnh biểu đạt của SQL.

Ok, điều đó có lẽ ít quan trọng hơn, nhưng các ràng buộc khóa ngoại và các cơ chế SQL khác để toàn vẹn dữ liệu không có khả năng mở rộng nhiều phân đoạn.

MySQL không có API cho phép các truy vấn không đồng bộ theo thứ tự hoạt động.

Khi dữ liệu cùng loại nằm trên nhiều nút (ví dụ: dữ liệu người dùng trên các nút A, B và C), các truy vấn ngang thường cần được giải quyết dựa trên tất cả các nút này ("Tìm tất cả tài khoản người dùng chưa được đăng nhập trong 90 ngày hoặc hơn"). Thời gian truy cập dữ liệu tăng tuyến tính với số lượng nút, trừ khi có thể yêu cầu nhiều nút song song và kết quả được tổng hợp khi chúng xuất hiện ("Map-Reduce").

Điều kiện tiên quyết cho điều đó là một API giao tiếp không đồng bộ, không tồn tại cho MySQL ở trạng thái hoạt động tốt. Giải pháp thay thế là rất nhiều sự rèn luyện và kết nối trong các quá trình trẻ em, đang đến thăm thế giới của sự hấp dẫn khi vượt qua mùa giải.


Khi bạn bắt đầu sharding, cấu trúc dữ liệu và cấu trúc liên kết mạng sẽ hiển thị dưới dạng điểm hiệu suất cho ứng dụng của bạn. Để hoạt động tốt một cách hợp lý, ứng dụng của bạn cần phải lưu ý những điều này và điều đó có nghĩa là chỉ có phân cấp ứng dụng thực sự mới có ý nghĩa.

Câu hỏi đặt ra nhiều hơn nếu bạn muốn tự động phân đoạn (xác định hàng đi vào nút nào bằng cách băm khóa chính chẳng hạn) hoặc nếu bạn muốn phân chia theo chức năng theo cách thủ công ("Các bảng liên quan đến câu chuyện người dùng xyz chuyển đến mục này master, trong khi abc và các bảng liên quan đến def chuyển đến master đó ").

Chức năng sharding có lợi thế là, nếu được thực hiện đúng, nó sẽ vô hình đối với hầu hết các nhà phát triển, vì tất cả các bảng liên quan đến câu chuyện người dùng của họ sẽ có sẵn cục bộ. Điều đó cho phép họ vẫn được hưởng lợi từ SQL khai báo càng lâu càng tốt, và cũng sẽ ít phải chịu độ trễ mạng hơn vì số lần truyền giữa các mạng được giữ ở mức tối thiểu.

Chức năng sharding có nhược điểm là nó không cho phép bất kỳ bảng nào lớn hơn một thể hiện và nó đòi hỏi sự chú ý thủ công của người thiết kế.

Chức năng sharding có ưu điểm là nó được thực hiện tương đối dễ dàng với cơ sở mã hiện có với một số thay đổi không quá lớn. http://Booking.com đã làm điều đó nhiều lần trong những năm qua và nó hoạt động tốt cho họ.


Đã nói tất cả những điều đó, nhìn vào câu hỏi của bạn, tôi tin rằng bạn đang đặt câu hỏi sai, hoặc tôi hoàn toàn hiểu sai tuyên bố vấn đề của bạn.


2
Đây là một câu trả lời tốt. Nhưng tôi muốn chỉ ra rằng sharding thực sự chỉ cần thiết cho các ứng dụng có khối lượng lớn và rất có thể chúng đang tạo ra một số loại doanh thu. Một ứng dụng sharding của bên thứ ba sẽ xử lý tất cả các mối quan tâm mà bạn có về các phép nối, giao dịch chéo, v.v. Và nếu bạn nhận được một ứng dụng tốt, nó sẽ duy trì tính toàn vẹn của cơ sở dữ liệu "quan hệ". Các ứng dụng khác, bạn nói đúng, sẽ đơn giản biến cơ sở dữ liệu của bạn thành một cặp khóa-giá trị và do đó đánh bại mục đích của SQL.
chantheman

3
Tôi vẫn chưa tìm thấy một ứng dụng sharding, thương mại hay không, thành công trong việc che giấu thực tế rằng dữ liệu hiện nằm rải rác trên mạng và có độ trễ hoặc không nhất quán do thiếu các lần chờ gây ra độ trễ. Nếu bạn đang dùng sharding, ứng dụng của bạn sẽ thông báo và sẽ yêu cầu thay đổi. Bạn cũng có thể tự mình kiểm soát điều đó. Không có viên đạn bạc, nhưng có nhiều dầu rắn.
Isotopp

1
Bạn nên kiểm tra dbShards. Nó chia tỷ lệ tốt hơn tuyến tính theo # "phân đoạn" bạn thêm vào. Bạn sẽ yêu cầu rất ít, nếu có, những thay đổi về phía ứng dụng và có, ứng dụng của bạn không biết sự khác biệt. Nó chỉ gửi và nhận các giao dịch giống như bạn làm với ODBC hoặc JDBC. dbShards cũng cho phép phân đoạn gợi ý nếu bạn muốn kiểm soát nhiều hơn giao dịch. Bạn có thể cho dbShards biết chính xác phân đoạn bạn muốn đọc hoặc viết.
chantheman

1
@Gigala tốt, dành thời gian soạn một câu trả lời rõ ràng như thế này, bất kể độ rộng, cũng không cần thiết, nhưng tôi rất vui vì nó đã được thực hiện, vì câu trả lời này đã được chứng minh là hữu ích cho tôi. Xin vui lòng không khuyến khích người dùng không "suy nghĩ bên ngoài" khi trả lời.
mewm

12
  1. Sharding cấp độ ứng dụng: dbShards là sản phẩm duy nhất mà tôi biết về nó có chức năng "phân tích ứng dụng". Có một vài bài báo hay trên trang web. Theo định nghĩa, sharding nhận biết ứng dụng sẽ hiệu quả hơn. Nếu một ứng dụng biết chính xác nơi cần đến với một giao dịch mà không cần phải tra cứu nó hoặc được chuyển hướng bởi một proxy, thì tự nó sẽ nhanh hơn. Và tốc độ thường là một trong những mối quan tâm chính, nếu không phải là mối quan tâm duy nhất, khi ai đó đang tìm hiểu về sharding.

  2. Một số người "shard" với một proxy, nhưng trong mắt tôi điều đó đánh bại mục đích của sharding. Bạn chỉ đang sử dụng một máy chủ khác để cho các giao dịch của bạn biết nơi tìm dữ liệu hoặc nơi lưu trữ dữ liệu. Với tính năng sharding nhận biết ứng dụng, ứng dụng của bạn sẽ tự biết đi đâu. Hiệu quả hơn nhiều.

  3. Điều này giống với # 2 thực sự.


dbShards được sử dụng trong sản xuất một số nơi? nó cũng không phải là mã nguồn mở.
sheki

Ngoài ra, cách tiếp cận 2 và 3 có thể khác nhau nếu proxy tìm kiếm dựa trên một hàm băm thay vì DB hoặc một cửa hàng.
sheki

1
dbShards đang được sản xuất với nhiều loại khách hàng, nhưng không, nó không phải là mã nguồn mở. Tôi không nghĩ rằng bạn sẽ tìm thấy một sản phẩm sharding mã nguồn mở tốt. Và vâng, bạn nói đúng rằng một băm có thể được sử dụng để tra cứu, nhưng trong trường hợp đó, bạn vẫn phải thực hiện thêm một lần "dừng" để đưa giao dịch của mình vào cơ sở dữ liệu. Đó là lý do tại sao sharding "nhận biết ứng dụng" hầu như sẽ luôn nhanh hơn.
chantheman

Nhưng như tôi đã nói, nếu bạn có thể có được một ứng dụng sharding duy trì tính toàn vẹn của các mối quan hệ, thì bạn sẽ có phong độ tốt. Tôi đề cập đến dbShards bởi vì nó là người duy nhất tôi biết về điều đó. Và kể từ khi có, nó sẽ chia tỷ lệ tốc độ ghi và đọc của bạn một cách tuyến tính. Bạn thêm 4 "mảnh" hoặc bạn chia một máy chủ MySQL của mình thành 4 và nó sẽ chạy nhanh gấp 4 lần.
chantheman

7

Bạn có biết bất kỳ dự án hoặc công cụ thú vị nào trong lĩnh vực này không?

Một số dự án mới trong không gian này:

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

5

Shard-Query là một giải pháp sharding dựa trên OLAP cho MySQL. Nó cho phép bạn xác định sự kết hợp của bảng được phân đoạn và bảng không được đánh dấu. Các bảng không được đánh dấu (như bảng tra cứu) có thể kết hợp tự do với các bảng được phân đoạn và các bảng được phân đoạn có thể được nối với nhau miễn là các bảng được nối bằng khóa phân đoạn (không có phân đoạn chéo hoặc tự tham gia mà vượt qua ranh giới phân đoạn). Là một giải pháp OLAP, Shard-Query thường có thời gian phản hồi tối thiểu là 100ms hoặc ít hơn, ngay cả đối với các truy vấn đơn giản vì vậy nó sẽ không hoạt động đối với OLTP. Shard-Query được thiết kế để phân tích song song các bộ dữ liệu lớn.

Các giải pháp sharding OLTP cũng tồn tại cho MySQL. Các giải pháp nguồn đóng bao gồm ScaleDB , DBShards . Giải pháp OLTP mã nguồn mở bao gồm JetPants , Cubrid hoặc Flock / Gizzard (cơ sở hạ tầng Twitter).


3

Mức độ ứng dụng của khóa học.

Cách tiếp cận tốt nhất mà tôi từng thấy trong cuốn sách này

MySQL hiệu suất cao http://www.amazon.com/High-Performance-MySQL-Jeremy-Zawodny/dp/0596003064

Mô tả ngắn gọn: bạn có thể chia dữ liệu của mình thành nhiều phần và lưu trữ ~ 50 phần trên mỗi máy chủ. Nó sẽ giúp bạn tránh được vấn đề lớn thứ hai của sharding - tái cân bằng. Chỉ cần di chuyển một số người trong số họ sang máy chủ mới và mọi thứ sẽ ổn :)

Tôi thực sự khuyên bạn nên mua nó và đọc phần "chia tỷ lệ mysql".


Cuốn sách mà bạn đề xuất là cuốn sách 8 tuổi ... nó có đề cập đến những nét liên quan đến công nghệ ngày nay không?
raffian

1
Nó bao gồm một số cách tiếp cận cơ bản để mở rộng mysql. AFAIK không có gì thay đổi trong việc mở rộng mysql. Các kỹ thuật nhân rộng và nhân bản cấp ứng dụng tương tự được sử dụng rộng rãi ngày nay.
Andrey Frolov

Tôi có thể sai, nhưng tôi đã thực hiện rất nhiều nghiên cứu về vấn đề này trong tuần qua và có vẻ như bản thân mySQL đã thực hiện rất nhiều thay đổi trong 8 năm qua, đặc biệt là về phân vùng và bộ nhớ đệm. Có một phiên bản mới ra mắt trong năm nay: amazon.com/High-Performance-MySQL-Optimization-Replication/dp/… Tôi chưa đọc nhưng tôi nghĩ nó bao gồm các mô hình sao chép mới có sẵn.
NateDSaint

4
Sách .. sao không giải thích ở đây.
DDD

2

Kể từ năm 2018, dường như có một giải pháp MySql-native cho điều đó. Thực tế có ít nhất 2 - Cụm InnoDBCụm NDB (có một phiên bản thương mại và cộng đồng của nó).

Vì hầu hết những người sử dụng phiên bản cộng đồng MySql đều quen thuộc hơn với công cụ InnoDB, đây là điều nên được ưu tiên hàng đầu. Nó hỗ trợ sao chép và phân vùng / phân vùng ra khỏi hộp và dựa trên MySql Router cho các tùy chọn định tuyến / cân bằng tải khác nhau.

Cú pháp để tạo bảng của bạn sẽ cần thay đổi, ví dụ:

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

(đây chỉ là một trong bốn kiểu phân vùng )

Một hạn chế rất quan trọng:

Các khóa ngoại InnoDB và phân vùng MySQL không tương thích. Bảng InnoDB được phân vùng không thể có tham chiếu khóa ngoại, cũng như không thể có các cột được tham chiếu bởi khóa ngoại. Các bảng InnoDB có hoặc được tham chiếu bởi các khóa ngoại không thể được phân vùng.


Hãy lưu ý rằng PARTITION BY HASH(YEAR...)sẽ quét tất cả các phân vùng nếu bạn có phạm vi ngày. Kinh quá.
Rick James
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.