Có rất nhiều bài báo trực tuyến mô tả các mẫu khả năng mở rộng cơ sở dữ liệu, nhưng chúng chủ yếu là các bài báo rải rác - chỉ là các kỹ thuật được định nghĩa một cách lộn xộn mà không có nhiều ngữ cảnh. Tôi thấy rằng chúng không được xác định theo cách từng bước và không thảo luận khi nào nên chọn tùy chọn mở rộng nào, tùy chọn chia tỷ lệ nào khả thi trong thực tế và tại sao.
Vì vậy, tôi dự định sẽ thảo luận chi tiết về một số kỹ thuật trong các bài viết tới. Để bắt đầu, tôi cảm thấy sẽ tốt hơn nếu tôi thảo luận về các kỹ thuật từng bước với một số ngữ cảnh theo cách của riêng tôi. Bài viết này là một bài viết cấp cao - tôi sẽ không thảo luận chi tiết về các kỹ thuật scale ở đây, nhưng sẽ cung cấp một cái nhìn tổng quan. Vì vậy, hãy bắt đầu.
Một nghiên cứu điển hình
Giả sử bạn đã xây dựng một công ty khởi nghiệp cung cấp dịch vụ chia sẻ chuyến đi với chi phí rẻ. Ban đầu khi bạn bắt đầu, bạn nhắm mục tiêu đến một thành phố và hầu như không có hàng chục khách hàng sau quảng cáo ban đầu của bạn.
Bạn lưu tất cả khách hàng, chuyến đi, vị trí, dữ liệu đặt chỗ và lịch sử chuyến đi của khách hàng trong cùng một cơ sở dữ liệu hoặc rất có thể trong một máy vật lý duy nhất. Không có bộ nhớ đệm ưa thích hoặc đường ống dữ liệu lớn để giải quyết vấn đề vì ứng dụng của bạn còn rất mới. Điều này hoàn hảo cho trường hợp sử dụng của bạn tại thời điểm này vì có rất ít khách hàng và chẳng hạn như hệ thống của bạn hầu như không đặt trước 1 chuyến đi trong 5 phút.
Nhưng thời gian trôi qua, nhiều người bắt đầu đăng ký vào hệ thống của bạn vì bạn là dịch vụ rẻ nhất trên thị trường và nhờ vào chương trình khuyến mại và quảng cáo của bạn. Bạn bắt đầu đặt trước, chẳng hạn, 10 lượt đặt chỗ mỗi phút, và dần dần con số tăng lên 20, 30 lượt đặt chỗ mỗi phút.
Tại thời điểm này, bạn nhận ra rằng hệ thống đã bắt đầu hoạt động kém:độ trễ API đã tăng lên rất nhiều, và một số giao dịch bị bế tắc hoặc chết đói và cuối cùng chúng thất bại. Ứng dụng của bạn mất nhiều thời gian hơn để phản hồi, khiến khách hàng không hài lòng. Bạn có thể làm gì để giải quyết vấn đề?
Dạng 1 - Tối ưu hóa Truy vấn &Triển khai Nhóm Kết nối:
Giải pháp đầu tiên được nghĩ đến là bộ nhớ đệm thường xuyên sử dụng dữ liệu không động như lịch sử đặt phòng, lịch sử thanh toán, hồ sơ người dùng, v.v. Nhưng sau khi lưu vào bộ nhớ đệm lớp ứng dụng này, bạn không thể giải quyết vấn đề độ trễ của các API hiển thị dữ liệu động như vị trí của tài xế hiện tại hoặc các xe taxi gần nhất cho một khách hàng nhất định hoặc chi phí chuyến đi hiện tại tại một thời điểm nhất định sau khi chuyến đi bắt đầu.
Bạn xác định rằng cơ sở dữ liệu của mình có thể đã được chuẩn hóa rất nhiều, vì vậy bạn giới thiệu một số cột dư thừa (các cột này thường xuất hiện trong WHERE
hoặc JOIN ON
mệnh đề trong truy vấn) trong các bảng được sử dụng nhiều nhằm mục đích không chuẩn hóa. Điều này làm giảm các truy vấn nối, chia một truy vấn lớn thành nhiều truy vấn nhỏ hơn và thêm kết quả của chúng vào lớp ứng dụng.
Một cách tối ưu song song khác mà bạn có thể làm là điều chỉnh các kết nối cơ sở dữ liệu. Thư viện máy khách cơ sở dữ liệu và thư viện bên ngoài có sẵn trong hầu hết các ngôn ngữ lập trình. Bạn có thể sử dụng thư viện nhóm kết nối để đệm các kết nối cơ sở dữ liệu hoặc có thể định cấu hình kích thước nhóm kết nối trong chính hệ thống quản lý cơ sở dữ liệu.
Việc tạo bất kỳ kết nối mạng nào cũng tốn kém vì nó yêu cầu một số giao tiếp qua lại giữa máy khách và máy chủ. Việc gộp các kết nối có thể giúp bạn tối ưu hóa số lượng kết nối. Thư viện nhóm kết nối có thể giúp bạn ghép kênh - nhiều luồng ứng dụng có thể sử dụng cùng một kết nối cơ sở dữ liệu. Tôi sẽ xem liệu tôi có thể giải thích chi tiết về việc gộp kết nối trong một bài viết riêng sau này không.
Đo lường độ trễ của các API của bạn và nhận thấy độ trễ có thể giảm từ 20–50% trở lên. Đây là cách tối ưu hóa tốt tại thời điểm này.
Giờ đây, bạn đã mở rộng quy mô kinh doanh của mình sang một thành phố nữa, nhiều khách hàng đăng ký hơn, bạn từ từ bắt đầu thực hiện 80–100 lượt đặt phòng mỗi phút. Hệ thống của bạn không thể xử lý quy mô này. Một lần nữa, bạn thấy độ trễ API đã tăng lên, lớp cơ sở dữ liệu đã từ bỏ, nhưng lần này, không có tối ưu hóa truy vấn nào mang lại cho bạn bất kỳ mức tăng hiệu suất đáng kể nào. Bạn kiểm tra chỉ số hệ thống, bạn thấy dung lượng ổ đĩa gần đầy, CPU bận 80% thời gian, RAM đầy rất nhanh.
Mẫu 2 - Chia tỷ lệ theo chiều dọc hoặc Tăng tỷ lệ:
Sau khi kiểm tra tất cả các chỉ số hệ thống, bạn biết rằng không có giải pháp nào khác dễ dàng hơn là nâng cấp phần cứng của hệ thống. Bạn nâng cấp kích thước RAM của mình lên 2 lần, nâng cấp dung lượng ổ đĩa lên gấp 3 lần hoặc hơn. Đây được gọi là mở rộng quy mô theo chiều dọc hoặc mở rộng hệ thống của bạn. Bạn thông báo cho nhóm cơ sở hạ tầng của mình hoặc nhóm phát triển hoặc đại lý trung tâm dữ liệu của bên thứ ba để nâng cấp máy của bạn.
Nhưng làm cách nào để thiết lập máy tính theo tỷ lệ dọc?
Bạn phân bổ một máy lớn hơn. Một cách tiếp cận là không di chuyển dữ liệu theo cách thủ công từ máy cũ thay vì đặt máy mới là replica
vào máy hiện có (primary
) -tạo một primary replica
cấu hình. Hãy để việc nhân rộng diễn ra một cách tự nhiên. Khi quá trình nhân bản được thực hiện xong, hãy thăng cấp máy mới thành máy chính và đưa máy cũ vào ngoại tuyến. Vì máy lớn hơn được mong đợi sẽ phục vụ tất cả yêu cầu, nên tất cả việc đọc / ghi sẽ diễn ra trên máy này.
Ngầu. Hệ thống của bạn đang hoạt động trở lại với hiệu suất tăng lên.
Doanh nghiệp của bạn đang hoạt động rất tốt và bạn quyết định mở rộng quy mô đến 3 thành phố nữa - hiện tại bạn đang hoạt động tại 5 thành phố. Lưu lượng truy cập gấp 3 lần so với trước đó, bạn dự kiến sẽ thực hiện khoảng 300 lượt đặt chỗ mỗi phút. Trước khi đạt được mục tiêu đặt phòng này, bạn lại gặp phải vấn đề về hiệu suất, kích thước chỉ mục cơ sở dữ liệu đang tăng lên rất nhiều trong bộ nhớ, nó cần được bảo trì liên tục, quá trình quét bảng với chỉ mục ngày càng chậm hơn bao giờ hết. Bạn tính toán chi phí mở rộng máy thêm nhưng không thấy thuyết phục với chi phí bỏ ra. Bạn làm gì bây giờ?
Mẫu 3 - Phân tách Trách nhiệm Truy vấn Lệnh (CQRS):
Bạn xác định rằng máy lớn không thể xử lý tất cả read/write
các yêu cầu. Ngoài ra trong hầu hết các trường hợp, bất kỳ công ty nào cũng cần khả năng giao dịch trên write
nhưng không có trên read
các hoạt động. Bạn cũng không sao với một chút read
không nhất quán hoặc chậm trễ hoạt động và doanh nghiệp của bạn cũng không có vấn đề gì với điều đó. Bạn thấy một cơ hội mà nó có thể là một lựa chọn tốt để tách read
&write
hoạt động vật lý máy khôn ngoan. Nó sẽ tạo phạm vi cho các máy riêng lẻ để xử lý nhiều read/write
hơn các hoạt động.
Bây giờ bạn lấy thêm hai máy lớn và thiết lập chúng dưới dạng replica
vào máy hiện tại. Sao chép cơ sở dữ liệu sẽ đảm nhận việc phân phối dữ liệu từ primary
máy thành replica
máy móc. Bạn điều hướng tất cả các truy vấn đã đọc (Truy vấn (Q
) trong CQRS
) đến các bản sao - bất kỳ replica
nào có thể phục vụ bất kỳ yêu cầu đọc nào, bạn điều hướng tất cả các truy vấn ghi (Command (C
) trong CQRS
) đến primary
. Có thể có một chút độ trễ trong việc sao chép, nhưng theo trường hợp sử dụng của doanh nghiệp bạn thì điều đó ổn.
Hầu hết các công ty khởi nghiệp quy mô trung bình phục vụ vài trăm nghìn yêu cầu mỗi ngày có thể tồn tại với thiết lập bản sao chính miễn là họ lưu trữ định kỳ dữ liệu cũ hơn.
Bây giờ bạn mở rộng quy mô đến 2 thành phố nữa, bạn thấy rằng primary
của bạn không thể xử lý tất cả write
các yêu cầu. Nhiều write
yêu cầu đang có độ trễ. Hơn nữa, độ trễ giữa primary
&replica
đôi khi tác động đến khách hàng và tài xế, ví dụ:khi chuyến đi kết thúc, khách hàng thanh toán thành công cho tài xế, nhưng tài xế không thể thấy khoản thanh toán vì hoạt động của khách hàng là write
yêu cầu chuyển đến primary
, trong khi hoạt động của người lái xe là read
yêu cầu chuyển đến một trong các bản sao. Hệ thống tổng thể của bạn quá chậm đến mức tài xế không thể nhìn thấy khoản thanh toán trong ít nhất nửa phút - điều này gây khó chịu cho cả tài xế và khách hàng. Bạn giải quyết nó như thế nào?
Mẫu 4 - Nhiều bản sao chính
Bạn đã mở rộng quy mô thực sự tốt với primary-replica
nhưng bây giờ bạn cần hiệu suất ghi nhiều hơn. Bạn có thể sẵn sàng thỏa hiệp một chút về read
yêu cầu hiệu suất. Tại sao không phân phối yêu cầu ghi tới một replica
còn nữa?
Trong một multi-primary
cấu hình, tất cả các máy có thể hoạt động như cả primary
&replica
. Bạn có thể nghĩ đến multi-primary
như một vòng tròn máy nói A->B->C->D->A
. B
có thể sao chép dữ liệu từ A
, C
có thể sao chép dữ liệu từ B
, D
có thể sao chép dữ liệu từ C
, A
có thể sao chép dữ liệu từ D
. Bạn có thể ghi dữ liệu vào bất kỳ nút nào, trong khi đọc dữ liệu, bạn có thể truyền phát truy vấn đến tất cả các nút, bất kỳ ai trả lời sẽ trả lời đó. Tất cả các nút sẽ có cùng một lược đồ cơ sở dữ liệu, cùng một tập hợp các bảng, chỉ mục, v.v. Vì vậy, bạn phải đảm bảo rằng không có xung đột trong id
giữa các nút trong cùng một bảng, nếu không trong quá trình phát sóng, nhiều nút sẽ trả về dữ liệu khác nhau cho cùng một id
.
Nói chung tốt hơn nên sử dụng UUID
hoặc GUID
cho id. Một nhược điểm nữa của kỹ thuật này là - read
các truy vấn có thể không hiệu quả vì nó liên quan đến việc truyền phát truy vấn và nhận được kết quả chính xác - về cơ bản phương pháp thu thập phân tán.
Bây giờ bạn mở rộng quy mô đến 5 thành phố nữa và hệ thống của bạn lại bị ảnh hưởng. Bạn dự kiến sẽ xử lý khoảng 50 yêu cầu mỗi giây. Bạn đang cần xử lý số lượng lớn các yêu cầu đồng thời. Làm thế nào để bạn đạt được điều đó?
Pattern 5 - Partitioning:
Bạn biết rằng location
của mình cơ sở dữ liệu là thứ gì đó đang trở nên cao hơn write
&read
giao thông. Có thể là write:read
tỷ lệ là 7:3
. Điều này đang gây ra rất nhiều áp lực cho các cơ sở dữ liệu hiện có. Vị trí location
bảng chứa ít dữ liệu chính như longitude
, latitude
, timestamp
, driver id
, trip id
v.v ... Nó không liên quan nhiều đến các chuyến đi của người dùng, dữ liệu người dùng, dữ liệu thanh toán, v.v. Còn việc tách location
thì sao bảng trong một lược đồ cơ sở dữ liệu riêng biệt? Còn việc đặt cơ sở dữ liệu đó vào các máy riêng biệt với primary-replica
thích hợp thì sao hoặc multi-primary
cấu hình?
Đây được gọi là phân vùng dữ liệu theo chức năng. Các cơ sở dữ liệu khác nhau có thể lưu trữ dữ liệu được phân loại theo chức năng khác nhau, nếu được yêu cầu, kết quả có thể được tổng hợp trong lớp back end. Sử dụng kỹ thuật này, bạn có thể tập trung vào việc mở rộng quy mô tốt các chức năng yêu cầu read/write
cao các yêu cầu. Mặc dù kết thúc phía sau hoặc lớp ứng dụng phải chịu trách nhiệm kết hợp các kết quả khi cần thiết, dẫn đến có thể có nhiều thay đổi mã hơn.
Bây giờ, hãy tưởng tượng bạn đã mở rộng hoạt động kinh doanh của mình lên tổng cộng 20 thành phố trong quốc gia của bạn và có kế hoạch mở rộng sang Úc sớm. Nhu cầu ngày càng tăng của bạn về ứng dụng đòi hỏi phản hồi nhanh hơn và nhanh hơn. Không có phương pháp nào ở trên có thể giúp bạn đến cùng cực. Bạn phải mở rộng quy mô hệ thống của mình theo cách mà việc mở rộng sang các quốc gia / khu vực khác không phải lúc nào cũng cần bạn thực hiện các thay đổi về kỹ thuật hoặc kiến trúc thường xuyên. Làm thế nào để bạn làm điều đó?
Mẫu 6 - Tỷ lệ ngang:
Bạn tìm kiếm rất nhiều trên Google, đọc rất nhiều về cách các công ty khác đã giải quyết vấn đề - và đi đến kết luận rằng bạn cần mở rộng quy mô theo chiều ngang. Bạn phân bổ ví dụ 50 máy - tất cả đều có cùng một lược đồ cơ sở dữ liệu, lần lượt chứa cùng một tập hợp các bảng. Tất cả các máy chỉ giữ một phần dữ liệu.
Vì tất cả các cơ sở dữ liệu đều chứa cùng một tập hợp các bảng, nên bạn có thể thiết kế hệ thống theo cách mà địa phương của dữ liệu ở đó, tức là; tất cả dữ liệu liên quan đều nằm trong cùng một máy. Mỗi máy có thể có các bản sao của riêng chúng, các bản sao có thể được sử dụng để khắc phục lỗi. Mỗi cơ sở dữ liệu được gọi là shard
. Máy vật lý có thể có một hoặc nhiều shards
- tùy thuộc vào thiết kế của bạn theo cách bạn muốn. Bạn cần quyết định chọn sharding key
theo cách mà một sharding key
duy nhất luôn luôn đề cập đến cùng một máy. Vì vậy, bạn có thể tưởng tượng rất nhiều máy đều chứa dữ liệu liên quan trong cùng một tập hợp bảng, read/write
yêu cầu cho cùng một hàng hoặc cùng một tập hợp đất tài nguyên trong cùng một máy cơ sở dữ liệu.
Sharding nói chung là khó - ít nhất là các kỹ sư từ các công ty khác nhau nói như vậy. Nhưng khi bạn phục vụ hàng triệu hoặc hàng tỷ yêu cầu, bạn phải đưa ra quyết định khó khăn như vậy.
Tôi sẽ thảo luận về sharding
chi tiết hơn trong bài đăng tiếp theo của tôi, vì vậy tôi không muốn thảo luận thêm về bài đăng này.
Bây giờ vì bạn đã có sharding, bạn tự tin rằng bạn có thể mở rộng quy mô ra nhiều quốc gia. Doanh nghiệp của bạn đã phát triển đến mức các nhà đầu tư đang thúc đẩy bạn mở rộng quy mô kinh doanh trên khắp các châu lục. Bạn lại thấy một số vấn đề ở đây. Độ trễ API một lần nữa. Dịch vụ của bạn được tổ chức tại Hoa Kỳ và những người từ Việt Nam đang gặp khó khăn khi đặt vé. Tại sao? Bạn làm gì với nó?
Mẫu 7 - Phân vùng Khôn ngoan của Trung tâm Dữ liệu:
Doanh nghiệp của bạn đang phát triển ở Mỹ, Nam Á và một số quốc gia ở Châu Âu. Bạn đang thực hiện hàng triệu lượt đặt phòng hàng ngày với hàng tỷ lượt yêu cầu đến máy chủ của bạn. Xin chúc mừng - đây là thời điểm đỉnh cao cho công việc kinh doanh của bạn.
Nhưng vì các yêu cầu từ ứng dụng phải đi khắp các lục địa thông qua hàng trăm hoặc hàng nghìn máy chủ trên internet, độ trễ phát sinh. Điều gì về việc phân phối lưu lượng truy cập qua các trung tâm dữ liệu? Bạn có thể thiết lập một trung tâm dữ liệu ở Singapore để xử lý tất cả các yêu cầu từ Nam Á, trung tâm dữ liệu ở Đức có thể xử lý tất cả các yêu cầu từ các nước Châu Âu và một trung tâm dữ liệu ở California có thể xử lý tất cả các yêu cầu của Hoa Kỳ.
Ngoài ra, bạn kích hoạt tính năng sao chép trung tâm dữ liệu chéo để giúp khôi phục thảm họa. Vì vậy, nếu trung tâm dữ liệu California nhân rộng đến trung tâm dữ liệu Singapore, trong trường hợp trung tâm dữ liệu California bị sập do sự cố điện hoặc thiên tai, tất cả các yêu cầu của Hoa Kỳ có thể chuyển về trung tâm dữ liệu Singapore, v.v.
Kỹ thuật mở rộng quy mô này rất hữu ích khi bạn có hàng triệu khách hàng để phục vụ trên khắp các quốc gia và bạn không thể tránh khỏi bất kỳ trường hợp mất dữ liệu nào, bạn phải luôn duy trì tính khả dụng của hệ thống.
Đây là một số kỹ thuật từng bước chung để mở rộng cơ sở dữ liệu. Mặc dù hầu hết các kỹ sư không có đủ cơ hội để triển khai các kỹ thuật này, nhưng về tổng thể, tốt hơn hết là bạn nên có ý tưởng rộng hơn về hệ thống như vậy, trong tương lai có thể giúp bạn thiết kế hệ thống và kiến trúc tốt hơn.
Trong các bài viết tiếp theo của tôi, tôi sẽ cố gắng thảo luận chi tiết về một số khái niệm. Vui lòng đưa ra phản hồi thích hợp cho bài đăng này nếu có.
Bài viết ban đầu được đăng trên tài khoản phương tiện của tác giả:https://medium.com/@kousiknath/und hieu-database-scaling-patterns-ac24e5223522