- vừa được xem lúc

Event Sourcing vs CRUD: Khi 1000 lượt ghi cơ sở dữ liệu không còn quan trọng

0 0 1

Người đăng: Vinh Phạm

Theo Viblo Asia

"Cơ sở dữ liệu của bạn là một sổ cái, không phải một cuốn sổ lưu niệm."

Hầu hết các ứng dụng đều xử lý dữ liệu như một chiếc bảng đen — liên tục xóa và ghi đè. CRUD (Tạo, Đọc, Cập nhật, Xóa) rất đơn giản… cho đến khi:

  • Bạn cần kiểm tra các thay đổi (“Ai đã đặt giá này về $0?”)
  • Bạn muốn phát lại lịch sử (“Hệ thống đã hoạt động ra sao vào thứ Ba tuần trước?”)
  • Bạn vô tình ghi đè dữ liệu mà không thể khôi phục.

Event Sourcing (Lưu vết sự kiện) đảo ngược mô hình truyền thống: thay vì lưu trữ trạng thái hiện tại, bạn lưu trữ các sự kiện đã dẫn đến trạng thái đó.

Nhưng khi nào điều này thực sự quan trọng? Hãy so sánh ngay sau đây.

1. Sự khác biệt cốt lõi

CRUD (Kiểu truyền thống như trong Rails)

# Cập nhật trực tiếp số dư của người dùng
user.update!(balance: 100) # Vấn đề: Lịch sử bị mất
# Số dư trước đó là bao nhiêu? Ai đã thay đổi? Vì lý do gì?

Event Sourcing

# Ghi nhận một sự kiện thay vì cập nhật trực tiếp
event = BalanceAdjusted.new( user_id: user.id, old_balance: user.balance, new_balance: 100, reason: "Điều chỉnh thủ công bởi admin"
)
EventStore.publish(event) # Có thể dựng lại trạng thái bất cứ lúc nào
current_balance = EventStore.for(user.id).sum(&:amount)

Ý tưởng chính:

  • CRUD = “Số dư hiện tại là bao nhiêu?”
  • Event Sourcing = “Tại sao số dư lại là 100?”

2. Khi nào Event Sourcing tỏa sáng?

Trường hợp sử dụng 1: Hệ thống tài chính

  • Yêu cầu: Mỗi xu đều phải được kiểm toán.
  • Rủi ro với CRUD: Một câu lệnh UPDATE sẽ xóa mất lịch sử.
  • Cách giải quyết với Event Sourcing: Sổ cái bất biến lưu lại mọi giao dịch.

Trường hợp sử dụng 2: Tuân thủ pháp lý

  • Yêu cầu: Chứng minh được trạng thái dữ liệu ở bất kỳ thời điểm nào trong quá khứ.
  • Rủi ro với CRUD: Rất khó dựng lại lịch sử.
  • Event Fix: Phát lại sự kiện tới bất kỳ mốc thời gian nào.

Trường hợp sử dụng 3: Quy trình phức tạp

  • Yêu cầu: Hoàn tác/làm lại hành động (ví dụ: hủy đơn hàng).
  • Rủi ro với CRUD: Rollback cần chỉnh sửa thủ công.
  • Cách giải quyết: Đảo ngược các sự kiện để “quay ngược” trạng thái.

3. Khi CRUD vẫn là lựa chọn tốt hơn

Trường hợp sử dụng 1: Ứng dụng đơn giản

  • Ví dụ: Danh sách việc cần làm, hệ quản trị blog.
  • Tại sao không dùng Event? Không cần audit hay phát lại.

Trường hợp sử dụng 2: Ghi dữ liệu tốc độ cao

  • Ví dụ: Phân tích thời gian thực (hàng nghìn lượt ghi/giây).
  • Sự cố với Event: Dựng lại trạng thái gây trễ.

Trường hợp sử dụng 3: Dữ liệu tĩnh

  • Ví dụ: Danh mục sản phẩm (ít khi thay đổi).
  • Tại sao Event lãng phí? Không đáng để theo dõi từng chỉnh sửa nhỏ.

4. Phương pháp kết hợp: Tốt cho cả hai

Mẫu 1: CRUD kèm theo ghi log sự kiện

class User < ApplicationRecord after_update :log_balance_change private def log_balance_change if balance_previously_changed? AuditLog.create!( event: "balance_change", old_value: balance_previous_change[0], new_value: balance ) end end
end

Phù hợp với: Ứng dụng cần audit nhẹ nhàng.

Mẫu 2: Dùng Event Sourcing cho luồng nghiệp vụ quan trọng

  • Ví dụ: Dùng event cho thanh toán, CRUD cho thông tin người dùng.
  • Phù hợp với: Giảm độ phức tạp ở chỗ không cần thiết.

Mẫu 3: CQRS + Event Sourcing

  • Ví dụ: Ghi theo dạng sự kiện, đọc từ các view được dựng sẵn (materialized view).
  • Phù hợp với: Hệ thống quy mô lớn (như thương mại điện tử).

5. Khung ra quyết định

Tự hỏi:

  • Có cần lưu vết audit không? (Có → Dùng Event)
  • Việc phát lại sự kiện có giá trị không? (Có → Dùng Event)
  • Dữ liệu ghi có tần suất cao và giá trị thấp không? (Có → Dùng CRUD)
  • Có thể chấp nhận nhất quán cuối cùng không? (Có → Dùng Event)

Nguyên tắc ngầm định:

Hãy dùng Event Sourcing khi lịch sử là một phần cốt lõi trong nghiệp vụ, chứ không chỉ là một tính năng “cho có”.

“Nhưng ActiveRecord thì quá dễ dùng!”

Đúng vậy — cho đến khi nó không còn dễ nữa.

Bạn không cần phải "chơi lớn" ngay từ đầu:

  • Hãy bắt đầu với một luồng công việc quan trọng (ví dụ: thanh toán).
  • Giữ CRUD cho dữ liệu ít quan trọng (ví dụ: tùy chọn cá nhân).
  • Đo lường sự đánh đổi trước khi mở rộng.

Bạn đã thử kết hợp CRUD và Event Sourcing chưa? Hãy chia sẻ bài học của bạn bên dưới.

Bình luận

Bài viết tương tự

- vừa được xem lúc

Xây dựng ứng dụng web CRUD với Python và Flask - Phần một

Chào các bạn, hôm nay mình sẽ hướng dẫn cách dựng 1 ứng dụng web quản lý nhân viên CRUD (Create, Read, Update, Delete) bằng cách sử dụng Flask, một microframework cho Python. Project sẽ gồm có các tín

0 0 246

- vừa được xem lúc

[Laravel] CRUD với Laravel

Mở đầu. Gần đây mình mới đi thực tập tại công ty và được yêu cầu tìm hiểu Laravel.

0 0 89

- vừa được xem lúc

CRUD với NodeJs, Express và MongoDB

1. Cài đặt môi trường. . B1: Tạo một thư mục dự án.

0 0 78

- vừa được xem lúc

CRUD Là Gì? Lập Trình Website CRUD? CRUD Database?

CRUD là gì? CRUD là viết tắt của 4 từ tiếng Anh: Create, Read, Update, Delete. CRUD là 4 tính năng quan trọng nhất để làm việc với Database của một Website. . 1.

0 0 64

- vừa được xem lúc

Tạo Web CURD đơn giản với Nodejs + Mysql + EJS

Mở đầu. Trong bài viết này mình sẽ tạo web CRUD đơn giản bằng Nodejs sử dụng Mysql , Express, Ejs.

0 0 39

- vừa được xem lúc

Rest API - cách front và back nói chuyện với nhau qua ví dụ cụ thể

Bạn đã từng dành 1 tháng ăn không ngon ngủ không yên vì không thể hiểu API là gì dù đã đọc đi đọc lại khái niệm? Tôi là một trong số đó, và sai lầm của tôi là: tôi không code, tôi chỉ đọc lý thuyết. C

0 0 45