user_wallets SET balance = balance + X thông thường. Thay vào đó, hệ thống xây dựng trên nền tảng Sổ Cái Kế Toán Đúp (Double-Entry Bookkeeping) kết hợp với Event Sourcing.1. Nguyên Tắc Kế Toán Đúp (Double-Entry Ledger)Mọi biến
TK88 động tài sản trong TK88 đều được hạch toán dưới dạng một cặp bút toán đối ứng: Ghi Nợ (Debit) và Ghi Có (Credit). Tổng giá trị Ghi Nợ bắt buộc phải luôn bằng tổng giá trị Ghi Có trong cùng một giao dịch:$$\sum \text{Debit} = \sum \text{Credit}$$Ví dụ luồng Đặt cược 500,000 VNĐ:Tài khoản Ví Người dùng: Ghi Nợ (Debit) $500,000\text{ VNĐ}$ (Giảm số dư tài sản khả dụng).Tài khoản Ví Tạm giữ (Escrow Wallet): Ghi Có (Credit) $500,000\text{ VNĐ}$ (Tăng tài sản đảm bảo của phiên cược). [ Ví Người Dùng ] ─── (Debit 500k) ───┐
▼
[ Transaction Engine ]
│
[ Ví Tạm Giữ Escrow ] ◄── (Credit 500k) ┘
2. Nhật Ký Bất Biến & Chuỗi Mã Hóa (Cryptographic Hash Chain)Nhật ký chỉ thêm (Append-Only Log): Bảng dữ liệu sổ cái (ledger_entries) được cấu hình vô hiệu hóa lệnh UPDATE và DELETE. Mọi thao tác điều chỉnh số dư đều phải thông qua giao dịch đảo (Reversal Entry) để bảo toàn nguyên vẹn lịch sử.Xác thực dữ liệu bằng Chuỗi Mã Hóa (Hash Chain): Nhằm ngăn chặn hành vi can thiệp trực tiếp vào Database từ bên trong (Insider Threat) hoặc do Hacker, mỗi dòng bản ghi sổ cái lưu trữ một mã Hash $H_n$:$$H_n = \text{HMAC-SHA256}(\text{TransactionData}_n + H_{n-1}, \text{SecretKey})$$Trong đó $H_{n-1}$ là mã Hash của bản ghi kế trước. Khi có bất kỳ sự chỉnh sửa dữ liệu trái phép nào ở quá khứ, chuỗi Hash Chain toàn bộ sổ cái sẽ đứt gãy ngay lập tức, kích hoạt cảnh báo an ninh P1.Phần 2: Kiểm Soát Giao Dịch Đồng Thời & Cơ Chế Anti-Race ConditionKhi hàng ngàn Yêu cầu (Requests) nạp/rút tiền hoặc đặt cược cùng tác động vào số dư của một tài khoản trong cùng một khoảng thời gian cực ngắn, việc đảm bảo tính toàn vẹn (ACID) đòi hỏi sự kết hợp kiểm soát đa tầng.1. Khóa Phân Tán (Distributed Lock) & Pessimistic Row LockingLớp 1 — Redlock (Redis Cluster): Trước khi đi vào luồng xử lý ví, Wallet Service bắt buộc phải lấy thành công Distributed Lock trên cụm Redis theo cấu trúc lock:wallet:{user_id} với thời gian giữ khóa siêu ngắn (Short-lived TTL).Lớp 2 — Lock Cấp Độ Dòng Trong Database: Khi thực thi giao dịch trong CSDL (PostgreSQL / CockroachDB), hệ thống kích hoạt Pessimistic Locking:SQLSELECT balance, frozen_balance
FROM user_wallets
WHERE user_id = 'TK_889922'
FOR UPDATE;
Thao tác FOR UPDATE ép buộc các Transaction đến sau phải xếp hàng chờ (Queueing) cho đến khi Transaction trước thực hiện COMMIT hoặc ROLLBACK.2. Chuẩn Xử Lý Bất Biến (Idempotency Key Pattern)Để ngăn hiện tượng giao dịch bị lặp do người dùng bấm nút nhiều lần, hoặc do cơ chế Retry tự động của Client khi mạng chờ chập chờn:Client ──[ POST /api/v1/wallet/withdraw (X-Idempotency-Key: UUID-XYZ) ]──► API Gateway
│
┌───────────────────────────────────────────────────────────────────┘
▼
[ Redis Idempotency Cache ]
├── Key chưa tồn tại ──► Ghi nhận Key ──► Thực thi trừ tiền ──► Lưu cached result.
└── Key đã tồn tại ──► Trả về kết quả cũ ngay lập tức (Bỏ qua logic trừ tiền).
Mọi yêu cầu liên quan đến tài chính bắt buộc kèm theo Header X-Idempotency-Key (chuỗi UUIDv4 duy nhất cho mỗi thao tác).Nếu Request trùng Key gửi lên trong khung thời gian hiệu lực, API Gateway lập tức trả về kết quả đã xử lý trước đó mà không chuyển tiếp luồng xử lý xuống Wallet Engine.Phần 3: Hệ Thống Đối Soát & Chống Thất Thoát Số Dư (Reconciliation Engine)Bên cạnh các cơ chế khóa thời gian thực, TK88 vận hành hệ thống đối soát chạy ngầm nhằm phát hiện sớm mọi dấu hiệu lệch dòng tiền.1. Phân Tích Luồng Dữ Liệu Thời Gian Thực (Stream-based Real-time Reconciliation)Change Data Capture (CDC): Mọi sự thay đổi trên bảng Sổ cái được Debezium bắt giữ trực tiếp từ Database WAL (Write-Ahead Log) và phát sự kiện vào Kafka topic wallet-ledger-stream.Xử lý luồng bằng Apache Flink: Flink liên tục tính toán tổng lượng tiền vào/ra trên sổ cái trong các cửa sổ thời gian (Sliding Windows) và so sánh trực tiếp với giá trị số dư thực tế (calculated_balance vs current_balance).Auto-Freeze Protocol: Nếu phát hiện chênh lệch bất kỳ dù chỉ $1\text{ VNĐ}$, Flink lập tức kích hoạt trạng thái tạm khóa ví (status = SUSPENDED) và thông báo tới đội ngũ kiểm soát rủi ro.