8 phút

SQL phân tán: Khi nào nên dùng Spanner, CockroachDB, YugabyteDB

Tìm hiểu khi nào SQL phân tán xứng đáng với chi phí, cách Spanner, CockroachDB và YugabyteDB khác nhau, cùng cách lập kế hoạch khối lượng công việc đa khu vực an toàn.

SQL phân tán: Khi nào nên dùng Spanner, CockroachDB, YugabyteDB

SQL phân tán là gì

SQL phân tán là kiến trúc cơ sở dữ liệu quan hệ, phân bố dữ liệu và xử lý giao dịch trên nhiều máy nhưng vẫn cung cấp cho ứng dụng một cơ sở dữ liệu SQL logic duy nhất. Nó giữ lại bảng, join, chỉ mục, ràng buộc và giao dịch ACID, rồi bổ sung tính năng tự động phân vùng, sao chép và phục hồi khi lỗi.

Một hệ thống thường được xếp vào nhóm này khi có các đặc điểm sau:

  • Schema quan hệ và giao diện truy vấn SQL
  • Mở rộng ngang trên các node cơ sở dữ liệu
  • Tính nhất quán giao dịch giữa các phân vùng
  • Sao chép và failover tự động
  • Hoạt động phối hợp như một cơ sở dữ liệu logic duy nhất

Định nghĩa này quan trọng vì cơ sở dữ liệu không trở thành SQL phân tán chỉ nhờ thêm read replica cho PostgreSQL hoặc MySQL. Mô hình primary kèm replica vẫn gửi ghi qua một máy chủ chính. Sharding do ứng dụng quản lý phân tán việc ghi, nhưng buộc ứng dụng tự quyết định bản ghi nằm ở đâu và công việc liên shard hoạt động ra sao. SQL phân tán chuyển phần lớn trách nhiệm đó vào cơ sở dữ liệu.

Vị trí giữa RDBMS truyền thống và NoSQL

SQL phân tán kết hợp mô hình lập trình quan hệ của RDBMS truyền thống với thiết kế mở rộng ngang thường thấy ở kho dữ liệu phân tán. Triển khai PostgreSQL và MySQL truyền thống hoạt động tốt khi một primary có thể xử lý tải ghi và lỗi khu vực không đòi hỏi phải tiếp tục ghi ở nơi khác. Read replica, cache, connection pool và chỉ mục tốt hơn có thể kéo dài mô hình đó trong nhiều năm.

Nhiều cơ sở dữ liệu NoSQL chọn cách phân tán đơn giản hơn bằng cách hạn chế join, giao dịch hoặc bảo đảm nhất quán. Những lựa chọn này vẫn hợp lý cho các khối lượng công việc như luồng sự kiện lớn, cache có thể bỏ đi và các bản ghi hiếm khi tham gia giao dịch nhiều hàng. Cụm quan hệ phải phối hợp nhiều hơn vì ứng dụng kỳ vọng ràng buộc và giao dịch vẫn hợp lệ sau khi dữ liệu được chia giữa các node.

Khác biệt thực tế nằm ở việc ai sở hữu độ phức tạp. Với sharding thủ công, nhóm ứng dụng tự triển khai định tuyến, cân bằng lại dữ liệu, phối hợp thay đổi schema và xử lý các thao tác chạm đến nhiều shard. Với SQL phân tán, cơ sở dữ liệu cung cấp những cơ chế này, dù kỹ sư vẫn phải thiết kế schema và truy vấn cho một hệ thống qua mạng.

Những vấn đề mà nó được thiết kế để giải quyết

SQL phân tán được thiết kế cho ứng dụng có yêu cầu về khả dụng, vị trí địa lý hoặc mức tăng trưởng ghi đã vượt quá kiến trúc một primary. Các ví dụ phổ biến gồm dịch vụ SaaS toàn cầu, hệ thống đặt chỗ không được bán vượt và sổ cái tài chính mà các bất biến phải tồn tại qua lỗi node.

Nó có thể loại bỏ nhu cầu sharding ở tầng ứng dụng và giảm sự phụ thuộc vào một vị trí ghi duy nhất. Nó cũng có thể đặt dữ liệu gần người dùng hoặc trong các khu vực pháp lý được phê duyệt. Những lợi ích này phải trả giá bằng nhiều replica hơn, lưu lượng mạng lớn hơn, nhiều phối hợp hơn và các kiểu lỗi không tồn tại trên một máy chủ.

Cơ sở dữ liệu quan hệ được quản lý thông thường vẫn là lựa chọn mặc định tốt hơn khi khối lượng công việc vừa vặn trong một khu vực. SQL phân tán xứng đáng với chi phí khi sharding tùy biến, failover khu vực hoặc kiểm soát dữ liệu theo địa lý nếu không sẽ trở thành một hệ thống kỹ thuật lớn riêng biệt.

SQL phân tán hoạt động như thế nào bên trong

SQL phân tán hoạt động bằng cách chia dữ liệu thành các phân vùng được sao chép và phối hợp thay đổi bằng giao thức đồng thuận cùng giao dịch phân tán. Cơ sở dữ liệu che giấu phần lớn cơ chế này sau SQL, nhưng hành vi của chúng vẫn ảnh hưởng đến độ trễ, thông lượng, thiết kế schema và phản ứng sự cố.

Phân vùng quyết định nơi bản ghi nằm

Một cụm chia các bảng logic thành những đơn vị nhỏ hơn có thể di chuyển độc lập giữa các node. Spanner thường gọi các đơn vị này là split, CockroachDB dùng range và YugabyteDB dùng tablet. Mỗi đơn vị bao phủ một phần không gian khóa của bảng hoặc chỉ mục.

Ranh giới phân vùng có thể theo range, hash hoặc quy tắc địa lý rõ ràng. Range được sắp theo mã khách hàng giúp quét các bản ghi liên quan dễ hơn, nhưng mã tăng dần có thể dồn các lần ghi mới vào một phân vùng. Phân bố hash trải đều ghi hơn, dù có thể làm việc quét có thứ tự hoặc đặt tenant khó hơn. Nhiều schema sản xuất kết hợp mã tenant với một giá trị khác để dữ liệu liên quan vẫn dễ truy cập mà không dồn mọi lần ghi vào một nơi.

Chỉ mục thứ cấp cần kho lưu trữ phân tán riêng. Vì thế, một lần ghi vào một hàng có thể cập nhật bảng gốc và nhiều mục chỉ mục ở các phân vùng khác nhau. Một chỉ mục rẻ trên máy chủ đơn có thể tạo thêm công việc đồng thuận và lưu lượng mạng trong cụm.

Sao chép và đồng thuận bảo vệ từng phân vùng

Mỗi phân vùng thường có nhiều replica và một nhóm đồng thuận quyết định chuỗi thay đổi được chấp nhận. CockroachDB và YugabyteDB dùng sao chép dựa trên Raft. Spanner dùng sao chép dựa trên Paxos cùng hạ tầng thời gian của mình.

Leader hoặc leaseholder phối hợp việc ghi cho một nhóm replica. Hệ thống ghi nhận thay đổi trên đủ replica để tạo quorum trước khi coi nó đã commit. Nếu một node biến mất, các thành viên còn lại có thể bầu hoặc chỉ định một điều phối viên khác, miễn là quorum vẫn còn.

Quorum là yêu cầu toán học, không phải cam kết rằng mọi sự cố đều vô hại. Nhóm ba replica thường chịu được một replica không khả dụng. Mất hai thành viên nghĩa là bản sao còn lại không thể nhận ghi một cách an toàn vì không thể chứng minh rằng đa số khác chưa tiến triển ở nơi khác. Việc đặt replica giữa các miền lỗi quan trọng không kém số lượng replica.

Giao dịch phân tán phối hợp nhiều phân vùng

Một giao dịch chỉ chạm một phân vùng thường có thể hoàn tất với ít phối hợp. Giao dịch liên quan đến nhiều phân vùng cần một quyết định commit chung để mọi bên tham gia hoặc áp dụng ghi hoặc hủy chúng.

Giao thức cụ thể khác nhau theo sản phẩm, nhưng công việc thường gồm đọc hoặc khóa phiên bản liên quan, xác thực thay đổi đồng thời, sao chép intent hoặc bản ghi tạm thời và hoàn tất commit. Giao dịch dài làm tăng khoảng thời gian xảy ra xung đột. Batch lớn có thể liên quan đến nhiều nhóm đồng thuận và tạo đột biến độ trễ dù từng câu lệnh trông đơn giản.

Đó là lý do thiết kế giao dịch có ý thức về mạng rất quan trọng. Nhóm các hàng liên quan dưới tiền tố phân vùng tương thích khi cơ sở dữ liệu hỗ trợ chiến lược này. Giữ giao dịch ngắn, tránh chờ dịch vụ bên ngoài khi giao dịch đang mở và đừng đưa hàng nghìn bản ghi không liên quan vào một đơn vị nguyên tử khi chưa đo tác động.

Thời gian và thứ tự cần cơ chế rõ ràng

Các node phân tán không dùng chung đồng hồ vật lý được đồng bộ hoàn hảo, vì vậy mỗi sản phẩm cần cách sắp thứ tự giao dịch. Spanner dùng biên độ bất định TrueTime và chờ commit để cung cấp nhất quán bên ngoài. Hệ thống khác có thể kết hợp đồng hồ vật lý với thành phần logic, theo dõi phụ thuộc và giao thức giao dịch.

Việc phối hợp đồng hồ ảnh hưởng đến các thao tác như thực thi serializable, follower read và snapshot. Ứng dụng nên dùng timestamp giao dịch của cơ sở dữ liệu thay vì cho rằng timestamp tạo bởi các máy chủ ứng dụng riêng lẻ tạo ra thứ tự toàn cục đáng tin cậy.

Locality kiểm soát đường đi qua mạng

Cấu hình locality quyết định replica nằm ở đâu và khu vực nào phối hợp việc ghi của một bản ghi. Đọc có thể nhanh khi một replica phù hợp ở gần bên gọi. Ghi có thứ tự mạnh vẫn phải đến các replica cần cho quorum, vì vậy độ trễ phản ánh topology đã chọn.

Cách đặt tốt phải đi theo khối lượng công việc, không phải sơ đồ công ty. Nếu phần lớn ghi của tenant EU bắt nguồn ở châu Âu, đặt điều phối viên ghi của tenant đó tại đây tránh được chuyến đi liên lục địa ở đầu mỗi giao dịch. Bản ghi được chia sẻ toàn cầu, như một bộ đếm được mọi khu vực cập nhật, không thể ở gần mọi người ghi và có thể thành điểm tranh chấp.

Khi nào SQL phân tán là lựa chọn đúng

SQL phân tán phù hợp khi khả năng phục hồi theo địa lý, năng lực ghi ngang hoặc tính đúng đắn giữa các phân vùng quan trọng đến mức biện minh cho chi phí phối hợp liên tục. Một công ty lớn không mặc nhiên cần nó, và một sản phẩm nhỏ có thể cần nếu cam kết kinh doanh bao gồm khả dụng khu vực nghiêm ngặt.

Điều kiện đáng để đánh giá

Nên đánh giá nghiêm túc khi có nhiều điều kiện sau:

  • Dịch vụ phải tiếp tục hoạt động khi một zone hoặc khu vực ngừng hoạt động
  • Nhu cầu ghi sắp chạm giới hạn thực tế của một primary
  • Sharding thủ công sẽ tốn nhiều thời gian kỹ thuật ứng dụng
  • Giao dịch phải luôn chính xác giữa các node hoặc vị trí
  • Bản ghi cần vị trí địa lý có thể thực thi

Các điều kiện này nên được hỗ trợ bằng số liệu. Hãy xác định mục tiêu thời gian phục hồi, mục tiêu điểm phục hồi, độ trễ giao dịch, tốc độ ghi đỉnh và miền lỗi. Yêu cầu mơ hồ về quy mô toàn cầu không đủ để chọn kiến trúc.

Chỉ có người dùng ở nhiều khu vực chưa phải lý do quyết định. Ứng dụng nhiều nội dung có thể đặt máy chủ web và cache gần người dùng trong khi vẫn giữ một khu vực cơ sở dữ liệu. Read replica có thể hỗ trợ duyệt theo khu vực nếu chấp nhận kết quả cũ một chút. Lý do trở nên thuyết phục hơn khi người dùng ở nhiều nơi phải ghi với độ trễ thấp vào dữ liệu liên quan.

Điều kiện nghiêng về cơ sở dữ liệu đơn giản hơn

Dịch vụ quan hệ truyền thống thường phù hợp hơn khi lưu lượng vừa phải, ghi xuất phát từ một khu vực và quá trình phục hồi có thể gồm việc chuyển primary cơ sở dữ liệu theo kế hoạch. Nó có công cụ trưởng thành, tương thích extension rộng, cách gỡ lỗi quen thuộc và chi phí hạ tầng nhỏ hơn.

Yêu cầu độ trễ chặt chẽ cũng có thể nghiêng về một primary theo khu vực. Ghi bền vững cục bộ có thể hoàn tất nhanh hơn nhiều so với ghi quorum đi qua các khu vực xa. Hệ thống thiên về phân tích thường nên tách giao dịch vận hành khỏi các truy vấn quét dài, thay vì mong cùng một cụm làm tốt cả hai.

Năng lực đội ngũ cũng quan trọng. Dịch vụ quản lý giảm việc về phần cứng, vá lỗi và vận hành control plane, nhưng không loại bỏ tranh chấp schema, retry giao dịch, lập kế hoạch truy vấn, quản lý dung lượng hoặc xử lý sự cố ở phía ứng dụng. Nếu đội không có thời gian kiểm thử hành vi lỗi, việc dùng cơ sở dữ liệu phân tán có thể tăng rủi ro.

Ngưỡng quyết định dựa trên phương án thay thế

Lý do mạnh nhất xuất hiện khi phương án thay thế vốn đã phức tạp. Nếu kỹ sư sắp phải xây dựng định tuyến tenant, shard map, quy tắc giao dịch liên shard, quy trình chuyển vùng và công cụ migration riêng, một cơ sở dữ liệu cung cấp các chức năng đó đáng được đánh giá kỹ.

Nếu phương án thay thế là một PostgreSQL được quản lý với read replica và backup đã kiểm thử, việc migration cần bằng chứng rõ ràng. Hãy benchmark hệ thống hiện tại trước. CPU bão hòa thực ra có thể do truy vấn kém hiệu quả, quản lý kết nối yếu, quá nhiều chỉ mục hoặc thiếu cache chứ không phải cần ghi ngang.

Tính nhất quán, tính sẵn sàng và độ trễ

SQL phân tán thường giữ tính nhất quán giao dịch khi có lỗi bằng cách từ chối thao tác không thể đạt quorum cần thiết. Hành vi này bảo vệ trạng thái đã commit, nhưng khiến một số yêu cầu có thể thất bại hoặc phải chờ khi mạng bị phân vùng.

CAP mô tả hành vi khi có lỗi

Định lý CAP áp dụng khi liên lạc giữa các phần của cụm bị gián đoạn. Với dữ liệu bị ảnh hưởng, hệ thống không thể đồng thời bảo đảm tính nhất quán tuyến tính và phản hồi thành công từ mọi phía bị cô lập. Cơ sở dữ liệu ưu tiên nhất quán cho phía có quorum tiếp tục hoạt động và từ chối ghi không an toàn ở nơi khác.

CAP không giải thích độ trễ khi vận hành bình thường. Ngay cả khi mọi kết nối đều hoạt động, replica vẫn phải giao tiếp. Quyết định kỹ thuật rộng hơn gồm điều gì xảy ra khi phân vùng mạng và ứng dụng chấp nhận mức phối hợp nào khi hệ thống khỏe mạnh.

Ứng dụng phải xử lý rõ ràng các kết quả không khả dụng. Timeout, lỗi giao dịch có thể retry và mất tạm thời vùng ghi đều là khả năng bình thường. Trả về thành công từ cả hai khu vực bị cô lập sẽ tệ hơn với số dư hoặc đặt chỗ vì việc đối soát có thể không có câu trả lời tự động hợp lệ.

Đọc mạnh và đọc cố ý cũ khác nhau

Đọc mạnh quan sát trạng thái cơ sở dữ liệu phù hợp với bảo đảm thứ tự được yêu cầu. Một số sản phẩm cũng cung cấp follower read hoặc bounded-staleness read, đánh đổi độ mới để có độ trễ thấp hơn và giảm công việc ở điều phối viên ghi.

Lựa chọn này nên theo trường dữ liệu được đọc. Mô tả sản phẩm thường chịu được replica cũ một chút. Mật khẩu vừa đổi, số dư tài khoản hiện tại hoặc tồn kho còn lại nên dùng đường đọc mạnh hoặc nhất quán theo phiên phù hợp. Ứng dụng không nên gắn mọi lần đọc là cũ để tăng tốc rồi xây lại tính đúng đắn trong mã dịch vụ.

Hành vi đọc sau ghi cần được kiểm thử với driver và tầng định tuyến thực tế. Sau cập nhật, yêu cầu tiếp theo có thể đến máy chủ ứng dụng hoặc endpoint cơ sở dữ liệu khác. Token phiên, ranh giới giao dịch hoặc cài đặt đọc mạnh có thể cần thiết để bảo đảm người dùng thấy thay đổi đã được chấp nhận.

Mức cô lập kiểm soát kết quả đồng thời

Mức cô lập giao dịch xác định những bất thường mà các giao dịch đồng thời có thể tạo ra. Serializable hướng đến việc khiến các giao dịch hoàn tất trông như chạy lần lượt, dù cơ sở dữ liệu thực thi chúng đồng thời.

Thực thi serializable có thể hủy một bên tham gia khi các thao tác đồng thời không thể sắp thứ tự an toàn. Việc hủy này bảo vệ khỏi kết quả sai, không phải cơ sở dữ liệu hỏng. Ứng dụng cần retry có giới hạn quanh toàn bộ giao dịch, gồm mọi lần đọc đã ảnh hưởng đến ghi.

Retry phải có tính idempotent ở bên ngoài cơ sở dữ liệu. Nếu mã gửi email hoặc gọi nhà cung cấp thanh toán trước khi giao dịch chắc chắn commit, retry có thể lặp lại tác dụng phụ. Hãy ghi sự kiện outbox trong giao dịch cơ sở dữ liệu, commit rồi để worker riêng gửi hành động bên ngoài.

Khoảng cách đặt sàn cho độ trễ ghi

Giao dịch liên khu vực không thể hoàn tất nhanh hơn các thông điệp giao thức yêu cầu. Một vòng đi 80 mili giây giữa các thành viên quorum góp thời gian thực trước cả khi tính thực thi truy vấn, bảo trì chỉ mục, công việc ứng dụng và xếp hàng.

Mẫu tốn kém thường là nhiều giao dịch tuần tự trong một hành động người dùng. Nếu checkout thực hiện chèn đơn hàng, giữ tồn kho, cập nhật trạng thái thanh toán và ghi audit thành bốn commit chặn, chi phí mạng sẽ tích lũy. Kết hợp các thay đổi cơ sở dữ liệu chung một kết quả nguyên tử có thể bỏ bớt vòng đi, trong khi lệnh gọi thanh toán bên ngoài nên nằm ngoài giao dịch đang mở.

Hãy đo độ trễ theo percentile thay vì trung bình. Chuyển leader, tranh chấp, nghẽn lưu trữ và retry xuất hiện ở phần đuôi. Thiết kế đạt mục tiêu median nhưng bỏ lỡ percentile thứ 99 khi cân bằng lại thông thường vẫn có thể gây lỗi người dùng rõ rệt.

So sánh Spanner, CockroachDB và YugabyteDB

Spanner, CockroachDB và YugabyteDB giải quyết các vấn đề phân tán tương tự nhưng khác nhau về mô hình triển khai, tính tương thích, cách triển khai giao dịch và giả định vận hành. Việc chọn giữa chúng cần kiểm thử hành vi ứng dụng thay vì chọn chỉ dựa trên nhãn SQL chung.

Hạng mụcGoogle SpannerCockroachDBYugabyteDB
Giao diện SQL chínhGoogleSQL hoặc dialect PostgreSQLSQL tương thích PostgreSQL qua wire protocol PostgreSQLYSQL tương thích PostgreSQL, kèm YCQL truy cập kiểu Cassandra
Nền tảng sao chépNhóm Paxos với thứ tự dựa trên TrueTimeSao chép Raft trên rangeSao chép Raft trên tablet
Cách cung cấp thường gặpCơ sở dữ liệu Google Cloud được quản lýDịch vụ cloud được quản lý hoặc tự quản lýDịch vụ cloud được quản lý hoặc tự quản lý
Điểm cần lưu ý về tính di độngDialect và hành vi đặc thù nền tảngKhác biệt về tính năng, extension và ngữ nghĩa PostgreSQLKhác biệt về phiên bản và tính năng giữa YSQL và PostgreSQL
Trường hợp đánh giá tự nhiênHệ thống Google Cloud cần đặt giao dịch toàn cầuĐội ngũ muốn phát triển theo hướng PostgreSQL với vận hành phân tánĐội ngũ muốn truy cập theo hướng PostgreSQL hoặc lựa chọn API SQL và kiểu Cassandra

Spanner phù hợp với chiến lược Google Cloud được quản lý

Spanner phù hợp với tổ chức sẵn sàng dùng cơ sở dữ liệu Google Cloud được quản lý và thiết kế theo dialect, topology cùng mô hình vận hành của nó. TrueTime hỗ trợ giao dịch nhất quán bên ngoài, nghĩa là các giao dịch đã commit tôn trọng thứ tự thời gian thực trong ngữ nghĩa đã công bố.

Dialect PostgreSQL của nó có thể giảm khác biệt về cú pháp SQL, nhưng dialect không đồng nghĩa tương đương hoàn toàn với PostgreSQL. Extension, hàm quản trị, system catalog, kiểu dữ liệu, driver và giả định của ORM vẫn cần xác minh. Đội ngũ nên kiểm kê mọi phụ thuộc cơ sở dữ liệu trước khi coi ứng dụng hiện có là có thể di chuyển.

Spanner đặc biệt đáng chú ý khi hệ thống mong muốn đã phụ thuộc vào danh tính, mạng, quan sát và kiểm soát khu vực của Google Cloud. Mô hình quản lý loại bỏ việc quản trị node cơ sở dữ liệu, dù thiết kế schema, tối ưu truy vấn, quota, quản lý chi phí và phục hồi ứng dụng vẫn là trách nhiệm của khách hàng.

CockroachDB phù hợp với ứng dụng phân tán theo hướng PostgreSQL

CockroachDB phù hợp với đội ngũ muốn truy cập ứng dụng kiểu PostgreSQL trong khi phân bố dữ liệu giao dịch qua các range. Nó mặc định cô lập serializable, vì vậy ứng dụng phải retry đúng các giao dịch bị từ chối do tranh chấp hoặc xung đột thứ tự.

Cần kiểm thử tính tương thích ở các tầng migration, driver và ORM. Extension PostgreSQL và hành vi chuyên biệt có thể không có hoặc khác. Truy vấn dựa vào execution plan trên một node cũng có thể hoạt động khác sau khi bảng và chỉ mục được chia giữa các range.

Di chuyển range và cân bằng lại tự động đơn giản hóa thay đổi dung lượng, nhưng lựa chọn primary key kém vẫn có thể tạo hot range. Các abstraction đa khu vực giúp biểu đạt locality của bảng, nhưng nhà phát triển phải quyết định bản ghi nào theo khu vực, bản ghi nào toàn cầu và ghi nên được phối hợp ở đâu.

YugabyteDB phù hợp với YSQL và yêu cầu API hỗn hợp

YugabyteDB phù hợp với ứng dụng coi trọng giao diện quan hệ tương thích PostgreSQL và có thể hưởng lợi từ API tương thích Cassandra riêng biệt. YSQL cung cấp bảng quan hệ và giao dịch phân tán, còn YCQL theo mô hình dữ liệu khác và không nên bị coi là một đường khác để thực hiện mọi thao tác YSQL.

Tầng lưu trữ của nó phân bố dữ liệu qua tablet. Thiết kế bảng, tách tablet, vị trí chỉ mục và phạm vi giao dịch ảnh hưởng đến cách công việc trải trên cụm. Ứng dụng PostgreSQL vẫn cần kiểm thử tương thích cho extension, hàm, công cụ và hành vi planner.

Sự sẵn có của các cách triển khai khác nhau có thể phù hợp với chính sách hạ tầng đòi hỏi kiểm soát vị trí. Khi tự quản lý, quyền kiểm soát này chuyển trách nhiệm vận hành sang khách hàng: nâng cấp, quy trình sửa chữa, dung lượng, quan sát, chứng chỉ, backup và kiểm thử lỗi đều cần chủ sở hữu.

Kiểm thử sản phẩm hữu ích dựa trên bằng chứng ứng dụng

So sánh hữu ích sẽ chạy cùng một khối lượng công việc đại diện trên từng sản phẩm khả thi. Hãy kiểm thử tạo schema, migration, SQL do ORM sinh ra, retry giao dịch, phục hồi backup, failover, sự kiện mở rộng và những truy vấn có lưu lượng lớn nhất.

Đừng chỉ so sánh số giao dịch mỗi giây cao nhất. Hãy ghi nhận độ trễ p50, p95 và p99; tỷ lệ xung đột và retry; byte truyền giữa các khu vực; hệ số khuếch đại lưu trữ; thời gian khôi phục và nỗ lực vận hành khi mô phỏng sự cố. Lựa chọn tốt nhất là lựa chọn đạt mục tiêu về tính đúng đắn và phục hồi với chi phí cùng gánh nặng vận hành chấp nhận được.

SaaS toàn cầu với người dùng theo khu vực

Tạo PoC nhanh
Khởi tạo ứng dụng React + Go và biến PoC SQL phân tán thành một sản phẩm có giao diện hoàn chỉnh.

Ứng dụng SaaS toàn cầu hưởng lợi từ SQL phân tán khi tenant cần vị trí dữ liệu theo khu vực và truy cập giao dịch mà không cần các stack cơ sở dữ liệu riêng cho từng nơi. Thiết kế hiệu quả nhất khi tenancy được thể hiện rõ trong schema và phần lớn giao dịch nằm trong một tenant.

Locality của tenant nên theo hợp đồng và lưu lượng

Mã tenant có thể dẫn dắt việc đặt dữ liệu để bản ghi châu Âu ở các vị trí châu Âu được phê duyệt, trong khi bản ghi của khách hàng khác ở quốc gia hoặc khu vực đã ký hợp đồng. Nhờ đó vẫn có một schema logic nhưng cho phép chính sách vật lý khác nhau.

Quy tắc đặt dữ liệu phải bao phủ nhiều hơn bảng gốc. Mục chỉ mục, change stream, dữ liệu tạm, backup và bản ghi xuất có thể chứa thông tin chịu quản lý. Chính sách ghim hàng nhưng gửi chỉ mục thứ cấp toàn cục sang nơi khác có thể vi phạm ranh giới dự kiến.

Cô lập tenant cũng ảnh hưởng đến hiệu năng. Tenant lớn có thể lấn át một phân vùng dùng chung hoặc chi phối một node. Có thể cần hash hoặc chia nhỏ phân vùng trong tenant đó, nhưng cần giữ khả năng truy cập hiệu quả cho giao dịch theo tenant.

Đọc theo khu vực cần chính sách độ mới rõ ràng

Dashboard đọc nhiều có thể dùng replica gần đó nếu chấp nhận dữ liệu chậm một chút. Thay đổi tài khoản, quyết định ủy quyền và màn hình xác nhận sau giao dịch cần hành vi mạnh hơn. Hãy phân loại đường truy vấn theo yêu cầu độ mới thay vì áp dụng một cài đặt chung toàn cục.

Vị trí ghi nên theo người ghi thông thường của từng tenant. Nếu nhân viên khách hàng chủ yếu làm việc ở Singapore, phối hợp ghi của họ ở châu lục khác tạo độ trễ không cần thiết. Quy trình di chuyển tenant nên cập nhật vị trí mà không mất ghi, vi phạm quy định lưu trú hoặc để cache ứng dụng vẫn trỏ đến vị trí cũ.

Mã ứng dụng toàn cầu phải chịu được di chuyển

Leader di chuyển, node khởi động lại và định tuyến thay đổi trong lúc bảo trì. Driver cần timeout hợp lý, chính sách retry, làm mới kết nối và logic khởi động lại giao dịch. Retry nên dùng jitter và có giới hạn để cụm quá tải không nhận một làn sóng yêu cầu lặp lại đồng bộ ngay lập tức.

Giám sát nên tách độ trễ người dùng theo khu vực và nhóm tenant. Trung bình toàn cầu có thể che giấu một nhóm khách hàng ở xa phải chịu thêm nhiều chuyến đi mạng. Trace identifier nối các span API với câu lệnh cơ sở dữ liệu giúp tìm lỗi locality dễ hơn.

Quy trình tài chính và sổ cái

Quy trình tài chính hưởng lợi khi ràng buộc và giao dịch cơ sở dữ liệu thực thi các bất biến sổ cái qua lỗi và yêu cầu đồng thời. Phân tán tự nó không tạo ra kế toán đúng, vì vậy schema phải mã hóa các quy tắc không thể vi phạm.

Sổ cái cần giữ chuỗi bút toán có thể kiểm toán

Sổ cái theo hướng append ghi mỗi chuyển động thành các bút toán thay vì liên tục thay một giá trị số dư không có lịch sử. Mỗi lần hạch toán cần mã giao dịch ổn định, tài khoản, số tiền, tiền tệ, timestamp nghiệp vụ và metadata tạo lập. Quy tắc ghi sổ kép phải được kiểm tra trước commit để ghi nợ và ghi có cân bằng trong đơn vị hạch toán.

Số dư cache có thể tăng tốc đọc, nhưng phải thay đổi trong cùng giao dịch với các bút toán hoặc được xem rõ là dữ liệu dẫn xuất. Job đối soát nên so sánh tổng dẫn xuất với bút toán nguồn và báo cáo chênh lệch mà không âm thầm viết lại lịch sử.

Hiếm khi cần thứ tự toàn cục cho mọi tài khoản. Giao dịch ảnh hưởng một tài khoản hoặc cặp chuyển khoản cần thứ tự nhất quán, còn các tài khoản không liên quan có thể chạy đồng thời. Thiết kế theo ranh giới này giảm tranh chấp so với một chuỗi hoặc hàng thanh toán toàn cục.

Idempotency giúp retry an toàn

API thanh toán, queue và webhook retry sau timeout, vì vậy mỗi thao tác nghiệp vụ cần khóa idempotency ổn định. Hãy thực thi tính duy nhất trong phạm vi đúng, như một merchant hoặc tài khoản, rồi tạo bản ghi thanh toán và bút toán trong một giao dịch cơ sở dữ liệu.

CREATE TABLE payment_attempts (
    account_id UUID NOT NULL,
    idempotency_key TEXT NOT NULL,
    provider_reference TEXT,
    status TEXT NOT NULL,
    created_at TIMESTAMPTZ NOT NULL,
    PRIMARY KEY (account_id, idempotency_key)
);

Nếu hai worker gửi cùng thao tác, ràng buộc duy nhất quyết định lần chèn nào thành công. Worker thua nên đọc bản ghi hiện có và trả về kết quả đã xác lập. Nó không được tạo một khoản phí nhà cung cấp thứ hai chỉ vì giao dịch cơ sở dữ liệu đã retry.

Lệnh gọi bên ngoài cần ranh giới giao dịch

Cơ sở dữ liệu không thể commit nguyên tử với nhà cung cấp thanh toán độc lập trừ khi cả hai cùng tham gia giao thức phối hợp chuyên biệt, điều mà phần lớn API công khai không có. Hãy để lệnh gọi mạng ngoài giao dịch cơ sở dữ liệu và mô hình hóa quy trình bằng trạng thái rõ ràng như pending, authorized, captured, failed và reversed.

Transactional outbox có thể xuất bản thay đổi đã commit cho worker phía sau. Consumer nên khử trùng lặp theo mã sự kiện vì thông điệp có thể được gửi nhiều lần. Cách này giúp xử lý có thể phục hồi mà không tuyên bố có một giao dịch duy nhất bất khả thi trên mọi dịch vụ.

Tài khoản nóng cần thiết kế theo khối lượng công việc

Chạy bảng lương, thanh toán marketplace và merchant lớn có thể tập trung ghi vào một tài khoản. Thêm node cơ sở dữ liệu không chia một hàng đang xung đột cho chúng. Các lựa chọn gồm phân vùng bút toán bất biến, bộ tích lũy theo kỳ, xếp hàng hạch toán cho một tài khoản hoặc cấu trúc phân cấp subaccount được xác định cẩn thận.

Hãy kiểm thử phân bố lệch thực tế. Lưu lượng tổng hợp đồng đều có thể khiến cụm trông như đã sẵn sàng trong khi một merchant sản xuất tạo xung đột serializable lặp lại. Tính đúng đắn là ưu tiên đầu, nhưng mô hình dữ liệu nên bộc lộ được sự đồng thời an toàn nơi quy tắc kế toán cho phép.

Tồn kho, đặt chỗ và giữ chỗ

Hệ thống tồn kho và đặt chỗ cần giao dịch phân bổ có thẩm quyền khi nhiều người có thể cùng yêu cầu một mặt hàng khan hiếm. Đọc nhanh về tình trạng còn hàng cải thiện trải nghiệm duyệt, nhưng chỉ đường commit mới quyết định ai nhận đơn vị cuối cùng.

Ghi có điều kiện ngăn bán vượt

Cập nhật có điều kiện chỉ có thể giữ hàng khi còn đủ. Số hàng bị ảnh hưởng cho ứng dụng biết việc phân bổ có thành công hay không.

UPDATE inventory
SET available = available - 1
WHERE sku = $1
  AND available > 0;

Câu lệnh này nên dùng chung giao dịch với bản ghi giữ chỗ. Đọc lượng còn trước rồi giảm sau tạo ra race condition, trừ khi mức cô lập và xử lý predicate bảo vệ quyết định. Ràng buộc cơ sở dữ liệu nên từ chối số lượng âm như một lớp an toàn khác.

Với ghế được chỉ định, ràng buộc duy nhất trên mã buổi diễn và mã ghế sẽ cho một lần đặt thắng. Tồn kho khách sạn thường được mô hình theo đêm phòng hoặc ngày của nhóm tồn kho để các kỳ lưu trú chồng lấp không thể chiếm cùng công suất. Đơn vị tranh chấp đúng phải xuất phát từ quy tắc nghiệp vụ.

Hold tách phân bổ khỏi thanh toán

Hold tạm thời giữ tồn kho khi thanh toán hoặc xác nhận người dùng diễn ra. Lưu thời hạn hết hạn và trạng thái của nó, rồi chuyển thành đặt chỗ xác nhận bằng giao dịch có điều kiện. Worker hết hạn chỉ nên giải phóng hold vẫn còn hoạt động vì xác nhận và hết hạn có thể tranh chấp.

Trì hoãn theo đồng hồ thực không đủ để bảo đảm giải phóng. Worker có thể dừng, queue có thể chậm và khu vực có thể lỗi. Truy vấn tính tồn kho có thể bán phải xử lý trạng thái hết hạn một cách nhất quán, trong khi job sửa chữa thu hồi các hold bị bỏ sót.

Thời lượng hold là quyết định về sản phẩm và công suất. Hold mười phút có thể hợp lý cho checkout, nhưng có thể khóa phần đáng kể của tồn kho khan hiếm trong thời gian cao điểm. Hãy đo tỷ lệ bỏ dở và thời gian hoàn tất thanh toán trước khi đặt thời lượng.

Tranh chấp cực cao không mở rộng tuyến tính

Hàng nghìn người mua cạnh tranh cho một hàng không thể trở nên song song chỉ nhờ thêm replica. Mỗi lần giảm thành công phải được sắp thứ tự với các lần khác. Kiểm soát nhận vào, queue, bucket tồn kho hoặc quota theo khu vực cấp trước có thể bảo vệ cơ sở dữ liệu khi mở bán.

Quota khu vực giảm phối hợp nhưng thay đổi ngữ nghĩa. Nếu châu Âu còn đơn vị chưa dùng trong khi khu vực khác bán hết, hệ thống cần cách an toàn để chuyển quota hoặc chấp nhận mất cân bằng tạm thời. Chỉ dùng mẫu này khi nghiệp vụ có thể xác định cách đối soát công suất khu vực.

Tính sẵn sàng cao và khôi phục thảm họa

Giữ quyền kiểm soát stack
Nắm quyền sở hữu mã nguồn để tiếp tục làm việc trong repo khi nguyên mẫu đã sẵn sàng.

SQL phân tán có thể duy trì dịch vụ qua các lỗi hạ tầng đã chọn khi vị trí replica, dung lượng dự phòng và hành vi ứng dụng phù hợp với mục tiêu dịch vụ xác định. Chỉ sao chép thôi chưa tạo ra kết quả đó.

SLO cần chỉ rõ miền lỗi

Mục tiêu uptime cần gắn với khối lượng công việc và kịch bản lỗi. Hãy xác định dịch vụ phải sống sót qua một node, một availability zone hay toàn bộ khu vực. Nêu rõ tỷ lệ lỗi và độ trễ chấp nhận được trong sự kiện, không chỉ sau khi phục hồi.

Cụm ba replica trong một tòa nhà có hồ sơ rủi ro khác ba replica trải qua các zone độc lập. Topology đa khu vực bảo vệ trước sự kiện rộng hơn nhưng tạo đường quorum dài hơn và cần đủ dung lượng còn lại để hấp thụ lưu lượng sau khi một địa điểm biến mất.

Mục tiêu thời gian phục hồi xác định dịch vụ phải trở lại nhanh thế nào. Mục tiêu điểm phục hồi xác định lượng dữ liệu đã commit có thể mất. Sao chép quorum đồng bộ có thể hỗ trợ mục tiêu không mất dữ liệu đã commit cho các lỗi được bao phủ, nhưng chỉ khi các replica cần thiết và đường ứng dụng hoạt động như thiết kế.

Failover tạo sự kiện ứng dụng nhìn thấy được

Thay đổi leader có thể ngắt giao dịch đang chạy, đóng kết nối và tăng độ trễ. Ứng dụng phải phân biệt kết quả cơ sở dữ liệu có thể retry với lỗi nghiệp vụ vĩnh viễn. Giao dịch thất bại nên khởi động lại như một đơn vị thay vì chỉ chạy lại câu lệnh cuối.

Connection pool có thể giữ endpoint đã chết sau sự cố. Health check, hành vi DNS, load balancer, xác thực chứng chỉ và khả năng khám phá topology của driver thuộc kế hoạch kiểm thử. Cơ sở dữ liệu có thể khỏe nhưng ứng dụng vẫn không tìm được nó.

Dung lượng sau lỗi cần được tính rõ ràng. Nếu ba khu vực bình thường chạy gần 70 phần trăm mức sử dụng, mất một khu vực sẽ không còn đủ chỗ cho phần công việc của nó. Dự phòng headroom tốn tiền, nhưng topology không có dung lượng failover không đạt mục tiêu đã nêu.

Game day xác thực thiết kế

Bài tập lỗi nên vô hiệu hóa một node, cô lập một zone, gián đoạn kết nối khu vực và loại bỏ một endpoint ứng dụng. Hãy đo thời lượng lỗi, tỷ lệ retry giao dịch, percentile độ trễ, tăng trưởng queue và phản ứng của người vận hành.

Thực hiện các bài tập này sau thay đổi đáng kể về topology, driver hoặc schema. Quy trình đã chứng minh với lưu lượng năm trước có thể thất bại khi khối lượng dữ liệu tăng gấp đôi hoặc một tenant trở nên chi phối. Tự động hóa các phần an toàn của bài tập để bằng chứng không phụ thuộc vào một sự kiện thủ công hằng năm.

Sao chép không phải backup

Replica sao chép trung thực thao tác xóa nhầm, migration lỗi và ghi ứng dụng gây hại. Backup và khôi phục theo thời điểm bảo vệ trước hư hại logic mà sao chép không thể phát hiện.

Diễn tập restore nên dựng môi trường sạch riêng, xác minh checksum hoặc bất biến ứng dụng và đo tổng thời gian phục hồi. Hãy bao gồm khóa mã hóa, chính sách truy cập, phiên bản schema và cấu hình phụ thuộc. Backup tồn tại nhưng không thể khôi phục trong thời hạn mục tiêu không phải hệ thống phục hồi đầy đủ.

Lưu trú dữ liệu và kiến trúc theo yêu cầu tuân thủ

SQL phân tán có thể đặt nhóm tenant hoặc bản ghi tại các khu vực được phê duyệt, nhưng tuân thủ phụ thuộc vào mọi bản sao, đường truy cập và quy trình vận hành. Locality cơ sở dữ liệu là một biện pháp kiểm soát trong chương trình rộng hơn.

Quy tắc lưu trú cần định nghĩa chính xác

Yêu cầu dữ liệu phải ở trong một quốc gia có thể nói đến lưu trữ, xử lý, quyền truy cập hỗ trợ, backup, khóa mã hóa hoặc tất cả những điều này. Mỗi cách hiểu tạo ra topology khác nhau. Cố vấn pháp lý và kiểm toán viên nên chuyển quy định cùng hợp đồng thành biện pháp kiểm soát kỹ thuật có thể kiểm thử.

Đội ngũ cần kiểm kê các trường chịu quản lý và dữ liệu dẫn xuất. Log, trace, chỉ mục tìm kiếm, bản xuất phân tích, tệp đính kèm hỗ trợ và queue thông điệp có thể chứa cùng thông tin cá nhân với bảng chính. Hạn chế cơ sở dữ liệu nhưng xuất payload thô toàn cầu không đạt chính sách dự kiến.

Giảm thiểu dữ liệu có thể đơn giản hóa thiết kế. Nếu dịch vụ toàn cầu chỉ cần mã tài khoản và trạng thái tổng hợp, hãy giữ chi tiết nhạy cảm trong khu vực được phê duyệt và chỉ cung cấp biểu diễn nhỏ nhất được phép ở nơi khác.

Chính sách vị trí phải bao gồm thao tác trong toàn bộ vòng đời

Chính sách nên nêu nơi replica trực tiếp, replica tạm, backup, snapshot, bản ghi thay đổi và môi trường restore được phép tồn tại. Cân bằng lại và bảo trì phải tuân thủ cùng ranh giới. Quy trình khẩn cấp không nên sao chép dữ liệu chịu quản lý sang khu vực chưa phê duyệt cho tiện.

Kiểm soát truy cập cần giới hạn theo địa lý và tổ chức. Danh tính dịch vụ chỉ nên nhận quyền với bảng và thao tác cần thiết. Quyền truy cập production của con người nên được ghi log, giới hạn thời gian khi khả thi và được xem xét. Khóa mã hóa gắn khu vực có thể tăng kiểm soát, dù tính sẵn sàng của khóa và khôi phục thảm họa khi đó cũng cần thiết kế riêng.

Di chuyển tenant cần quy trình được ghi nhận. Thay đổi hợp đồng, di chuyển khách hàng hoặc tái cấu trúc doanh nghiệp có thể yêu cầu chuyển bản ghi giữa các khu vực pháp lý. Quy trình cần xác định khi nào bản sao cũ biến mất, backup cũ hết hạn thế nào và bằng chứng nào chứng minh hoàn tất.

Báo cáo toàn cầu có thể cần bộ dữ liệu dẫn xuất

Dashboard toàn cầu có thể xung đột với yêu cầu đặt dữ liệu nghiêm ngặt nếu nó quét dữ liệu khách hàng thô qua các khu vực. Xử lý theo khu vực có thể tính tổng hợp được phê duyệt tại chỗ, sau đó xuất kết quả không nhạy cảm sang kho báo cáo trung tâm.

Quy tắc tổng hợp cần ngăn việc tái dựng bản ghi bị hạn chế. Nhóm nhỏ, trường văn bản tự do và chiều dữ liệu chi tiết có thể làm lộ thông tin cá nhân ngay cả khi bỏ mã định danh trực tiếp. Vì vậy, quản trị phân tích cần có mặt trong đánh giá kiến trúc, không phải ở dự án báo cáo về sau.

Khối lượng công việc vận hành và phân tích thường xứng đáng có hệ thống riêng. Cơ sở dữ liệu giao dịch bảo vệ trạng thái sản phẩm hiện tại, còn pipeline theo phạm vi khu vực tạo bộ dữ liệu được quản trị cho báo cáo. Sự tách biệt này giữ các lần quét phân tích dài tránh xa giao dịch nhạy cảm với độ trễ.

Lập kế hoạch chi phí và hiệu năng

Tạo nguyên mẫu SaaS toàn cầu
Tạo khung SaaS đa tenant và sớm xác thực các giả định về vị trí dữ liệu theo từng tenant.

SQL phân tán tốn kém hơn cơ sở dữ liệu một khu vực cơ bản vì duy trì dung lượng dự phòng và phối hợp công việc qua mạng. Khoản đầu tư vẫn có thể hợp lý khi nó thay thế công sức sharding đắt đỏ hoặc ngăn tổn thất lớn hơn phần chi phí vận hành tăng thêm.

Tính toán và lưu trữ gồm chi phí sao chép

Bộ dữ liệu logic 2 TB với ba replica đầy đủ bắt đầu gần 6 TB dữ liệu được sao chép, trước khi tính chỉ mục thứ cấp, không gian nén tạm, backup và metadata. Cách tính phí và nén thực tế khác theo sản phẩm, nên ước lượng cần dựa vào lưu trữ vật lý đo được thay vì chỉ kích thước bảng logic.

Năng lực tính toán phải bao phủ công việc bình thường, xử lý đồng thuận, cân bằng lại, backup và headroom khi lỗi. Node không phải các đơn vị thông lượng có thể thay thế cho nhau khi một phân vùng nóng. Thêm dung lượng chỉ giúp khi khối lượng công việc có thể trải lên đó.

Chỉ mục nhân công việc ghi và lưu trữ. Hãy xem xét mỗi chỉ mục thứ cấp theo giá trị cho truy vấn, tần suất cập nhật và vị trí địa lý. Chỉ mục không dùng trong cụm phân tán làm tốn đĩa và khiến mỗi lần ghi bị ảnh hưởng đắt hơn.

Chi phí mạng có thể trở nên đáng kể

Sao chép gửi ghi giữa các vị trí replica. Truy vấn liên khu vực, change feed, backup và lưu lượng ứng dụng tạo thêm truyền dữ liệu. Lưu lượng hoạt động ở nhiều khu vực có thể tạo hóa đơn mà benchmark một khu vực không thể cho thấy.

Hãy ước lượng byte mỗi giao dịch, hệ số sao chép, tốc độ ghi, khuếch đại chỉ mục và hướng truyền. Sau đó kiểm thử bằng dữ liệu tính phí của nhà cung cấp trong đợt chạy tải đại diện. Chỉ số lượng yêu cầu không phản ánh payload lớn và hoạt động nền.

Lỗi locality làm tăng cả chi phí lẫn độ trễ. Dịch vụ triển khai ở một khu vực có thể liên tục truy vấn điều phối viên ở khu vực khác do chọn endpoint hoặc đặt tenant. Distributed tracing và phân tích chi phí theo khu vực có thể chỉ ra mẫu này.

Hành trình người dùng cho thấy độ trễ tích lũy

Hãy mô hình hóa toàn bộ hành động người dùng thay vì câu lệnh riêng lẻ. Với checkout, đếm mọi commit cơ sở dữ liệu tuần tự, đọc mạnh, lệnh gọi API bên ngoài và chuyển giao queue. Áp dụng thời gian vòng đi khu vực đã đo cùng percentile thực thi truy vấn vào đường tới hạn.

Giả sử một hành trình có hai lần ghi quorum tuần tự, mỗi lần thêm 90 mili giây phối hợp mạng. Như vậy góp khoảng 180 mili giây trước xử lý ứng dụng. Kết hợp các thay đổi chung một quyết định nguyên tử có thể loại bỏ một commit, còn chạy song song các lần đọc độc lập có thể rút ngắn đường đi.

Kiểm thử tải nên có tranh chấp và kích thước payload thực tế. Benchmark với mã định danh ngẫu nhiên có thể phân bố hoàn hảo dù ghi sản xuất nhắm vào vài tenant phổ biến. Hãy bao gồm chuyển leader và cân bằng lại để độ trễ đuôi phản ánh vận hành cụm thông thường.

So sánh tổng chi phí sở hữu với phương án thực tế

So sánh phù hợp không phải SQL phân tán với cơ sở dữ liệu tưởng tượng không có chi phí vận hành. Hãy so sánh với phương án cụ thể: PostgreSQL được quản lý, replica, dịch vụ sharding, phục hồi theo khu vực, định tuyến ứng dụng và kỹ sư cần để duy trì chúng.

Bao gồm công việc migration, đào tạo, quan sát, phản ứng sự cố, gói hỗ trợ và chi phí thoát. Vận hành được quản lý có thể giảm công sức hạ tầng, còn tự quản lý có thể đáp ứng yêu cầu kiểm soát với cái giá là cần nhân sự chuyên sâu hơn.

Mô hình tài chính đơn giản có thể so sánh phần chi phí nền tảng hằng năm với tổn thất dự kiến do ngừng hoạt động, công việc kỹ thuật chậm lại, rủi ro tuân thủ và doanh thu bị ảnh hưởng bởi độ trễ khu vực. Dùng khoảng giá trị cho đầu vào không chắc chắn và xác định giả định nào làm thay đổi quyết định. Nếu kết quả phụ thuộc vào ước tính sự cố lớn khó tin, hệ thống đơn giản hơn có lẽ vẫn phù hợp.

Mẫu thiết kế schema và ứng dụng

Schema SQL phân tán hoạt động tốt khi đường truy cập của nó phân tán công việc độc lập nhưng giữ giao dịch liên quan ở gần nhau. Chuyển nguyên schema một node có thể vẫn đúng nhưng tạo độ trễ kém hoặc tranh chấp nghiêm trọng.

Primary key ảnh hưởng đến phân bố

Primary key tăng dần có thể dồn hàng mới về cuối một range. Mã ngẫu nhiên trải lần chèn, nhưng phân bố hoàn toàn ngẫu nhiên có thể khiến quét tenant hoặc đặt theo khu vực đắt hơn. Khóa tổng hợp thường cân bằng các mục tiêu bằng cách bắt đầu bằng mã tenant hoặc bucket và giữ giá trị có thể sắp xếp trong nhóm đó.

Hãy chọn tiền tố theo ranh giới giao dịch. Nếu gần như mọi thao tác theo tenant, nhóm theo tenant có thể giảm công việc phân tán. Tenant rất lớn có thể cần bucket trong không gian tên của nó để nhiều phân vùng nhận ghi đồng thời.

Thay primary key sau khi bảng đã lớn có thể cần viết lại dữ liệu lớn. Hãy kiểm thử bố cục ứng viên với độ lệch thực tế trước migration. Xem nhiệt phân vùng, mức độ trải giao dịch, locality của chỉ mục và hành vi quét thay vì chỉ đánh giá tổng thông lượng.

Tranh chấp cần thiết kế lại trước khi tăng dung lượng

Bộ đếm toàn cục, hàng cấu hình singleton hoặc một số dư merchant có thể tuần tự hóa các yêu cầu vốn độc lập. Nhiều node hơn không thể xóa yêu cầu logic rằng mọi giao dịch phải cập nhật cùng một giá trị.

Thay bộ đếm toàn cục chính xác bằng bộ đếm phân vùng khi chấp nhận tổng hợp tạm thời. Phiên bản hóa cấu hình thay vì cập nhật một hàng với tần suất cao. Với trạng thái tiền tệ, hãy giữ bất biến kế toán và tìm sự đồng thời trong bút toán append-only hoặc subaccount độc lập thay vì làm yếu tính đúng đắn.

Giao dịch đọc-sửa-ghi dài khiến xung đột nặng hơn. Đọc tập nhỏ nhất cần thiết, tránh tương tác người dùng trong giao dịch và commit nhanh. Nếu công việc nghiệp vụ kéo dài nhiều phút, hãy biểu diễn nó thành state machine qua nhiều giao dịch ngắn.

Hành vi retry thuộc hợp đồng ứng dụng

Driver có thể retry từng câu lệnh hoặc trả lỗi có thể retry cho mã ứng dụng. Cần hiểu tầng nào sở hữu việc chạy lại toàn bộ giao dịch. Chạy lại một phần có thể dùng quyết định cũ hoặc bỏ sót lần đọc trước đó.

Vòng retry cần số lần thử tối đa, backoff ngẫu nhiên và công cụ quan sát. Hãy ghi loại xung đột, thao tác bị ảnh hưởng, số lần thử và kết quả cuối. Retry không giới hạn biến tranh chấp thành độ trễ ẩn và có thể làm cụm quá tải.

Yêu cầu nghiệp vụ cần mã ổn định để phản hồi client không chắc chắn có thể được kiểm tra an toàn. Nếu cơ sở dữ liệu đã commit nhưng phản hồi bị mất, client nên truy vấn thao tác đã xác lập thay vì gửi thao tác mới về mặt ngữ nghĩa.

Thay đổi schema cần diễn tập ở quy mô production

Thay đổi schema phân tán có thể cập nhật metadata nhanh trong khi backfill và tạo chỉ mục tiếp tục ở nền. Những job này dùng lưu trữ, mạng và CPU, đồng thời có thể tương tác với ghi trực tiếp.

Dùng migration mở rộng rồi thu gọn. Trước hết thêm trường hoặc bảng tương thích, triển khai mã chạy được với cả hai dạng, backfill theo batch có kiểm soát, chuyển lần đọc rồi xóa dạng cũ sau khi xác minh. Kế hoạch rollback phải tính đến dữ liệu được phiên bản mới ghi.

Hãy kiểm thử migration lớn với khối lượng và topology khu vực gần production. Thay đổi hoàn tất nhanh ở cụm staging nhỏ có thể mất nhiều giờ trong production và cạnh tranh với lưu lượng khách hàng. Theo dõi tiến độ, điều khiển tạm dừng, headroom đĩa và hành vi retry trước khi bắt đầu.

Checklist áp dụng và proof of concept

Proof of concept hữu ích kiểm thử một khối lượng công việc đại diện với mục tiêu rõ ràng về tính đúng đắn, độ trễ, khả năng phục hồi và chi phí. Benchmark chung chung không thể xác định schema và ứng dụng cụ thể có hoạt động tốt hay không.

Chọn khối lượng công việc có ràng buộc thực tế

Chọn quy trình như đặt mặt hàng khan hiếm, ghi chuyển khoản sổ cái hoặc cấp phát tenant trong khu vực bắt buộc. Dùng lại schema, truy vấn, ranh giới giao dịch, kích thước payload và độ lệch lưu lượng kiểu production của nó.

Xác định thành công trước khi chạy kiểm thử:

  • Kết quả đúng khi đồng thời và retry
  • Độ trễ p50, p95 và p99 theo khu vực
  • Thông lượng đỉnh duy trì được với headroom khi lỗi
  • Hành vi phục hồi khi node và khu vực lỗi
  • Chi phí tính toán, lưu trữ và mạng đã đo

Biên độ an toàn phải đến từ tăng trưởng dự kiến và dung lượng khi lỗi, không phải hệ số tùy tiện. Nếu mất một khu vực nằm trong phạm vi, các vị trí còn lại phải xử lý tải được chuyển hướng trong khi kiểm thử.

Xây dựng bề mặt ứng dụng sát thực tế

API và giao diện người dùng nhỏ cho thấy trình tự giao dịch, hành vi driver và độ trễ người dùng cảm nhận mà công cụ chỉ dành cho cơ sở dữ liệu có thể bỏ sót. Koder.ai có thể tạo giao diện React, backend Go và nền tảng PostgreSQL thông qua chat. Chế độ lập kế hoạch của nó có thể giúp xác định quy trình trước khi tạo, còn xuất mã nguồn cho phép kỹ sư điều chỉnh tầng dữ liệu cho cơ sở dữ liệu ứng viên.

Hãy dùng ứng dụng được tạo đó làm khung kiểm thử, không phải bằng chứng tương thích cơ sở dữ liệu. Chạy migration, kiểm tra SQL được tạo, cấu hình driver chính thức và chủ động triển khai retry giao dịch. Snapshot và rollback của Koder.ai có thể bảo vệ các lần lặp ứng dụng, nhưng không thay thế backup hay diễn tập restore cơ sở dữ liệu.

Koder.ai cũng hỗ trợ triển khai và hosting, có thể đặt các instance ứng dụng kiểm thử gần những khu vực cơ sở dữ liệu. Nhờ đó có thể đo toàn bộ đường yêu cầu thay vì gửi mọi benchmark từ một vị trí. Chỉ dùng dữ liệu kiểm thử tổng hợp trừ khi môi trường có biện pháp kiểm soát cần cho bản ghi production.

Kiểm tra vận hành bình thường và lỗi

Bài kiểm thử nên bao phủ lưu lượng ổn định, bùng nổ, phân vùng nóng, truy vấn chạy dài, thay đổi schema, công việc backup và thay node. Sau đó ngắt kết nối và loại bỏ một miền lỗi trong môi trường kiểm thử đã được phê duyệt.

Ghi nhận giao dịch bị hủy, số lần retry, phản hồi không khả dụng, chuyển leader, độ sâu queue, mức dùng đĩa và truyền dữ liệu theo khu vực. Ghi lại những gì người vận hành phải làm. Khôi phục tự động cần một bước thủ công không được ghi nhận thì chưa sẵn sàng cho production.

Khôi phục backup vào môi trường riêng và xác minh các bất biến ứng dụng. Với tồn kho, xác nhận phân bổ không vượt quá lượng hàng. Với sổ cái, tính lại số dư và xác minh bút toán cân bằng. Với SaaS tenancy, xác nhận chính sách vị trí và truy cập vẫn tồn tại sau restore.

Xác thực tương thích trước migration

Kiểm kê extension cơ sở dữ liệu, stored procedure, trigger, kiểu dữ liệu, giả định về cô lập, tính năng ORM, truy vấn báo cáo, công cụ backup và script quản trị. Phân loại từng mục là tương thích, có thể thay thế hoặc chặn.

Chạy migration đại diện trên bản sao kích thước đầy đủ hoặc bộ dữ liệu được tạo. Đo thời gian backfill, độ trễ change-data-capture, chi phí chạy song song và thời gian cutover. Nếu migration dùng dual write, hãy xác định cách phát hiện sai khác và hệ thống nào vẫn là nguồn có thẩm quyền ở mỗi giai đoạn.

Shadow read có thể so sánh kết quả mà không thay đổi trạng thái production. Hãy tính đến khác biệt thời gian và truy vấn cố ý cũ để so sánh không gắn biến thiên dự kiến là hỏng dữ liệu. Mọi khác biệt chưa giải thích trong dữ liệu giao dịch cần được xử lý trước cutover.

Rà soát mức sẵn sàng production

Rà soát production nên phân công chủ sở hữu cho vận hành cơ sở dữ liệu, retry ứng dụng, bảo mật, chính sách lưu trú, chi phí và phản ứng sự cố. Nó nên bao gồm dashboard, cảnh báo, runbook, ngưỡng dung lượng, bằng chứng restore và điểm quyết định rollback.

Quyết định cuối cùng vẫn có thể là tiếp tục dùng PostgreSQL hoặc MySQL. Proof of concept thành công khi tạo ra bằng chứng đáng tin cậy, kể cả khi bằng chứng đó cho thấy lựa chọn phân tán tốn kém hơn mức yêu cầu hiện tại biện minh. Khi yêu cầu thực sự hỗ trợ việc áp dụng, hãy migration dần dần, đo lường từng giai đoạn và giữ đường quay lại đã kiểm thử cho đến khi hệ thống mới chứng minh được dưới tải thực tế.

Câu hỏi thường gặp

Nói đơn giản, cơ sở dữ liệu “SQL phân tán” là gì?

Cơ sở dữ liệu SQL phân tán cung cấp giao diện quan hệ, SQL gồm bảng, join, ràng buộc và giao dịch, nhưng chạy như một cụm trên nhiều máy, thường ở nhiều khu vực, trong khi vẫn hoạt động như một cơ sở dữ liệu logic duy nhất.

Trên thực tế, nó hướng tới việc kết hợp:

  • Hành vi SQL/ACID quen thuộc
  • Mở rộng ngang bằng cách thêm node
  • Tính sẵn sàng cao và khả năng chịu lỗi mà không cần sharding thủ công
SQL phân tán khác gì so với PostgreSQL/MySQL truyền thống?

RDBMS một node hoặc primary/replica thường đơn giản hơn, rẻ hơn và nhanh hơn cho OLTP một khu vực.

SQL phân tán trở nên hấp dẫn khi phương án thay thế là:

  • Sharding do ứng dụng tự quản lý
  • Failover đa khu vực phức tạp
  • Yêu cầu nhất quán mạnh giữa các zone/khu vực
  • Nhu cầu lưu trú dữ liệu nhưng vẫn dùng một mô hình vận hành
Vì sao hệ thống SQL phân tán dùng các giao thức đồng thuận như Raft hoặc Paxos?

Hầu hết hệ thống dựa vào hai ý tưởng cốt lõi:

  • Sao chép: mỗi shard/phân vùng dữ liệu được lưu trên nhiều node.
  • Đồng thuận: chẳng hạn Raft hoặc Paxos, các replica thống nhất thứ tự ghi; việc commit thường cần đa số xác nhận.

Đây là nền tảng cho tính nhất quán mạnh ngay cả khi node gặp sự cố, nhưng cũng làm tăng chi phí phối hợp qua mạng.

Dữ liệu được phân vùng và đặt trên các node/khu vực như thế nào?

Chúng chia bảng thành các phần nhỏ hơn, thường gọi là phân vùng/shard, hoặc dùng tên riêng của nhà cung cấp như range/tablet/split. Mỗi phân vùng:

  • Có nhóm replica riêng
  • Có thể được đặt tại các node/khu vực cụ thể
  • Có thể di chuyển khi cụm cân bằng lại

Bạn thường tác động đến vị trí bằng chính sách, để dữ liệu nóng và nơi ghi chính ở gần nhau, nhờ đó giảm các chuyến đi qua mạng.

Vì sao giao dịch có thể chậm hơn trong SQL phân tán, nhất là giữa các khu vực?

Giao dịch phân tán thường chạm đến nhiều phân vùng, có thể ở các node hoặc khu vực khác nhau. Một lần commit an toàn có thể cần:

  • Khóa/xác thực giữa các bên tham gia
  • Xác nhận sao chép theo quorum
  • Quyết định commit có phối hợp

Các vòng đi mạng bổ sung này là lý do chính khiến độ trễ ghi tăng, nhất là khi đồng thuận trải qua nhiều khu vực.

Dấu hiệu rõ nhất cho thấy tôi thực sự cần SQL phân tán là gì?

Hãy cân nhắc SQL phân tán khi đúng từ hai điều kiện trở lên:

  • Bạn có lượng người dùng đáng kể ở nhiều khu vực và muốn dữ liệu nhất quán
  • Bạn cần failover tự động giữa zone/khu vực với RTO/RPO chặt chẽ
  • Mở rộng dọc không còn đủ cho nhu cầu ghi
  • Bạn cần nhất quán mạnh cho các giao dịch cốt lõi như tiền, tồn kho, đặt chỗ
  • Tuân thủ yêu cầu đặt dữ liệu theo vị trí địa lý

Nếu khối lượng công việc vừa trong một khu vực với replica/cache, RDBMS thông thường thường là lựa chọn mặc định tốt hơn.

Tính nhất quán mạnh mang lại gì, và phải đánh đổi gì?

Nhất quán mạnh nghĩa là sau khi giao dịch commit, các lần đọc sẽ không thấy dữ liệu cũ hơn.

Ở góc độ sản phẩm, điều này giúp ngăn:

  • Chi tiêu hai lần / số dư sai
  • Bán vượt món hàng cuối cùng
  • Hai người cùng đặt một ghế

Đánh đổi là khi mạng bị phân vùng, hệ thống nhất quán mạnh có thể chặn hoặc từ chối một số thao tác thay vì chấp nhận những trạng thái khác nhau.

Làm sao xử lý retry an toàn, có tính idempotent, với SQL phân tán?

Dựa vào ràng buộc cơ sở dữ liệu và giao dịch:

  • Lưu idempotency_key hoặc khóa tương tự cho mỗi yêu cầu/lần thử
  • Thêm ràng buộc duy nhất như (account_id, idempotency_key)
  • Trong một giao dịch, ghi bản ghi nghiệp vụ cùng mọi dòng sổ cái/outbox

Nhờ vậy, retry trở thành thao tác không tạo thêm thay đổi thay vì tạo bản sao, đặc biệt quan trọng với thanh toán, cấp phát và xử lý lại job nền.

Nên chọn giữa Spanner, CockroachDB và YugabyteDB như thế nào?

Có thể phân biệt thực tế như sau:

  • Spanner: thường được quản lý trên GCP; có nền tảng thiết kế đa khu vực mạnh; lựa chọn dialect SQL ảnh hưởng đến tính di động.
  • CockroachDB: trải nghiệm và wire protocol giống Postgres; có thể dùng dịch vụ quản lý hoặc tự host; không tương thích Postgres 100%.
  • YugabyteDB: API SQL tương thích Postgres là YSQL, kèm API kiểu Cassandra tùy chọn là YCQL; có thể dùng dịch vụ quản lý hoặc tự host.

Trước khi chọn, hãy kiểm thử ORM/migration thực tế và mọi extension Postgres bạn phụ thuộc, đừng cho rằng có thể thay thế trực tiếp.

Kế hoạch proof of concept tốt trước khi cam kết với SQL phân tán là gì?

Bắt đầu với một PoC tập trung quanh quy trình quan trọng như checkout, đặt chỗ hoặc ghi sổ cái. Hãy xác thực:

  • Tính đúng đắn, không đặt trùng/mất cập nhật
  • Độ trễ p50/p95 của các truy vấn chính, gồm cả mục tiêu đa khu vực
  • Hành vi khi lỗi: mất node, mất zone và nếu phù hợp, mất khu vực
  • Các nền tảng vận hành: giám sát, backup, diễn tập restore

Nếu cần hỗ trợ xác định phạm vi chi phí/gói, hãy xem phần giá. Với các ghi chú triển khai liên quan, hãy xem blog.

Related posts