0
0
Lập trình
Admin Team
Admin Teamtechmely

Kiến Trúc CockroachDB: Những Sai Lầm Và Bài Học

Đăng vào 6 ngày trước

• 9 phút đọc

Giới Thiệu

Lời cảnh báo: Đây có thể là một ý tưởng tồi. Chúng tôi có thể đang bỏ lỡ một điều gì đó hiển nhiên. Những kỹ sư thông minh hơn chắc chắn sẽ tìm ra giải pháp tốt hơn. Nhưng đây là câu chuyện của chúng tôi.

Khi chúng tôi bắt đầu đánh giá CockroachDB cho DeviceLab, chúng tôi đã có nhiều hy vọng. Lời hứa về một cơ sở dữ liệu SQL phân tán có khả năng mở rộng ngang trong khi vẫn duy trì tính nhất quán dường như rất hoàn hảo cho nền tảng SaaS của chúng tôi. Rốt cuộc, ai không muốn sự mở rộng của NoSQL với sự quen thuộc của PostgreSQL?

Nhưng thực tế đã tấn công chúng tôi như một thời gian chờ cấu hình cơ sở dữ liệu không đúng cách.

Hành Trình Vào Cơn Điên 🤯

Cố gắng đầu tiên của chúng tôi là với dịch vụ đám mây của CockroachDB. Các truy vấn đơn giản mất hơn 2 giây. Tạo bảng? Gần 2 phút. Chúng tôi đã gửi một phiếu hỗ trợ, hy vọng vào một phép màu cấu hình. Thay vào đó, chúng tôi nhận được hai phản hồi làm chúng tôi nghi ngờ mọi thứ:

  1. Đầu tiên, họ đề xuất xóa toàn bộ cụm của chúng tôi và bắt đầu lại từ đầu.
  2. Khi điều đó không hiệu quả, họ gần như nói rằng vấn đề hiệu suất thực sự không phải là vấn đề trừ khi một cái gì đó hoàn toàn "hỏng".

Chúng tôi nghĩ có thể chúng tôi đang làm sai điều gì đó, vì vậy chúng tôi quyết định tự mình chạy thử nghiệm. Đó là lúc mọi thứ trở nên kỳ lạ.

Chúng tôi đã khởi động CockroachDB trên Google Cloud (GCE) và chạy cùng một truy vấn (dưới tải thử nghiệm):

  • Cụm GCE: 200 milliseconds ✅
  • Một nút trên VM nhỏ (2 vCPUs, 2GB RAM): 20 milliseconds 🚀

Làm thế nào mà một nút đơn giản với tài nguyên hạn chế lại vượt trội hơn một cụm đã được cấp phát đúng cách đến một bậc?

Khi Vật Lý Ngừng Làm Mọi Thứ Hợp Lý 🌌

Điều làm chúng tôi thắc mắc là khi chúng tôi thử nghiệm kết nối giữa các vùng miền. Chúng tôi có máy chủ ứng dụng trên AWS và một cụm cơ sở dữ liệu trên GCE. Lý trí sẽ gợi ý rằng việc giữ mọi thứ trong cùng một nhà cung cấp đám mây và vùng miền sẽ nhanh hơn, đúng không?

Sai lầm. (dưới tải thử nghiệm)

Copy
AWS → GCE (giữa các đám mây): 124ms ⚡
GCE → GCE (cùng vùng): 2.65 giây 🐌

Vâng, bạn đã đọc đúng. Giao tiếp giữa các đám mây thực sự nhanh hơn 20 lần so với giao tiếp trong cùng một vùng của GCE.

Tại thời điểm này, chúng tôi bắt đầu nghi ngờ hiểu biết của mình về mạng cơ bản. Có lẽ chúng tôi đã đo sai? Có lẽ chúng tôi đã cấu hình sai điều gì đó cơ bản? Chúng tôi đã chạy thử nghiệm một lần nữa. Và một lần nữa. Kết quả vẫn nhất quán.

Chi Phí Nút Đa 🌍

Khi chúng tôi đào sâu hơn, chúng tôi phát hiện ra một điều mà lẽ ra nên rõ ràng từ trước: Tính phân tán của CockroachDB đi kèm với một cái giá.

  • Mỗi ghi cần sự đồng thuận từ phần lớn các nút.
  • Mỗi truy vấn có thể cần phải nhảy giữa các nút để tìm người sở hữu dữ liệu.
  • Càng nhiều nút chúng tôi thêm vào, mọi thứ càng chậm lại.

Điều này có lý cho trường hợp sử dụng mà CockroachDB nhắm đến - các ứng dụng phân tán toàn cầu nơi việc sống sót sau các sự cố vùng miền quan trọng hơn tốc độ thô. Nhưng đối với trường hợp của chúng tôi, nơi hầu hết khách hàng là khu vực và độ trễ quan trọng hơn sự sống sót đa vùng miền, chúng tôi đã phải trả một cái giá nặng nề cho những lợi ích mà chúng tôi không cần.

Giải Pháp Lười Biếng 💡

Bây giờ, một nhóm kỹ sư có năng lực sẽ lấy bài học này và thiết kế một kiến trúc đúng đắn. Họ có thể đã:

  • Triển khai định tuyến truy vấn thông minh.
  • Sử dụng bản sao đọc.
  • Có thể thậm chí tự hỏi liệu CockroachDB có phải là lựa chọn đúng đắn hay không.

Chúng tôi không phải là đội ngũ như vậy.

Thay vào đó, chúng tôi đã xem xét:

  • Các máy chủ ứng dụng của chúng tôi: 150MB RAM, <10% CPU sử dụng.
  • Các nút cơ sở dữ liệu của chúng tôi: Cần các phiên bản riêng biệt.

Và chúng tôi đã có một ý tưởng tồi tệ, khủng khiếp, không tốt.

Liệu chúng tôi có thể... kết hợp chúng lại với nhau?

Cài Đặt Không Ai Nên Sao Chép ⚠️

Vậy là chúng tôi đã làm vậy. Mỗi phiên bản của chúng tôi hiện đang chạy:

  • Máy chủ ứng dụng của chúng tôi
  • Một nút CockroachDB

Ứng dụng kết nối đến localhost:26257. Chỉ vậy thôi. Đó là toàn bộ kiến trúc cơ sở dữ liệu của chúng tôi.

Copy
# Kiến trúc của chúng tôi trong một cái nhìn
instance:
  - app_server: ✅
  - cockroachdb_node: ✅
  - connection: localhost:26257
  - complexity: none
  - best_practices: ignored

Chúng tôi biết điều này vi phạm mọi nguyên tắc thiết kế hệ thống hợp lý:

  • Phân tách mối quan tâm? Bị ném ra ngoài cửa sổ.
  • Mở rộng độc lập? Không thể.
  • Thời gian bảo trì? Chúng ảnh hưởng đến mọi thứ.

Bất kỳ kiến trúc sư nào nhìn vào thiết lập của chúng tôi sẽ ngay lập tức đánh trượt chúng tôi trong một cuộc xem xét thiết kế.

Nhưng đây là sự thật đáng xấu hổ: nó hoạt động tốt hơn so với thiết lập "đúng" của chúng tôi.

Cách Nó Thực Sự Hoạt Động

Khi ứng dụng của chúng tôi thực hiện một truy vấn, một trong ba điều xảy ra:

  1. Dữ liệu là địa phương → Phản hồi dưới 1 millisecond (không cần nhảy mạng).
  2. Dữ liệu nằm trên nút khác → CockroachDB địa phương chuyển tiếp nó (một nhảy mạng).

So sánh điều này với thiết lập truyền thống:

Copy
App Server → Bộ cân bằng tải → Nút CockroachDB ngẫu nhiên → Người giữ thuê thực tế

Có thể hai nhảy mạng.

Kết quả: Chúng tôi đã loại bỏ một vòng đi mạng hoàn toàn khỏi mỗi truy vấn cơ sở dữ liệu.

Tại Sao Điều Này Vẫn Là Một Ý Kiến Tồi 🚨

Hãy để tôi rõ ràng: điều này có thể sai. Chúng tôi gần như chắc chắn đang tạo ra những vấn đề mà chúng tôi chưa phát hiện. Các kỹ sư thực sự tách biệt các tầng ứng dụng và cơ sở dữ liệu vì những lý do tốt mà chúng tôi quá lười biếng hoặc ngu dốt để hiểu đầy đủ.

Các Vấn Đề Tiềm Ẩn Chúng Tôi Đang Bỏ Qua:

  • Cạnh tranh tài nguyên: Điều gì xảy ra trong quá trình hợp nhất CockroachDB? Hoặc trong quá trình sao lưu?
  • Giải pháp của chúng tôi nếu có vấn đề phát sinh: Chỉ cần thêm nhiều RAM vào. Phần cứng rẻ. Suy nghĩ là đắt giá.
  • Khả năng truy vấn phân tán lãng phí: Trình tối ưu hóa truy vấn giả định rằng tất cả các nút đều có thể truy cập như nhau.
  • Chúng tôi đang sử dụng một chiếc Ferrari để đi chợ.

Kinh Tế Của Sự Kém Cỏi 💰

Kinh tế thực sự hợp lý hơn so với vẻ bề ngoài:

Mở Rộng Thiết Lập Truyền Thống:

  1. Tìm hiểu xem tầng nào cần mở rộng (ứng dụng hay cơ sở dữ liệu?)
  2. Phối hợp các thay đổi
  3. Cân bằng tải của bạn
  4. Gỡ lỗi tại sao việc pool kết nối đột nhiên hành xử kỳ lạ.

Mở Rộng Thiết Lập Của Chúng Tôi:

  1. Thêm một phiên bản nữa
  2. Chỉ vậy thôi.
Copy
// Chiến lược mở rộng của chúng tôi
if (needMoreCapacity) {
  addInstance();  // Nhận cả máy chủ ứng dụng VÀ nút cơ sở dữ liệu
}
// Xong. Về nhà. Ngủ ngon.

Điều đáng lưu ý? Máy chủ ứng dụng đơn lẻ của chúng tôi có thể xử lý 10,000 yêu cầu mỗi giây. Vì vậy, khi chúng tôi thêm các phiên bản, chúng tôi thực sự đang thêm chúng để phân phối cơ sở dữ liệu, không phải dung lượng ứng dụng. Nhưng chúng tôi nhận được cả hai.

Những Gì Chúng Tôi Đáng Lẽ Phải Làm 🤔

Nhìn lại, chúng tôi có lẽ nên:

  1. Sử dụng PostgreSQL với sao chép luồng - Đơn giản hơn, nhanh hơn, phù hợp hơn.
  2. Thuê người thực sự hiểu về hệ thống phân tán - Để cấu hình CockroachDB đúng cách.
  3. Giữ lại dịch vụ đám mây - Và tìm ra điều gì sai với chúng tôi.

Nhưng chúng tôi không làm vậy. Chúng tôi đã chọn con đường lười biếng, kết hợp những thứ không nên kết hợp, bỏ qua các quy tắc tốt mà những người thông minh đã phát triển vì lý do chính đáng.

Phần tồi tệ nhất? Nó đã chạy trong môi trường sản xuất trong nhiều tháng mà không gặp vấn đề gì.

  • Độ trễ P99 tốt hơn bao giờ hết.
  • Khách hàng hài lòng.
  • Gánh nặng vận hành tối thiểu.

Chúng tôi vẫn đang chờ đợi nó phát nổ một cách ngoạn mục, để dạy chúng tôi bài học mà chúng tôi xứng đáng nhận cho những tội lỗi kiến trúc của mình. Nhưng nó vẫn tiếp tục hoạt động.

Kết Luận 🎯

Tôi không khuyến khích cách tiếp cận này. Xin đừng đọc điều này và nghĩ rằng "những người ở DeviceLab đang làm đúng điều gì đó." Chúng tôi không. Chúng tôi chỉ là những kỹ sư lười biếng đã tìm ra một cực trị địa phương hoạt động cho trường hợp rất cụ thể của chúng tôi, có thể bất thường.

Nếu bạn đáp ứng TẤT CẢ các tiêu chí này:

  • ✅ Ứng dụng của bạn nhỏ.
  • ✅ Khối lượng công việc chủ yếu là đọc.
  • ✅ Bạn không thích sự phức tạp trong vận hành.
  • ✅ Bạn sẵn sàng chấp nhận rằng bạn có thể đang làm sai.

Thì có thể thiết lập tồi tệ của chúng tôi cũng có thể hoạt động cho bạn.

Nhưng có lẽ không. Bạn nên làm đúng. Không giống như chúng tôi.


P.S. - Nếu bạn biết lý do tại sao điều này sẽ gây ra rắc rối cho chúng tôi, hãy cho chúng tôi biết trong phần bình luận. Chúng tôi thực sự tò mò về những gì chúng tôi đang bỏ lỡ. Chắc chắn phải có điều gì đó, đúng không? 🤷

Nếu bạn đang tìm kiếm một giải pháp mà các quyết định kiến trúc nghi ngờ không thể làm tổn hại đến dữ liệu của bạn, hãy xem DeviceLab - chúng tôi đã xây dựng một nền tảng phòng thí nghiệm thiết bị phân tán không tin cậy. Chúng tôi không hứa sẽ không nhìn vào dữ liệu của bạn; về mặt kiến trúc, chúng tôi không thể. Mọi thứ đều chạy trên thiết bị của bạn, kết nối peer-to-peer. Các thử nghiệm của bạn, dữ liệu của bạn, bảo mật của bạn. Không giống như thiết lập cơ sở dữ liệu của chúng tôi, chúng tôi thực sự đã suy nghĩ về điều này.

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào