English· Español· Deutsch· Nederlands· Français· 日本語· ქართული· 繁體中文· 简体中文· Português· Русский· العربية· हिन्दी· Italiano· 한국어· Polski· Svenska· Türkçe· Українська· Tiếng Việt· Bahasa Indonesia

un

khách
1 / ?
trở lại bài học

Dạng 1: Sửa Chữa Trạng Thái. Dạng 2: Báo Cáo Lãng Phí.

Một Trái Tim Đo Lường đập theo đồng hồ. Không theo nhu cầu. Không theo thay đổi. Theo một bộ hẹn giờ.

Hai dạng, một nguyên nhân gốc rễ: một công việc định kỳ thay thế cho thiết kế đúng.

Dạng 1: Sửa Chữa Trạng Thái

Một chuyển đổi trạng thái không hoàn thành nguyên tử. Thay vì sửa chuyển đổi, một công việc nền chạy theo độ trễ & điều hòa. Người dùng thấy trạng thái bị hỏng trong cửa sổ điều hòa.

Ví dụ GitHub (2026-04-08): Một pull request có kho lưu trữ upstream trở thành private. GitHub đã cố gắng thực hiện chuyển đổi trạng thái: đóng PR, cập nhật trạng thái nhánh, xóa trạng thái merge. Việc chuyển đổi không hoàn thành một cách nguyên tử. Trạng thái PR hiển thị đồng thời 'branch-forced-closed' & 'Merge status cannot be loaded'. Một Sidekiq background job chạy vài phút sau và hoàn thành việc điều hòa. Người quan sát thấy trạng thái bị hỏng trong suốt khoảng thời gian đó.

The Metered Heart: Sidekiq job chạy theo lịch trình. Nó không chạy vì GitHub phát hiện trạng thái bị hỏng; nó chạy vì bộ đếm thời gian đã kích hoạt. Một người dùng theo dõi PR theo thời gian thực thấy một PR mâu thuẫn với chính nó cho đến khi job thực thi lần tiếp theo.

Form 2: Báo cáo lãng phí

Một báo cáo hoặc tổng hợp được tính toán lại từ đầu theo một khoảng thời gian cố định. Không kiểm tra cache. Không có guard idempotency. Không cập nhật tăng dần. Mỗi lần thực thi: một lần quét đầy đủ.

Ví dụ: một cron job chạy hàng đêm tính toán lại tổng số tiền mua hàng của mỗi người dùng bằng cách quét tất cả đơn hàng từ đầu. Một job phân tích hàng ngày tạo lại bảng điều khiển từ nhật ký sự kiện thô. Một email tóm tắt hàng tuần truy vấn mọi dòng trong bảng hoạt động.

Mỗi job chạy bất kể dữ liệu có thay đổi hay không kể từ lần thực thi trước. Mỗi job quét toàn bộ lịch sử ngay cả khi chỉ 24 giờ qua chứa dữ liệu mới. Mỗi job thay thế việc lặp lại theo lịch trình bằng thiết kế tăng dần.

Nguồn gốc chung

A Metered Heart không thể nói sự thật về trạng thái của chính nó. Nó chỉ biết đồng hồ. Form 1: job sửa chữa trạng thái chạy tại T+5 phút bất kể trạng thái có bị hỏng tại T+0 hay không. Form 2: job báo cáo chạy lúc 2 AM bất kể dữ liệu có thay đổi hay không kể từ hôm qua.

Đồng hồ không mang thông tin về việc cần làm. Một sự kiện mới mang thông tin đó: 'một trạng thái chuyển đổi vừa thất bại,' 'đơn hàng mới vừa đến.' Một Trái Tim Đo Lường loại bỏ thông tin đó và thay thế bằng một lịch trình.

Sự Hao Mòn Vốn

Một Trái Tim Đo Lường làm hao mòn vốn sống: các kỹ sư phải trực để xử lý các sự cố trạng thái hỏng. Làm xói mòn niềm tin xã hội: người dùng thấy dữ liệu không nhất quán và báo cáo lỗi rồi tự khắc phục. Khuếch đại các MOAD khác: một công việc sửa trạng thái quét toàn bộ bản ghi để tìm trạng thái hỏng thường chứa MOAD-0001 (quét O(N²)). Một công việc báo cáo tính toán lại dữ liệu lạnh có thể kích hoạt MOAD-0005 (cache stampede). MOAD-0009 làm trầm trọng thêm các lỗi khác.

Nguồn Gốc Chung

Form 1 & Form 2 trông khác nhau bề ngoài: một cái sửa trạng thái, một cái tính toán lại dữ liệu. Nguyên nhân gốc rễ kết nối chúng.

Form 1 và Form 2 chia sẻ một nguyên nhân gốc rễ. Mô tả nó trong một câu. Sau đó đưa ra một ví dụ cho mỗi form từ phần mềm bạn đã sử dụng.

Fire on Change, Not on Clock

Thiết kế hướng sự kiện kích hoạt khi có gì đó thay đổi. Sự thay đổi trạng thái chính là sự kiện. Sự kiện là yếu tố kích hoạt.

Form 1: chuyển đổi nguyên tử thay thế công việc sửa chữa.

Nếu một chuyển đổi trạng thái có thể để lại hệ thống ở trạng thái trung gian bị hỏng, thì lỗi nằm ở chính chuyển đổi đó, chứ không phải vì thiếu công việc sửa chữa. Hãy sửa chuyển đổi để nó hoàn tất một cách nguyên tử (hoặc giao dịch). Khi chuyển đổi hoàn tất nguyên tử, trạng thái hỏng không bao giờ tồn tại. Công việc sửa chữa không còn gì để sửa.

# DEFECT: non-atomic transition leaves broken state
def close_pr_on_repo_private(pr_id):
pr = PR.get(pr_id)
pr.status = 'branch-forced-closed'   # bước 1: trạng thái một phần
pr.save()                             # hiển thị ngay cho người dùng
# ... các bước khác có thể thất bại ...
pr.merge_status = 'not_applicable'
pr.save()                             # bước 2: giờ đã nhất quán
# Sidekiq job sẽ điều hòa nếu bước 2 thất bại
# SỬA: chuyển đổi nguyên tử; không có trạng thái trung gian nào hiển thị
def close_pr_on_repo_private(pr_id):
with db.transaction():
pr = PR.get(pr_id)
pr.status = 'branch-forced-closed'
pr.merge_status = 'not_applicable'
pr.save()   # cả hai trường được commit nguyên tử; không bao giờ ghi một nửa

Dạng 2: cập nhật tăng dần thay thế việc tính toán lại toàn bộ.

Một báo cáo tính toán lại từ đầu được kích hoạt vì dữ liệu cũ + dữ liệu mới = kết quả mới. Nhưng kết quả cũ + delta = cùng kết quả mới, được tính toán theo cách tăng dần. Sự kiện: dữ liệu mới đến. Kích hoạt: cập nhật tổng hợp chỉ cho dữ liệu mới.

# LỖI: tính toán lại toàn bộ theo lịch
def nightly_totals_job():
for user in all_users():
total = sum(o.amount for o in user.orders)  # quét toàn bộ thời gian
user.total_purchases = total
user.save()

# SỬA: cập nhật tăng dần theo sự kiện
def on_order_placed(order):
order.user.total_purchases += order.amount   # chỉ thay đổi delta
order.user.save()

Cập nhật tăng dần được kích hoạt khi có đơn hàng mới đến, không phải lúc 2 giờ sáng. Nó chỉ cập nhật người dùng bị ảnh hưởng. Nó chỉ đọc đơn hàng mới, không phải tất cả đơn hàng từ trước đến nay. Công việc chạy vào ban đêm biến mất.

Tại sao Form 1 tiết lộ một chuyển đổi bị hỏng

Một Form 1 Metered Heart cho thấy một chuyển đổi trạng thái đã bị bỏ dở. Công việc sửa chữa tồn tại vì một kỹ sư nhận thấy trạng thái bị hỏng và đã thêm cơ chế điều hòa thay vì sửa đổi chuyển đổi. Công việc sửa chữa: một bản vá cho một quyết định kiến trúc bị hỏng.

MOAD-0009 như một yếu tố khuếch đại

MOAD-0009 khuếch đại các MOAD khác. Một công việc sửa chữa trạng thái quét tất cả bản ghi để tìm trạng thái bị hỏng: MOAD-0001 (quét O(N) hoặc O(N²) mỗi lần chạy công việc). Một công việc báo cáo tính toán lại mọi thứ từ đầu: MOAD-0005 (đám đông bộ nhớ đệm khi công việc bắt đầu và chạm vào nguồn dữ liệu upstream đang nóng). MOAD-0009 không chỉ gây hại riêng lẻ; nó mang theo các MOAD khác theo lịch trình.

Chẩn đoán & Thiết kế lại

Một nhóm chạy một công việc cron hàng đêm lúc 2 giờ sáng. Công việc quét tất cả đơn hàng của mọi người dùng và tính toán lại tổng số tiền mua hàng của từng người dùng từ đầu. Công việc mất 4 giờ. Đến 6 giờ sáng, bảng điều khiển hiển thị tổng số mới. Từ 2 giờ sáng đến 6 giờ sáng, bảng điều khiển hiển thị tổng số của ngày hôm trước.

Đây là dạng nào của MOAD-0009? Sự kiện nào nên kích hoạt việc tính toán lại? Cấu trúc dữ liệu trung gian nào giúp cập nhật trở nên tăng dần?