Nhật ký kỹ thuật · Hà Nội · Backend & CloudVol. 2026
← Tất cả bài viết
Số 0418 phút đọc

Đừng tin con số trung bình

Dashboard báo 150 ms, đèn xanh sáng, vậy mà user vẫn nhắn “app lag quá”. Vì sao con số trung bình che giấu nỗi đau, p50, p99, p999 thực sự nói gì, phép tính 63% biến một service khỏe mạnh thành một trang chậm, cách tính percentile mà không tự lừa mình, và nên nói gì với sếp.

  • performance
  • latency
  • percentiles
  • observability
  • ddia
Tranh khắc gỗ sảnh nhà ga với chiếc đồng hồ khổng lồ: hành khách chảy qua các cổng mở, riêng một cổng xa có hàng chờ dài ngoằn ngoèo và ông trưởng ga cau mày nhìn đồng hồ quả quýt.
Trong bài này
  1. Cái panel màu xanh
  2. Con số trung bình nói dối thế nào: 100 request
  3. Percentile: p50, p95, p99, p999
  4. Ai quan tâm đến p999?
  5. Khuếch đại đuôi: phép tính 63%
  6. Trung bình nói dối cả hai chiều
  7. Tính percentile mà không tự lừa mình
  8. Đừng bao giờ lấy trung bình của percentile
  9. Prometheus và HdrHistogram
  10. Coordinated omission
  11. Thuần hóa cái đuôi
  12. Nói chuyện với sếp
  13. Biến nó thành SLO
  14. Kết: hãy hỏi về cái đuôi
  15. Câu hỏi luyện tập

Cái panel màu xanh

Stand-up sáng thứ Hai. Panel Grafana trên màn hình ghi thời gian phản hồi trung bình: 150 ms, màu xanh, thoải mái dưới ngưỡng 200 ms của team. Hai tin nhắn bên dưới ở kênh support: “checkout thỉnh thoảng quay tròn tầm ba giây, app hỏng hả?”. Mình trả lời đúng như một backend engineer vừa nhìn thấy panel xanh vẫn hay trả lời: số liệu ổn mà, chắc do mạng của họ. Rồi có người gửi một đoạn video quay màn hình. Ba giây quay tròn, trong một hệ thống đang báo 150 ms. Cả hai điều cùng đúng một lúc, và cả bài viết này xoay quanh đúng chuyện đó.

Đây là bài thứ ba trong loạt ghi chú của mình về Designing Data-Intensive Applications của Martin Kleppmann (chương 1 ở bản 1, phần mô tả hiệu năng). Ý chính gói được trong một câu: con số trung bình mô tả một khách hàng không tồn tại. Nếu đo độ trễ, hãy đo bằng percentile, và nhớ rằng cái đuôi chậm không đứng yên một chỗ: mỗi lần một trang gọi nhiều service, nó lại bị nhân lên.

dashboard hiển thị
150 ms
user cảm nhận
3 s
trang dính một lời gọi p99, khi có 100 lời gọi
63%
doanh số mất cho mỗi 100 ms chậm thêm (Amazon)
~1%

Con số trung bình nói dối thế nào: 100 request

Mình làm cho cú lừa này cụ thể bằng một mẫu đồ chơi mà bạn kiểm bằng tay được. Một trăm request tới endpoint checkout, xếp từ nhanh nhất đến chậm nhất. Đa số nhanh, một ít chậm, hai cái tệ hại, khá giống hình dạng của hệ thống thật.

Thứ hạng sau khi xếpĐộ trễ mỗi cáiSố lượngTổng thời gian
1 đến 8040 ms803.200 ms
81 đến 92100 ms121.200 ms
93 đến 98500 ms63.000 ms
993.000 ms13.000 ms
1004.600 ms14.600 ms
Mẫu: 80 + 12 + 6 + 1 + 1 là 100 request và tổng cộng 15.000 ms chờ đợi.

Tổng thời gian là 15.000 ms cho 100 request, nên trung bình đúng 150 ms, đúng con số dashboard hiển thị. Giờ đọc percentile bằng cách đếm dọc danh sách đã xếp:

Thống kêGiá trịAi thực sự trải qua nó
Trung bình150 msKhông ai cả. Các giá trị có mặt là 40, 100, 500, 3.000, 4.600.
p50 (trung vị)40 msRequest điển hình. Cái thứ 50 theo thứ tự.
p95500 msKhoảng 1 trên 20 request chờ ngần này hoặc hơn. Cái thứ 95 theo thứ tự.
p993.000 msKhoảng 1 trên 100 (ở đây là 2 trên 100). Cái thứ 99 theo thứ tự.
Lớn nhất4.600 msUser xui nhất trong giờ.
Percentile theo nearest-rank trên 100 request ở trên. Trung bình (150 ms) chẳng gần p50 (40 ms) mà cũng chẳng gần nỗi đau (p99 là 3 giây).

Đọc dòng đầu hai lần. Không request nào trong mẫu mất 150 ms. Trung bình là phép tính của một khách vừa nhanh vừa thảm họa, và người đó chưa bao giờ bước vào cửa. Tám mươi phần trăm user nhận 40 ms, tốt hơn dashboard nói; hai user nhận một kết quả họ sẽ nhớ cả tuần, tệ hơn nhiều. Trung bình là trọng tâm của phân phối, không phải một vị trí mà ai đó đang đứng.

percentiles.sqlsql
-- PostgreSQL: percentile của một giờ gần nhất, tính thẳng từ request log
SELECT
  count(*)                                                  AS n,
  round(avg(ms))                                            AS mean_ms,
  percentile_disc(0.50) WITHIN GROUP (ORDER BY ms)          AS p50_ms,
  percentile_disc(0.95) WITHIN GROUP (ORDER BY ms)          AS p95_ms,
  percentile_disc(0.99) WITHIN GROUP (ORDER BY ms)          AS p99_ms
FROM request_log
WHERE route = 'POST /checkout'
  AND ts > now() - interval '1 hour';
-- percentile_disc trả về một giá trị có thật (nearest-rank, 3000 với mẫu của ta).
-- percentile_cont nội suy giữa hai giá trị kề nhau (3016 với mẫu của ta): mượt hơn, nhưng không phải một request có thật.

Percentile: p50, p95, p99, p999

Vậy đọc cái gì thay cho trung bình? Hình dung một nhà ga giờ cao điểm. Hai mươi cổng soi vé, ông trưởng ga đứng dưới chiếc đồng hồ lớn bấm giờ từng hành khách qua cổng. Nếu ông chỉ ghi một con số cho cả buổi sáng, “hành khách trung bình mất 40 giây”, ông đang mô tả một người không có thật: đa số qua trong 15 giây, và vài người kẹt ở đúng cổng có máy soi vé bị treo mười phút. Một bản báo cáo tốt hơn xếp mọi người theo thời gian đã mất rồi đọc theo vị trí trong hàng. Vị trí 50 trên 100 là hành khách điển hình. Vị trí 99 là người xui xẻo.

Tranh in màu chiếc đồng hồ bấm giờ bỏ túi bằng bạc cổ, nắp mở, đặt cạnh một đồng hồ cát có vài hạt cát mắc kẹt ở cổ.
Bản III. Đồng hồ bấm giờ và những hạt cát mắc kẹt. Đồng hồ bấm giờ cho biết hạt cát điển hình rơi mất bao lâu; đồng hồ cát thì thành thật về vài hạt không chịu rơi.

Đó chính là percentile. Xếp mọi thời gian phản hồi từ nhanh đến chậm; giá trị pN là mức thời gian mà N% request nhanh hơn, tức là (100 − N)% còn lại chậm hơn. Những cái tên bạn sẽ gặp:

  • p50, trung vị: một nửa số request nhanh hơn. Đây là con số đơn lẻ tốt nhất cho câu hỏi “điển hình là bao nhiêu”.
  • p95, p99, p999: mức mà 5%, 1% và 0,1% số request chậm hơn. Gộp lại, chúng là tail latency (độ trễ ở đuôi).
  • Đọc ngược lại: nếu p50 là 200 ms nhưng p99 là 4 giây, thì cứ một trăm request có một cái chờ bốn giây. Một user lướt một trăm trang sẽ trung bình gặp độ chờ đó một lần, và có 63% khả năng gặp ít nhất một lần.
DWG 03-ASCALE · NTS2002,7004,3001,8005602501106020102040801603206401.3 s2.6 s5.1 sđộ trễ, ms (thang log)số request mỗi khoảng (chiều cao cột: thang căn bậc hai)p50 ≈ 60 mstrung bình ≈ 111 msp99 ≈ 1.16 sp999 ≈ 3.84 scái đuôi: 190 trên 10.000 request
Hình 1. Histogram độ trễ minh họa cho 10.000 request, vẽ trên trục log. Trung bình nằm hơi lệch phải so với phần thân, p50 nằm trong thân, còn p99 và p999 ở rất xa trong đuôi, vượt qua đó chỉ còn 100 và 10 request.

Ai quan tâm đến p999?

Amazon, nổi tiếng với chuyện này. Sách mô tả cách họ đặt yêu cầu cho các service nội bộ ở percentile thứ 99,9, dù nó chỉ chạm một request trên một nghìn. Lý lẽ mới là chỗ mình thấy ấn tượng: những khách có request chậm nhất thường chính là những khách có nhiều dữ liệu nhất trong tài khoản, nghĩa là những người đã mua nhiều nhất, khách hàng giá trị nhất. Trang của họ chậm vì nó lớn, và họ đúng là những người bạn không thể chọc giận. Sách cũng nhắc quan sát của Amazon rằng response time chậm thêm 100 ms thì doanh số giảm khoảng 1%.

Đối trọng thành thật, cũng có trong sách: đẩy lên p9999 tốn kém rất nhanh, và đến một lúc nào đó độ chậm do các sự kiện ngẫu nhiên nằm ngoài tầm kiểm soát (GC pause, rớt gói tin, page fault), lợi ích không còn bù được chi phí. Bạn chọn percentile mà business của bạn thực sự quan tâm.

Khuếch đại đuôi: phép tính 63%

Giờ đến phần làm mình đặt cuốn sách xuống và mở máy tính. Giả sử một service hoàn toàn khỏe theo chuẩn của chính bạn: p99 là một giây, tức 99% số lời gọi nhanh hơn. Ổn. Nhưng một trang hiện đại không gọi một service. Trang sản phẩm có thể gọi pricing, tồn kho, review, gợi ý, profile, một slot quảng cáo, một service feature flag: hàng chục đến cả trăm lời gọi backend, thường là song song. Trang chỉ xong khi lời gọi chậm nhất trả về.

DWG 03-BSCALE · NTSRequest trangchờ tất cảservice 0121 msservice 0217 msservice 031.000 msservice 0424 msservice 0519 ms· · · 94 lời gọi nữa, đều nhanhservice 10023 mstrang xong lúc 1.000 ms: kẻ chậm nhất quyết địnhp99 của một lời gọi là 1 s
Hình 2. Một request trang, một trăm lời gọi backend. Chín mươi chín cái xong trong khoảng 20 ms; một cái rơi vào đuôi p99 với đúng một giây, và trang phải chờ nó.

Mỗi lời gọi có 99% khả năng nhanh, và chúng độc lập với nhau. Khả năng cả 100 đều nhanh là 0,99 nhân với chính nó một trăm lần. Vậy khả năng có ít nhất một cái chậm là phần bù:

amplification.tsts
// P(ít nhất một trong n lời gọi độc lập rơi vào phần chậm nhất (1 - q))
const hitTail = (n: number, q = 0.99) => 1 - q ** n;

hitTail(1);          // 0.010  -> 1,0%
hitTail(10);         // 0.096  -> 9,6%
hitTail(100);        // 0.634  -> 63,4%   <- con số chính
hitTail(100, 0.999); // 0.095  -> 9,5%    <- cùng trang đó nhưng backend đạt p999
Số lời gọi mỗi trangBackend ở p99Backend ở p999
11,0%0,1%
109,6%1,0%
5039,5%4,9%
10063,4%9,5%
20086,6%18,1%
50099,3%39,4%
Tỷ lệ lượt tải trang có chứa ít nhất một lời gọi từ phần đuôi chậm, giả sử các lời gọi độc lập.
DWG 03-CSCALE · NTS0%25%50%75%100%050100150200số lời gọi backend để dựng một trangP(ít nhất một lời gọi rơi vào đuôi)100 lời gọi: 63%100 lời gọi: 9,5%mỗi lời gọi p95mỗi lời gọi p99mỗi lời gọi p999
Hình 3. Cùng bảng trên nhưng vẽ thành đường cong. Với 100 lời gọi mỗi trang, một backend p99 làm chậm 63% lượt tải trang; ngay cả backend p999 vẫn làm chậm khoảng 10% lượt tải, và muốn giữ trang ở mức 1% thì backend phải đạt cỡ p9999.

Vậy là từng service, xét riêng, trông đều ổn. Đặt chúng sau một trang và trang chậm gần như mọi lúc. Đó là tail latency amplification, và là lý do sách muốn bạn nhìn percentile của thứ user chạm vào, chứ không phải của các bộ phận. Nó cũng là, như một hệ quả phụ, một lý do khiến kiến trúc microservices có thể chậm hơn cái monolith mà nó thay thế: mỗi service thêm vào trang là thêm một lần bốc thăm. (Phép nhân này cũng nằm sẵn trong đường đọc của một timeline, xem bài 01.)

Trung bình nói dối cả hai chiều

Cho đến giờ con số trung bình lạc quan quá mức. Ý của sách rộng hơn: nó bị outlier bóp méo theo cả hai chiều, nên là nền tảng tồi cho cả sự yên tâm lẫn báo động.

  • Lên, báo động giả. Một lô 10.000 request ở 40 ms, cộng một request bị kẹt mất 60 giây, có trung bình 46 ms. Alert nổ; user vẫn ổn. Một dòng log xấu đã đẩy con số chính của bạn lên 15%.
  • Xuống, nỗi đau thật bị che. Giả sử một triệu lượt ping health check mất 1 ms mỗi cái và mười nghìn lượt checkout thật mất 800 ms. Trung bình là khoảng 9 ms. Dashboard trộn cả hai báo một hệ thống khỏe, trong khi mọi khách thật chờ gần một giây.

Trường hợp thứ hai cho thêm một bài học. Request thật là 10.000 trên 1.010.000, tức 0,99%, ngay dưới ngưỡng 1%, nên ngay cả p99 của bể trộn đó cũng chỉ 1 ms. Percentile không phải phép màu; nó thừa hưởng mọi thứ bạn đổ vào histogram. Cách chữa là tách theo route (checkout, search, health) và đừng bao giờ để traffic rẻ pha loãng traffic đắt.

Tính percentile mà không tự lừa mình

Đừng bao giờ lấy trung bình của percentile

Lỗi phổ biến nhất mình hay gặp: mỗi server báo p99 của riêng nó, và dashboard hiện trung bình của các p99 đó làm p99. Về mặt toán học điều này vô nghĩa. Giả sử server A xử lý 9.000 request với p99 là 120 ms, server B xử lý 1.000 request với p99 là 2.400 ms. Trung bình của hai số là 1.260 ms. P99 thật trên cả 10.000 request phụ thuộc vào toàn bộ hình dạng của cả hai phân phối, và không có hàm nào của hai con số kia cho bạn đáp án. Tương tự khi lấy trung bình các p99 theo phút để ra p99 theo giờ.

Cách đúng là gộp phân phối trước, rồi mới lấy percentile. Nghĩa là mỗi server gửi lên một histogram (số đếm theo từng bucket độ trễ), các histogram cộng với nhau từng bucket một, và bạn đọc percentile trên histogram đã gộp.

Prometheus và HdrHistogram

Với Prometheus, expose một metric dạng histogram và để câu query lo việc gộp. Để ý thứ tự: sum by (le) cộng các bộ đếm bucket của mọi instance trước, rồi histogram_quantile mới nội suy.

p99.promqlpromql
# Đúng: gộp bucket của mọi pod, rồi mới lấy percentile thứ 99
histogram_quantile(
  0.99,
  sum by (le) (rate(http_request_duration_seconds_bucket{route="/checkout"}[5m]))
)

# Sai: p99 cho từng pod, rồi lấy trung bình các p99
avg(
  histogram_quantile(0.99, rate(http_request_duration_seconds_bucket{route="/checkout"}[5m]))
)

Hai lưu ý. Một, histogram_quantile nội suy tuyến tính bên trong một bucket, nên độ chính xác bị giới hạn bởi ranh giới bucket: nếu các bucket cao nhất là 1 s và 10 s, thì p99 bạn nhận được chỉ là “đâu đó giữa hai mốc”. Hãy đặt một mép bucket tại mọi ngưỡng bạn cam kết (ví dụ 0,5 s cho SLO) và thêm vài mép quanh đuôi. Hai, quantile summary tính sẵn trên từng instance không thể gộp được, đó là lý do nên chuộng histogram cho mọi thứ cần aggregate.

Với việc đo ở phía ứng dụng, HdrHistogram là công cụ quen thuộc: nó ghi giá trị trong dải rất rộng (nano giây tới hàng giờ) với độ chính xác tương đối cố định, ví dụ ba chữ số có nghĩa, trong một lượng bộ nhớ nhỏ và không đổi, và hai histogram có thể cộng được với nhau.

Hdr.javajava
Histogram a = new Histogram(3_600_000_000L, 3); // theo dõi tới 1 giờ tính bằng micro giây, 3 chữ số có nghĩa
Histogram b = new Histogram(3_600_000_000L, 3);
a.recordValue(micros);          // với mỗi request ở service A
b.recordValue(otherMicros);     // với mỗi request ở service B

a.add(b);                       // gộp: cộng từng bucket
long p99 = a.getValueAtPercentile(99.0);   // p99 thật của cả hai tập

Coordinated omission

Một cái bẫy cuối, cho ai hay load test. Benchmark ngây thơ gửi một request, chờ trả lời, rồi gửi cái tiếp theo. Khi server đứng hình năm giây, bộ sinh tải cũng ngừng gửi năm giây, nên hàng trăm request lẽ ra đã xếp hàng sau cú đứng hình đó không bao giờ được gửi và không bao giờ được đo. Kết quả: một p99 đẹp đẽ do một client lịch sự đã ngừng hỏi. Hiện tượng này gọi là coordinated omission (thuật ngữ của Gil Tene). Cách chữa là gửi theo lịch cố định, không phụ thuộc vào phản hồi, và tính thời gian của mỗi request từ lúc nó đáng lẽ được gửi; wrk2 làm việc này cho HTTP load, còn HdrHistogram có recordValueWithExpectedInterval để điền bù các mẫu bị thiếu.

Thuần hóa cái đuôi

Ngoài sách. Khi đã nhìn thấy cái đuôi, ta làm gì với nó? Sách cho bạn biết vì sao nó đau; các kỹ thuật dưới đây là những thứ mình thấy hiệu quả hoặc đọc được trong bài “The Tail at Scale” của Dean và Barroso. Chúng nằm ngoài sách, và cái nào cũng có giá.

  • Hedged request. Gửi lời gọi tới một replica; nếu không có phản hồi trong khoảng p95 của chính lời gọi đó, gửi bản sao tới replica thứ hai và lấy cái nào về trước, hủy cái còn lại. Chỉ dùng cho thao tác đọc idempotent. Bài báo ghi nhận p999 cải thiện rõ rệt chỉ với cỡ vài phần trăm request thừa trong thí nghiệm BigTable của họ (mình trích từ trí nhớ, nên hãy kiểm lại số liệu). Cái giá là tải phụ và nhu cầu cancellation thật sự.
  • Timeout kèm ngân sách. Một lời gọi không có timeout thừa hưởng hành vi tệ nhất của thứ nó gọi. Đặt timeout từng lời gọi gần p99,9 của backend, truyền một deadline tổng xuống cả chuỗi, và giới hạn retry (ngân sách retry khoảng 10% traffic) để một cơn bão timeout không thành sự cố thứ hai.
  • Ít hop tuần tự hơn. Độ trễ các lời gọi trong một chuỗi cộng lại, đuôi của chúng cũng vậy. Bỏ những hop chỉ tồn tại cho gọn gàng, cache thứ ít đổi, và gọi song song những việc độc lập. Đánh đổi chính là phép tính fan-out ở trên: gọi song song chặn được tổng nhưng tăng cơ hội dính đuôi, nên giữ fan-out nhỏ đến mức trang thực sự cần.
  • Degrade thay vì chờ. Cho các phần tùy chọn của trang (gợi ý, quảng cáo) một deadline ngắn và render mà không có chúng khi trễ. Khách thấy một trang đơn giản hơn chút ngay lập tức, thay vì một trang hoàn hảo sau ba giây.

Để ý thứ còn thiếu: “làm mọi service nhanh hơn ở mức trung bình”. Gọt trung bình gần như không giúp gì cho cái đuôi, vì đuôi thường do một thứ khác với đường đi điển hình gây ra (cache lạnh, GC pause, hàng xóm ồn ào, hàng đợi đầy, chờ lock trên một dòng nóng, compaction làm khựng một LSM-tree).

Nói chuyện với sếp

Quay lại buổi stand-up. Sếp bảo dashboard 150 ms là ngon rồi, hỏi sao user vẫn than. Trực giác của mình lúc đó chưa thành từ vựng nhưng đúng hướng: cần xem các request chậm nhất là bao nhiêu; gần 150 ms thì không sao, còn hai ba giây thì phải tìm cách. Trực giác đó chính là tư duy percentile mặc thường phục. Những câu mình sẽ nói bây giờ:

  1. “Trung bình bị đa số request nhanh kéo xuống, nên nó không cho thấy được các request chậm.”
  2. “Em đề xuất xem histogram và p95, p99 thay vào đó.”
  3. “Nếu p99 là 3 giây thì mỗi ngày 1% lượt dùng có trải nghiệm tệ. User quên 99 lần mượt và nhớ lần lag.”
  4. “Nên mình đặt mục tiêu trên cái đuôi, ví dụ p99 dưới 500 ms.”

Biến nó thành SLO

Câu cuối chính là một service level objective (SLO), và sách có nhắc rằng SLO, SLA thường được viết bằng percentile chính vì lý do này. Một SLO đầy đủ nêu route, percentile, ngưỡng và cửa sổ thời gian: 99% request POST /checkout hoàn thành dưới 500 ms, đo trong 28 ngày. Cách nhìn tương đương: error budget là 1% còn lại. Nếu trong cả cửa sổ có 1,4% request chậm hơn 500 ms, bạn đã tiêu lố ngân sách 1% và việc về độ tin cậy được ưu tiên trước tính năng. Cách đóng khung này (và ý tưởng ngân sách) là thực hành SRE tiêu chuẩn chứ không nằm trong sách, nhưng nó biến “user đang than” thành một con số mà cả team có thể lên kế hoạch quanh nó.

slo-check.promqlpromql
# Tỷ lệ request /checkout nhanh hơn 500 ms trong 28 ngày gần nhất
# (cần có mép bucket đúng tại le="0.5")
  sum(increase(http_request_duration_seconds_bucket{route="/checkout", le="0.5"}[28d]))
/
  sum(increase(http_request_duration_seconds_count{route="/checkout"}[28d]))
# SLO đạt khi giá trị này >= 0.99

Kết: hãy hỏi về cái đuôi

Khi ai đó nói với bạn con số trung bình, hãy hỏi: còn cái đuôi trông thế nào?

Câu thần chú của mình từ sáng thứ Hai đó

Nếu chỉ giữ bốn điều từ bài này: trung bình không mô tả ai cả; p50 là user điển hình, p99 và p999 là cái đuôi, và đuôi là nơi các khách hàng giá trị nhất của bạn hay sống; một trang gọi 100 service ở mức p99 sẽ chậm 63% thời gian; và percentile phải gộp từ histogram, không bao giờ lấy trung bình. Mình thêm một luật phụ: tách theo route, và test bằng một client không lịch sự chờ đợi. Panel Grafana trên tường vẫn xanh. Chỉ là mình không đọc nó một mình nữa: p99 nằm ngay bên cạnh, và chính con số đó đã không cho mình nói “chắc do mạng của họ”. Bài kế tiếp, bài 04, đi xuống bên dưới: vì sao database nhanh hay chậm, LSM-tree so với B-tree.

Câu hỏi luyện tập

  1. 10.000 request, p99 là 2 giây. Khoảng bao nhiêu request mất hơn 2 giây? (Khoảng 100. Câu này mình trả lời đúng lúc đọc sách.)
  2. Một trang gọi song song 50 lời gọi tới các backend có p99 là 300 ms. Bao nhiêu phần trăm lượt tải trang chậm ít nhất ngần đó? (1 − 0,99^50 ≈ 39,5%.)
  3. Dashboard của bạn hiển thị trung bình các p99 của từng server. Sai ở đâu, bạn sẽ đổi thế nào? (Vô nghĩa; export histogram và gộp chúng.)
  4. Sếp nói “trung bình 150 ms, ổn rồi”. Bạn đáp thế nào? (Xin histogram, p95 và p99; đề xuất SLO như p99 dưới 500 ms.)
Hết bài

Bài viết của Vũ Duy Anh, kỹ sư backend ở Hà Nội. Câu hỏi hay góp ý sửa sai xin gửi qua email.