Lịch sử System Design · Phần I · về mục lục

Chương 0. Đo lường một hệ thống đang tăng trưởng

phân vị, hàng đợi, định luật Little, Amdahl và CAP

Chương mở đầu trình bày các công cụ định lượng được dùng trong toàn bộ cuốn sách. Tình huống nghiên cứu là sự cố của Chợ Phố trong đêm khuyến mãi, khi hệ thống ngừng phục vụ trong lúc mức sử dụng CPU chỉ ở 35%. Từ tình huống này, chương lần lượt trình bày năm hướng tăng trưởng, phép đo độ trễ bằng phân vị, mô hình hàng đợi, định luật Little và giới hạn của việc bổ sung máy.

Thời gian đọc khoảng 15 phút Chương sau Chương 1. Kiến trúc một máy chủ Cập nhật 27/10/2026

Tình huống: sự cố trong đêm khuyến mãi

Chợ Phố là một trang web (site) thương mại điện tử bán đồ thủ công, do một nhóm ba người xây dựng. Toàn bộ hệ thống chạy trên một máy chủ (server): ứng dụng, cơ sở dữ liệu (database) và ảnh sản phẩm. Trong sáu tháng đầu, hệ thống vận hành ổn định. Lúc 20 giờ tối thứ Sáu, đợt khuyến mãi đầu tiên bắt đầu.

20:03
Lượng đơn hàng tăng nhanh hơn mọi ngày.
20:07
Trang sản phẩm cần 4 giây để hiển thị.
20:09
Khách hàng phản ánh thao tác thanh toán không hoàn tất.
20:12
Hầu hết các trang trả về lỗi.

Màn hình giám sát cho thấy mức sử dụng (utilization) CPU của máy chủ là 35%, bộ nhớ trong còn dư và ổ đĩa (disk) còn trống. Các chỉ số tài nguyên không cho thấy dấu hiệu quá tải, trong khi khách hàng không thể mua hàng. Nhóm đưa ra ba đề xuất: thuê máy mạnh hơn, bổ sung bộ nhớ đệm (cache), hoặc tách hệ thống thành nhiều phần. Không đề xuất nào dựa trên số liệu đo lường.

Nhật ký ứng dụng chứa một dòng lặp lại hàng nghìn lần:

logHikariPool-1 - Connection is not available, request timed out after 30000ms (total=10, active=10, idle=0, waiting=190)

Phần trong ngoặc cho biết mọi kết nối (connection) của nhóm kết nối (connection pool) đều đang bận, không kết nối nào rảnh, và 190 yêu cầu (request) đang chờ. Đây là dữ kiện quan trọng nhất của sự cố, và chương này sẽ dùng nó để xác định nguyên nhân.

Chương này trả lời ba câu hỏi. Vì sao một máy chủ với mức sử dụng CPU thấp lại ngừng phục vụ? Chợ Phố cần một hay nhiều máy? Và vì sao lựa chọn sai theo hướng nào cũng gây tốn kém?

Năm hướng tăng trưởng của một hệ thống

Cuốn sách theo dõi Chợ Phố từ một máy chủ đến hàng chục dịch vụ (service). Mỗi chương bắt đầu bằng cùng một câu hỏi: tài nguyên hoặc năng lực nào đã chạm giới hạn. Để trả lời bằng số liệu, cần xác định trước hệ thống có thể tăng trưởng theo những hướng nào.

Một hệ thống thông tin tăng trưởng theo năm hướng độc lập:

  1. Lượng truy cập. Trong đêm khuyến mãi, số yêu cầu mỗi giây tăng gần 6 lần so với giờ cao điểm thông thường.
  2. Lượng dữ liệu. Dữ liệu đơn hàng tăng vài trăm MB mỗi ngày, kéo theo thời gian sao lưu (backup) tăng dần.
  3. Số người phát triển. Khi nhiều kỹ sư cùng sửa một mã nguồn, các thay đổi bắt đầu xung đột với nhau.
  4. Tần suất triển khai (deploy). Nhu cầu triển khai tăng từ hằng tháng lên nhiều lần mỗi ngày.
  5. Phạm vi địa lý. Khi phục vụ khách hàng ở quốc gia khác, độ trễ (latency) tăng và quy định về lưu trữ dữ liệu thay đổi.

Các hướng này không tăng đồng thời, và mỗi hướng đòi hỏi một giải pháp khác. Bổ sung máy chủ giải quyết hướng thứ nhất nhưng không giải quyết hướng thứ ba. Tách dịch vụ giải quyết hướng thứ ba nhưng làm hướng thứ nhất phức tạp hơn.

HướngDấu hiệu chạm giới hạnChương liên quan
Lượng truy cậpĐộ trễ tăng rõ trong giờ cao điểmchương 3, 4, 6
Lượng dữ liệuTruy vấn chậm dù đã có chỉ mục; sao lưu kéo dàichương 5, 15, 20
Số người phát triểnXếp hàng chờ triển khai; thay đổi gây lỗi ở phần khácchương 8
Tần suất triển khaiTriển khai phải lên lịch trướcchương 7, 16
Phạm vi địa lýĐộ trễ cao với khách ở xa; yêu cầu lưu dữ liệu tại chỗchương 15, 26, 27

Sự cố đêm khuyến mãi thuộc hướng thứ nhất. Tuy nhiên, như phân tích dưới đây cho thấy, điểm nghẽn không nằm ở CPU.

Đo lường độ trễ và độ sẵn sàng

Trước sự cố, chỉ số duy nhất nhóm theo dõi là độ trễ trung bình. Giá trị trung bình không phản ánh trải nghiệm của nhóm người dùng chịu độ trễ cao nhất. Xét 1.000 yêu cầu, trong đó 980 yêu cầu mất 50 ms và số còn lại mất 5 giây. Độ trễ trung bình là 149 ms, trong khi cứ 50 yêu cầu có một yêu cầu phải chờ rất lâu.

Vì vậy độ trễ được đo bằng phân vị (percentile). Phân vị p50 là giá trị mà một nửa số yêu cầu nhanh hơn. Phân vị p99 là giá trị mà 99% số yêu cầu nhanh hơn. Trong ví dụ trên, p50 bằng mức nhanh và p99 bằng mức chậm. Hai giá trị này mô tả đúng phân bố mà giá trị trung bình che khuất.

Đi sâu: tính phân vị từ histogram

Hệ thống giám sát không lưu từng yêu cầu. Nó đếm số yêu cầu rơi vào từng khoảng thời gian (histogram bucket), ví dụ dưới 25 ms, dưới 100 ms, dưới 250 ms, rồi nội suy phân vị từ các khoảng đó. Ứng dụng cần bật histogram trước khi có thể tính phân vị. Với Spring Boot và Prometheus:

properties# Spring Boot: bật histogram cho yêu cầu HTTP; thiếu dòng này thì không có bucket để tính p99
management.metrics.distribution.percentiles-histogram.http.server.requests=true
promqlhistogram_quantile(0.99,
  sum by (le) (rate(http_server_requests_seconds_bucket[5m])))

Có ba lỗi đo lường thường gặp. Thứ nhất, lấy trung bình p99 của nhiều máy hoặc nhiều phút: phân vị không cộng trung bình được, cần gộp histogram trước khi tính. Thứ hai, chia khoảng quá thưa: nếu không có khoảng nào giữa 1 giây và 10 giây, hai giá trị p99 là 2 giây và 9 giây không phân biệt được. Thứ ba, đo bằng công cụ kiểm thử tải gửi yêu cầu tuần tự: khi hệ thống chậm, công cụ cũng gửi chậm lại và bỏ sót đúng những thời điểm xấu nhất. Gil Tene gọi lỗi này là coordinated omission.

Phân vị cao càng quan trọng khi một yêu cầu gọi nhiều dịch vụ. Nếu mỗi dịch vụ chậm với xác suất q và yêu cầu gọi n dịch vụ, xác suất yêu cầu gặp ít nhất một lời gọi chậm là 1 − (1 − q)ⁿ. Dean và Barroso gọi hiện tượng này là "the tail at scale".

Kéo ngang để xem hết hình

0% 10% 20% 30% 40% 50% 60% 70% 1 10 25 50 75 100 mỗi dịch vụ chậm 1%: 63% ở 100 lời gọi mỗi dịch vụ chậm 0,1%: 9,5% TỈ LỆ YÊU CẦU GẶP ÍT NHẤT MỘT LỜI GỌI CHẬM SỐ DỊCH VỤ ĐƯỢC GỌI TRONG MỘT YÊU CẦU 10 lời gọi: 9,6%
Hình 0.1. Đường màu nhấn ứng với trường hợp mỗi dịch vụ chậm 1% số lần; ở cuối trục, tỉ lệ lên tới khoảng 63%. Đường thấp hơn ứng với tỉ lệ chậm nhỏ hơn mười lần.

Ở giai đoạn một máy chủ, Chợ Phố chưa chịu ảnh hưởng này. Khi hệ thống được tách thành nhiều dịch vụ ở chương 8, đây là một trong những chi phí đầu tiên.

Độ sẵn sàng

Độ sẵn sàng (availability) là tỉ lệ thời gian hệ thống phục vụ được yêu cầu. Bảng dưới quy đổi các mức độ sẵn sàng thường gặp ra thời gian ngừng hoạt động cho phép, với tháng 30 ngày.

MứcThời gian ngừng cho phép mỗi thángYêu cầu vận hành
99%7,2 giờKhắc phục thủ công vẫn kịp
99,9%43 phútCảnh báo tự động và người trực
99,99%4,3 phútKhôi phục tự động
99,999%26 giâyVận hành ở nhiều vùng; triển khai không gián đoạn

Mỗi bậc thêm vào giảm thời gian ngừng cho phép mười lần và làm chi phí vận hành tăng đáng kể. Mức độ sẵn sàng cần được chọn theo mức độ chịu đựng của người dùng và ngân sách. Mức cam kết nội bộ cho một chỉ số như vậy gọi là SLO, được trình bày ở chương 17. Một khái niệm khác thường bị nhầm với độ sẵn sàng là khả năng mất dữ liệu, được phân tích ở chương 1.

Với phân vị p99, nhóm sẽ thấy người dùng đang phải chờ. Câu hỏi còn lại là họ chờ tài nguyên nào, khi CPU vẫn còn dư.

Mô hình hàng đợi và mức sử dụng

Mỗi tài nguyên dùng chung trong máy tính, như CPU, ổ đĩa hay kết nối cơ sở dữ liệu, có thể được mô hình hoá như một hàng đợi (queue). Trong mô hình này, các yêu cầu đến, chờ đến lượt, được xử lý rồi rời đi. Mức sử dụng, ký hiệu ρ, là tỉ lệ thời gian tài nguyên bận.

Mô hình hàng đợi đơn giản nhất gồm một bộ phận phục vụ và các yêu cầu đến ngẫu nhiên, ký hiệu M/M/1. Với mô hình này, thời gian một yêu cầu ở trong hệ thống là W = S / (1 − ρ), trong đó S là thời gian xử lý. Hệ quả quan trọng là thời gian chờ không tăng tuyến tính theo mức sử dụng.

Kéo ngang để xem hết hình

0x 5x 10x 15x 20x 0% 20% 40% 60% 80% 100% 20 lần ở 95% THỜI GIAN Ở TRONG HỆ THỐNG / THỜI GIAN XỬ LÝ MỨC SỬ DỤNG (ρ) 50%: 2x 80%: 5x 90%: 10x vùng độ trễ tăng vọt
Hình 0.2. Đường gần như nằm ngang khi tải thấp, cong lên khi tải cao và dựng đứng khi tài nguyên gần bão hoà. Vùng tô đỏ là miền mà một mức tăng tải nhỏ đủ làm yêu cầu quá thời gian chờ.
Mức sử dụng ρThời gian trong hệ thống ÷ thời gian xử lý
50%2
70%3,3
80%5
90%10
95%20

Một hệ thống vận hành ổn định ở 70% có thể ngừng phục vụ ở 95% mà không có thành phần nào hỏng, chỉ vì hàng đợi đã vào miền tăng nhanh. Khi nhiều bộ phận phục vụ dùng chung một hàng (mô hình M/M/c, ví dụ một nhóm kết nối), điểm uốn dời sang phải nhưng vẫn tồn tại. Do đó mỗi tài nguyên cần được đo cả mức sử dụng lẫn độ bão hoà, tức số yêu cầu đang chờ. Brendan Gregg hệ thống hoá cách làm này thành phương pháp USE (utilization, saturation, errors).

Mức sử dụng CPU của Chợ Phố trong đêm khuyến mãi còn xa điểm uốn. Tài nguyên bão hoà là một tài nguyên khác.

Định luật Little và nguyên nhân sự cố

Định luật Little được John Little chứng minh năm 1961. Trong một hệ thống ổn định, số phần tử đang ở trong hệ thống bằng tốc độ đến nhân với thời gian mỗi phần tử ở lại: L = λ × W. Định luật đúng với mọi hệ thống ổn định, không phụ thuộc cấu trúc bên trong.

Nhóm kết nối là tập kết nối cơ sở dữ liệu được mở sẵn và dùng lại. Ứng dụng của Chợ Phố quản lý nhóm kết nối bằng HikariCP, với giá trị mặc định tối đa 10 kết nối. Mỗi yêu cầu xem trang sản phẩm mượn một kết nối trong thời gian thực thi truy vấn (query). Trong điều kiện bình thường, truy vấn mất 40 ms. Đêm khuyến mãi có 200 yêu cầu mỗi giây, nên số kết nối bận trung bình là 200 × 0,04 = 8, nằm trong giới hạn của nhóm.

Trong tuần đó, nhóm bổ sung mục "sản phẩm gợi ý". Truy vấn mới không có chỉ mục (index) phù hợp và mất 400 ms. Theo định luật Little, số kết nối cần thiết trở thành 200 × 0,4 = 80, gấp tám lần kích thước nhóm.

Kéo ngang để xem hết hình

ĐÊM KHUYẾN MÃI, GIẢ SỬ TRUY VẤN VẪN NHANH Yêu cầu đến λ = 200 yêu cầu/giây Mỗi yêu cầu giữ 1 kết nối W = 40 ms = 0,04 giây L = 200 × 0,04 = 8 kết nối bận; nhóm 10 vừa đủ ĐÊM KHUYẾN MÃI THỰC TẾ: TRUY VẤN MỚI THIẾU CHỈ MỤC Yêu cầu đến vẫn λ = 200 yêu cầu/giây Mỗi yêu cầu giữ 1 kết nối W = 400 ms = 0,4 giây L = 200 × 0,4 = 80 cần 80, nhóm chỉ có 10
Hình 0.3. Hai hàng có cùng tốc độ đến và chỉ khác thời gian mỗi truy vấn giữ kết nối. Khung đỏ là trạng thái nhu cầu vượt kích thước nhóm kết nối.

Với 10 kết nối, mỗi kết nối bị giữ 0,4 giây, thông lượng (throughput) tối đa của nhóm là 10 ÷ 0,4 = 25 yêu cầu mỗi giây. Phần vượt quá là 200 − 25 = 175 yêu cầu mỗi giây phải xếp hàng, nên sau 30 giây có khoảng 5.250 yêu cầu đang chờ. Nếu mỗi khách tải lại trang một lần, tốc độ đến tăng gấp đôi thành 400 yêu cầu mỗi giây, và hàng chờ dài thêm 400 − 25 = 375 yêu cầu mỗi giây.

Sự tắc nghẽn lan sang tầng máy chủ ứng dụng. Mỗi yêu cầu đang chờ kết nối vẫn chiếm một luồng (thread) của Tomcat, máy chủ HTTP chạy bên trong ứng dụng Spring Boot. Tomcat có mặc định 200 luồng, nên chỉ sau khoảng một giây toàn bộ luồng đều ở trạng thái chờ. Tomcat tiếp tục nhận kết nối mới, mặc định tới 8.192 kết nối, nhưng để chúng chờ. Vượt mức này, kết nối mới đi vào hàng chờ của hệ điều hành (100 chỗ), rồi bị từ chối hoặc chờ đến khi quá thời gian. Phần lớn yêu cầu đang chờ nằm ở hàng kết nối của Tomcat. Chỉ những yêu cầu đã có luồng mới chờ nhóm kết nối. Vì vậy số chờ trong dòng nhật ký ở đầu chương bằng số luồng trừ số luồng đang giữ kết nối: 200 − 10 = 190.

Mức sử dụng CPU thấp được giải thích theo cùng cơ chế: các luồng đang chờ kết nối không thực thi lệnh, nên không tiêu thụ CPU.

Một chi tiết đáng chú ý khác là mức sử dụng của nhóm kết nối. Ngay cả khi truy vấn vẫn nhanh, nhóm đã ở mức 80% trong đêm khuyến mãi, tức gần điểm uốn của hình 0.2.

Quy trình chẩn đoán

Với dữ kiện từ nhật ký, quá trình chẩn đoán gồm ba bước.

  1. Kiểm tra nhóm kết nối. Chỉ số hikaricp_connections_active ở mức tối đa và hikaricp_connections_pending tăng liên tục xác nhận nhóm kết nối đã bão hoà. Các chỉ số hikaricp_* chỉ có khi ứng dụng dùng Spring Boot Actuator cùng thư viện micrometer-registry-prometheus. Chỉ số tomcat_threads_busy_threads cho thấy chuỗi bão hoà luồng, với điều kiện bật server.tomcat.mbeanregistry.enabled=true.
  2. Xác định truy vấn chậm. Truy vấn dưới đây liệt kê các truy vấn đang chạy lâu nhất trong PostgreSQL.
sql-- Các truy vấn đang chạy lâu nhất
SELECT pid, now() - query_start AS da_chay, state, left(query, 80) AS query
FROM pg_stat_activity
WHERE state <> 'idle'
ORDER BY da_chay DESC
LIMIT 5;
  1. Phân tích kế hoạch thực thi. EXPLAIN ANALYZE cho thấy truy vấn quét toàn bộ bảng (Seq Scan). Chỉ mục được tạo với CONCURRENTLY để không chặn thao tác ghi trong khi hệ thống đang nhận đơn hàng.
sqlEXPLAIN ANALYZE
SELECT id, name, price FROM products
WHERE category_id = 42
ORDER BY sold_count DESC
LIMIT 8;
-- Seq Scan on products ... rows=1200000  (quét toàn bộ bảng)

CREATE INDEX CONCURRENTLY idx_products_category_sold
  ON products (category_id, sold_count DESC);

Sau sự cố, nhóm tạo chỉ mục và tăng kích thước nhóm kết nối lên 20. Nhóm cũng giảm thời gian chờ kết nối xuống 3 giây để yêu cầu thất bại sớm thay vì giữ luồng, và bổ sung đo phân vị p99. Cách xác định kích thước nhóm kết nối được trình bày ở chương 2.

propertiesspring.datasource.hikari.maximum-pool-size=20
# chờ tối đa 3 giây thay vì 30 giây: thất bại sớm thay vì giữ luồng
spring.datasource.hikari.connection-timeout=3000
Tài nguyên bão hoà đầu tiên thường không phải CPU. Đó có thể là nhóm kết nối, số luồng hoặc một giá trị quá thời gian mặc định. Các giới hạn mặc định thường gặp được tổng hợp ở Phụ lục D.

Nguyên nhân sự cố đã được xác định. Câu hỏi tiếp theo là giới hạn của việc bổ sung máy khi lượng truy cập tăng gấp nhiều lần.

Giới hạn của việc bổ sung máy

Định luật Amdahl (1967) phát biểu rằng khi bổ sung bộ xử lý, tốc độ tối đa bị giới hạn bởi phần công việc phải thực hiện tuần tự. Nếu tỉ lệ công việc có thể song song hoá là p, thì với N máy, tốc độ tối đa là S(N) = 1 / ((1 − p) + p/N). Với 90% song song và 64 máy: 1 / (0,1 + 0,9/64) ≈ 8,8 lần.

Trong thực tế, giới hạn còn chặt hơn. Khi các máy phải phối hợp với nhau, ví dụ qua khoá dùng chung hoặc đồng bộ bộ nhớ đệm, bổ sung máy có thể làm hệ thống chậm đi. Neil Gunther mô tả hiện tượng này bằng Universal Scalability Law: C(N) = N / (1 + α(N − 1) + βN(N − 1)). Trong công thức, α là phần tranh chấp, tương ứng phần tuần tự của Amdahl, còn β là chi phí phối hợp. Khi β lớn hơn 0, đường tăng tốc đạt cực đại tại N ≈ √((1 − α)/β). Với α = 0,05 và β = 0,001, cực đại nằm ở khoảng 31 máy với tốc độ gấp khoảng 9 lần. Hai hệ số được ước lượng bằng cách khớp đường cong với kết quả kiểm thử tải.

Kéo ngang để xem hết hình

0x 10x 20x 30x 40x 1 2 4 8 16 32 64 99% song song được: 39x ở 64 máy 95%: 15x, trần 20x 90%: 8,8x, trần 10x 50%: trần 2x USL: đỉnh ≈ 9x ở 31 máy TĂNG TỐC SO VỚI MỘT MÁY SỐ MÁY (HOẶC SỐ CORE)
Hình 0.4. Đường màu nhấn vẫn tăng ở cuối trục. Các đường Amdahl còn lại tiệm cận một giới hạn trên mà việc bổ sung máy không vượt qua được. Đường nét đứt đỏ theo USL đạt cực đại rồi đi xuống, vì chi phí phối hợp tăng nhanh hơn lợi ích của mỗi máy thêm vào.

Ở Chợ Phố, phần tuần tự là cơ sở dữ liệu: mọi đơn hàng đều được ghi vào cùng một cơ sở dữ liệu, bất kể số máy chủ ứng dụng.

Định lý CAP và PACELC

Nhân bản cơ sở dữ liệu dẫn tới một giới hạn khác. Giả sử dữ liệu có nhiều bản sao (replica) và kết nối mạng giữa chúng bị đứt. Khi đó hệ thống chỉ có hai lựa chọn: tiếp tục trả lời với nguy cơ trả dữ liệu cũ, hoặc từ chối một phần yêu cầu để tránh sai lệch. Ví dụ, khi hai khách hàng ở hai phía cùng đặt món hàng cuối cùng, hệ thống hoặc bán trùng, hoặc từ chối một bên. Đây là nội dung của định lý CAP, trong đó C là tính nhất quán (consistency) và P là sự phân vùng mạng (partition). A là tính sẵn sàng theo nghĩa của CAP: mọi yêu cầu tới một nút còn hoạt động đều nhận được trả lời. Khái niệm này khác với độ sẵn sàng tính theo thời gian ở mục đo lường. Eric Brewer nêu giả thuyết năm 2000. Seth Gilbert và Nancy Lynch chứng minh định lý năm 2002.

Năm 2012, Daniel Abadi chỉ ra rằng ngay cả khi mạng hoạt động bình thường, hệ thống vẫn phải lựa chọn giữa độ trễ thấp và tính nhất quán. Nguyên nhân là việc chờ các bản sao xác nhận làm tăng độ trễ. Cách mô tả đầy đủ này được gọi là PACELC, với E chỉ trạng thái bình thường (else) và L chỉ độ trễ (latency).

Kéo ngang để xem hết hình

Các bản sao có mất liên lạc với nhau không? CÓ (P): phần CAP KHÔNG (E): phần ELC Chọn A (availability) hoặc C (consistency) không có lựa chọn thứ ba khi mạng đã đứt Chọn L (latency) hoặc C (consistency) đánh đổi này có ở mọi yêu cầu, kể cả lúc bình thường A: vẫn trả lời có thể là dữ liệu cũ C: từ chối hoặc chờ để không trả dữ liệu sai L: trả lời ngay từ bản sao gần nhất C: chờ các bản sao đồng ý rồi mới trả lời
Hình 0.5. Nhánh trái chỉ xảy ra khi kết nối mạng giữa các bản sao bị đứt. Nhánh phải áp dụng cho mọi yêu cầu. Một hệ thống được mô tả bằng hai lựa chọn: PA/EL nghĩa là khi mạng đứt vẫn trả lời và khi bình thường ưu tiên độ trễ thấp. PC/EC nghĩa là luôn ưu tiên tính nhất quán.

Trong hệ thống thực tế, lựa chọn này thể hiện qua cách sao chép dữ liệu. Sao chép đồng bộ tương ứng lựa chọn C, còn sao chép bất đồng bộ tương ứng L và A (chương 5). Các loại dữ liệu khác nhau có thể cần các mức nhất quán khác nhau, được phân tích ở chương 12. Sau sự cố, đã có đề xuất nhân bản cơ sở dữ liệu ra ba nơi.

Nguyên tắc đủ dùng

Đề xuất nhân bản cơ sở dữ liệu đi kèm tách vi dịch vụ (microservices) và triển khai Kubernetes, theo kiến trúc của các tổ chức lớn (chương 8, 9). Các biện pháp này giải quyết những vấn đề mà Chợ Phố chưa gặp. Đồng thời, các biện pháp này đưa vào các chi phí mới: nhiều thành phần cần vận hành hơn, nhiều dạng lỗi hơn, và tốc độ phát triển tính năng giảm.

Áp dụng quá sớm

Một nhóm ba người vận hành mười dịch vụ. Phần lớn thời gian dành cho vận hành hạ tầng thay vì tính năng mà khách hàng cần.

Áp dụng quá muộn

Hệ thống có hàng nghìn khách hàng nhưng chưa từng khôi phục (restore) thử bản sao lưu (chương 1). Sự cố lớn đầu tiên cũng là lúc phát hiện bản sao lưu không dùng được.

Nguyên tắc của cuốn sách là chỉ chuyển sang giai đoạn kiến trúc tiếp theo khi số liệu đo lường cho thấy một hướng tăng trưởng đã chạm giới hạn. Ngoại lệ là các biện pháp bảo vệ dữ liệu và phát hiện sự cố: sao lưu hằng ngày có khôi phục thử, cảnh báo khi trang lỗi hoặc chậm, và nhật ký tập trung. Các biện pháp này có chi phí thấp và cần được áp dụng từ đầu.

Ước lượng năng lực cho Chợ Phố

Các công cụ ở trên đủ để trả lời câu hỏi mà nhóm tranh luận trong đêm sự cố. Chợ Phố có khoảng 50.000 người dùng mỗi ngày, mỗi người tạo khoảng 20 yêu cầu.

  1. Số yêu cầu mỗi giây. 50.000 × 20 ÷ 86.400 giây ≈ 12 yêu cầu mỗi giây trung bình. Giờ cao điểm thông thường gấp khoảng 3 lần, tức khoảng 35; đêm khuyến mãi là 200.
  2. Số kết nối cơ sở dữ liệu. Theo định luật Little, giờ cao điểm cần 35 × 0,04 ≈ 1,4 kết nối, còn đêm khuyến mãi cần đúng số đã tính ở mục trước. Nhóm kết nối sau khi điều chỉnh đủ đáp ứng và vẫn thấp hơn nhiều so với giới hạn mặc định của PostgreSQL.
  3. Số luồng và băng thông. Mỗi yêu cầu giữ một luồng khoảng 50 ms, nên giờ cao điểm chỉ có ≈ 1,8 luồng bận, còn đêm khuyến mãi khoảng 10 trên 200 luồng của Tomcat. Mỗi trang trả về khoảng 50 KB, với 1 KB = 1.000 byte, nên băng thông ra là ≈ 14 Mbit/giây lúc cao điểm và 80 Mbit/giây trong đêm khuyến mãi.
  4. Dung lượng dữ liệu. Mỗi người dùng tạo khoảng 5 dòng dữ liệu 1 KB mỗi ngày, tương ứng 250 MB mỗi ngày và khoảng 91 GB mỗi năm, nằm trong khả năng của một ổ đĩa thông thường.
  5. Kết luận. Một máy chủ vẫn đáp ứng được tải hiện tại. Nguyên nhân sự cố là một chỉ mục thiếu, một nhóm kết nối có kích thước mặc định và việc không đo phân vị.
Ước lượng nhanh xác định cấp độ của bài toán. Nó phân biệt nhu cầu một máy với nhu cầu hàng trăm máy. Giá trị chính xác cần được xác định bằng kiểm thử tải.

Hướng tiếp theo

Sau các điều chỉnh, hệ thống một máy chủ vận hành ổn định trở lại. Tuy nhiên, toàn bộ dữ liệu vẫn nằm trên một ổ đĩa của một máy. Nếu ổ đĩa đó hỏng, Chợ Phố mất bao nhiêu dữ liệu? Bản sao lưu gần nhất đã từng được khôi phục thử hay chưa? Chương 1 phân tích các câu hỏi này.

Tóm tắt chương

  1. Trước mỗi thay đổi kiến trúc, cần xác định hướng tăng trưởng nào đã chạm giới hạn. Năm hướng: lượng truy cập, lượng dữ liệu, số người phát triển, tần suất triển khai, phạm vi địa lý.
  2. Độ trễ được đo bằng phân vị. Giá trị trung bình che khuất nhóm người dùng chịu độ trễ cao nhất.
  3. Mỗi bậc độ sẵn sàng giảm thời gian ngừng cho phép mười lần. Mức cần đạt được chọn theo người dùng và ngân sách.
  4. Thời gian chờ tăng phi tuyến theo mức sử dụng. Không nên vận hành tài nguyên sát mức bão hoà.
  5. L = λ × W. Khi truy vấn chậm đi, số kết nối cần thiết tăng tương ứng, và nhóm kết nối bão hoà trước CPU.
  6. Phần tuần tự giới hạn lợi ích của việc bổ sung máy. Chi phí phối hợp có thể làm hiệu năng giảm khi thêm máy.
  7. Nhân bản dữ liệu buộc phải lựa chọn: khi mạng đứt, giữa tính sẵn sàng và tính nhất quán; khi bình thường, giữa độ trễ và tính nhất quán.
  8. Sao lưu có khôi phục thử và cảnh báo cơ bản cần có từ đầu. Các thay đổi kiến trúc khác chờ số liệu đo lường.

Tài liệu tham khảo

  • John D. C. Little, "A Proof for the Queuing Formula: L = λW", Operations Research, 1961.
  • Gene Amdahl, "Validity of the single processor approach to achieving large scale computing capabilities", AFIPS Spring Joint Computer Conference, 1967.
  • Neil J. Gunther, Guerrilla Capacity Planning, Springer, 2007: Universal Scalability Law.
  • Eric Brewer, bài phát biểu tại PODC 2000; Seth Gilbert, Nancy Lynch, ACM SIGACT News, 2002.
  • Daniel Abadi, "Consistency Tradeoffs in Modern Distributed Database System Design", IEEE Computer, 2012.
  • Jeffrey Dean, Luiz André Barroso, "The Tail at Scale", Communications of the ACM, 2013.
  • Brendan Gregg, The USE Method. Gil Tene, "How NOT to Measure Latency".
  • Google, Site Reliability Engineering: các chương về SLO và độ sẵn sàng.
  • Phụ lục D: giới hạn mặc định của máy chủ ứng dụng, cơ sở dữ liệu, nhóm kết nối, hệ điều hành, cân bằng tải và Kubernetes.

Chợ Phố là tình huống giả định. Các giá trị mặc định (HikariCP 10 kết nối và 30 giây chờ, Tomcat 200 luồng, PostgreSQL 100 kết nối) được đối chiếu tài liệu chính thức trong _build/c00-verify.md. Các phép tính được kiểm lại bằng _build/c00_calc.py.