Wow, đây là một câu hỏi đơn giản, một mảng lớn các câu trả lời có thể. Phần rõ ràng hơn của câu hỏi của bạn hỏi liệu có thể mở rộng hơn để giao tiếp với cơ sở dữ liệu của bạn trực tiếp hoặc thông qua một dịch vụ web. Câu trả lời rất đơn giản: truy vấn cơ sở dữ liệu trực tiếp. Đi qua dịch vụ web cho biết thêm một loạt độ trễ hoàn toàn không cần thiết đối với mã hoạt động đằng sau tường lửa (lớn và lớn). Ví dụ, một dịch vụ web yêu cầu một số thành phần nhận yêu cầu, giải tuần tự hóa nó, truy vấn DB, tuần tự hóa một phản hồi và trả lại nó. Vì vậy, nếu mã của bạn là tất cả hoạt động đằng sau một tường lửa, hãy tự giải quyết rắc rối và chỉ cần truy vấn trực tiếp DB.
Tuy nhiên, việc tạo một trang web có thể mở rộng vượt xa câu hỏi bạn đặt ra ban đầu. Vì vậy, hãy tha thứ cho tôi nếu tôi đi tiếp tuyến ở đây, nhưng tôi nghĩ nó có thể hữu ích khi xem xét cụ thể bạn đã đề cập đến Facebook.
Tôi khuyên bạn nên đọc về công việc và các công cụ được xây dựng bởi Brad Fitzpatrick (người sáng lập LiveJournal và hiện tại Google). Khi tôi làm việc với anh ấy tại Six Apart, đây là một số điều tôi học được từ anh ấy, và về kiến trúc của LiveJournal khiến nó có thể mở rộng được.
Sử dụng các bảng cơ sở dữ liệu hẹp thay vì các bảng rộng . Điều hấp dẫn ở đây là học được điều gì thúc đẩy kiến trúc này, thứ đang tạo ra một hệ thống dễ dàng và nhanh chóngnâng cấp. Nếu bạn sử dụng các bảng rộng hoặc các bảng mà mỗi trường hoặc thuộc tính là một cột trong bảng, khi đến lúc nâng cấp lược đồ cơ sở dữ liệu, ví dụ: thêm một cột mới, thì hệ thống sẽ cần khóa bảng trong khi lược đồ thay đổi được thực hiện. Khi hoạt động ở quy mô, điều này có nghĩa là một thay đổi đơn giản đối với lược đồ cơ sở dữ liệu có thể dẫn đến mất điện cơ sở dữ liệu lớn. Mà hút rõ ràng. Mặt khác, một bảng hẹp chỉ đơn giản là lưu trữ từng thuộc tính riêng lẻ được liên kết với một đối tượng dưới dạng một hàng trong cơ sở dữ liệu. Do đó, khi bạn muốn thêm một cột mới vào cơ sở dữ liệu, tất cả những gì bạn cần làm là ghi lại các bản ghi vào một bảng, đây là một hoạt động không khóa. Ok, đó là một nền tảng nhỏ, hãy xem mô hình này thực sự dịch như thế nào trong hệ thống làm việc như LiveJournal.
Giả sử bạn muốn tải 10 mục nhật ký mới nhất trên blog của một người và giả sử mỗi mục nhật ký có mười thuộc tính. Trong cách bố trí bảng rộng cổ điển, mỗi thuộc tính sẽ tương quan với một cột trên bảng. Sau đó, một người dùng sẽ truy vấn bảng một lần để lấy tất cả dữ liệu họ cần. Truy vấn sẽ trả về 10 hàng và mỗi hàng sẽ có tất cả dữ liệu họ cần (ví dụ: CHỌN * TỪ các mục ĐẶT HÀNG theo ngày GIỚI HẠN 10). Trong một bố trí bảng hẹp tuy nhiên mọi thứ hơi khác nhau. Trong ví dụ này thực tế có hai bảng: bảng đầu tiên (bảng A) lưu các tiêu chí đơn giản mà người ta muốn tìm kiếm, ví dụ: id của mục nhập, id của tác giả, ngày của mục, v.v. (bảng B) sau đó lưu trữ tất cả các thuộc tính được liên kết với một mục. Bảng thứ hai này có ba cột: entry_id, khóa và giá trị. Đối với mỗi hàng trong bảng A, sẽ có 10 hàng trong bảng B (một hàng cho mỗi thuộc tính). Do đó, để tìm nạp và hiển thị mười mục nhập cuối cùng, bạn sẽ cần 11 truy vấn. Truy vấn đầu tiên cung cấp cho bạn danh sách ID mục nhập, và sau đó mười truy vấn tiếp theo sẽ tìm nạp các thuộc tính được liên kết với từng mục được trả về trong truy vấn đầu tiên.
"Thánh moly!" bạn nói, "làm thế nào trên Trái đất có thể mở rộng hơn?!" Nó hoàn toàn phản trực giác phải không? Trong kịch bản đầu tiên, chúng tôi chỉ có một truy vấn cơ sở dữ liệu, nhưng trong giải pháp "có thể mở rộng hơn" thứ hai, chúng tôi có 11 truy vấn cơ sở dữ liệu. Điều đó không có ý nghĩa. Câu trả lời cho câu hỏi đó hoàn toàn dựa vào viên đạn tiếp theo.
Sử dụng memcache một cách tự do. Trong trường hợp bạn không biết, memcache là một hệ thống bộ nhớ đệm dựa trên mạng phân tán, không trạng thái, độ trễ thấp. Nó được sử dụng bởi Facebook, Google, Yahoo và gần như mọi trang web phổ biến và có thể mở rộng trên hành tinh. Nó được Brad Fitzpatrick phát minh ra một phần để giúp bù đắp chi phí cơ sở dữ liệu vốn có trong một thiết kế cơ sở dữ liệu bảng hẹp. Chúng ta hãy xem ví dụ tương tự như được thảo luận trong # 1 ở trên, nhưng lần này, hãy giới thiệu memcache.
Hãy bắt đầu khi người dùng truy cập trang đầu tiên và không có gì trong bộ đệm. Bạn bắt đầu bằng cách truy vấn bảng A trả về ID của 10 mục bạn muốn hiển thị trên trang. Đối với mỗi mục nhập đó, sau đó bạn truy vấn cơ sở dữ liệu để truy xuất các thuộc tính được liên kết với mục nhập đó và sau đó sử dụng các thuộc tính đó tạo thành một đối tượng mà mã của bạn có thể giao tiếp với (ví dụ: một đối tượng). Sau đó, bạn bỏ đối tượng đó (hoặc một dạng nối tiếp của đối tượng đó) trong memcache.
Lần thứ hai ai đó tải cùng một trang, bạn bắt đầu theo cùng một cách: bằng cách truy vấn bảng A để biết danh sách ID mục nhập bạn sẽ hiển thị. Đối với mỗi mục, trước tiên bạn vào memcache và nói, "bạn có mục #X trong bộ đệm không?" Nếu có, thì memcache trả về đối tượng mục nhập cho bạn. Nếu không, sau đó bạn cần truy vấn lại cơ sở dữ liệu để tìm nạp các thuộc tính của nó, tạo thành đối tượng và lưu trữ nó trong memcache. Hầu hết thời gian, lần thứ hai ai đó truy cập vào cùng một trang chỉ có một truy vấn cơ sở dữ liệu, tất cả các dữ liệu khác sau đó được lấy thẳng từ memcache.
Trong thực tế, điều xảy ra với hầu hết LiveJournal là hầu hết dữ liệu của hệ thống, đặc biệt là dữ liệu ít biến động hơn, được lưu trong bộ nhớ memcache và các truy vấn bổ sung vào cơ sở dữ liệu cần để hỗ trợ lược đồ bảng hẹp hoàn toàn bù trừ.
Thiết kế này giúp giải quyết vấn đề liên quan đến việc tập hợp danh sách các bài đăng được liên kết với tất cả bạn bè của bạn thành một luồng hoặc "tường" dễ dàng hơn nhiều .
Tiếp theo, hãy xem xét phân vùng cơ sở dữ liệu của bạn. Mô hình đã thảo luận ở trên bề mặt một vấn đề khác, và đó là các bảng hẹp của bạn sẽ có xu hướng rất lớn / dài. Và càng nhiều hàng thì các bảng đó càng khó thực hiện các nhiệm vụ quản trị khác. Để bù đắp điều này, có thể có ý nghĩa khi quản lý kích thước các bảng của bạn bằng cách phân vùng các bảng trong một ngày nào đó, để các cụm người dùng được phục vụ bởi một cơ sở dữ liệu và một cụm người dùng khác được phục vụ bởi một cơ sở dữ liệu riêng biệt. Điều này phân phối tải trên cơ sở dữ liệu và giữ cho các truy vấn hiệu quả.
Cuối cùng, bạn cần các chỉ số tuyệt vời. Tốc độ truy vấn của bạn sẽ phụ thuộc phần lớn vào mức độ các bảng cơ sở dữ liệu của bạn được lập chỉ mục tốt. Tôi sẽ không dành quá nhiều thời gian để thảo luận về chỉ số là gì, ngoại trừ việc nói rằng nó rất giống với một hệ thống danh mục thẻ khổng lồ để giúp việc tìm kim trong một đống cỏ khô hiệu quả hơn. Nếu bạn sử dụng mysql thì tôi khuyên bạn nên bật nhật ký truy vấn chậm để theo dõi các truy vấn mất nhiều thời gian để thực hiện. Khi một truy vấn bật lên trên radar của bạn (ví dụ vì nó chậm), sau đó tìm ra chỉ số nào bạn cần thêm vào bảng để tăng tốc độ.
"Cảm ơn bạn cho tất cả các nền tảng tuyệt vời này, nhưng thánh thần, đó là rất nhiều mã tôi sẽ phải viết."
Không cần thiết. Nhiều thư viện đã được viết khiến việc giao tiếp với memcache thực sự dễ dàng. Tuy nhiên, các thư viện khác đã mã hóa toàn bộ quy trình được mô tả ở trên; Dữ liệu :: ObjectDriver trong Perl chỉ là một thư viện như vậy. Đối với các ngôn ngữ khác, bạn sẽ cần phải làm nghiên cứu của riêng bạn.
Tôi hy vọng bạn tìm thấy câu trả lời này hữu ích. Những gì tôi đã tìm thấy thường xuyên hơn không phải là khả năng mở rộng của một hệ thống thường ngày càng ít mã hóa, và ngày càng nhiều hơn cho một chiến lược quản lý và thiết kế kỹ thuật / lưu trữ dữ liệu âm thanh.