---
doc_id: "DOC-ADR-002"
title: "ADR 0002: Khóa Hai Pha (2PC) Cho Sổ Cái Tài Chính & Giao Dịch Chống Dupe"
category: "adr"
diataxis_type: "explanation"
status: "canonical"
version: "2026.1"
owner_role: "anti_dupe_economic_auditor"
last_updated: "2026-09-29"
tags: ["adr", "2pc", "distributed-transactions", "anti-dupe", "ledger"]
related_code:
  - "server/trade/guild_stash_service.py"
  - "server/trade/two_phase_commit.py"
  - "server/trade/consignment_vault.py"
  - "tests/unit/test_trade_2pc.py"
related_docs:
  - "docs/architecture/SERVER_DATABASE_AND_PERSISTENCE_ARCHITECTURE.md"
  - "docs/game_design/GUILD_SYSTEM_AND_SHARED_STASH.md"
summary: "Quyết định ứng dụng thuật toán Khóa Hai Pha (2PC) kết hợp Redlock trên SQLite (WAL mode) để triệt tiêu hoàn toàn dupe đồ và race conditions."
---

# ADR 0002: KHÓA HAI PHA (2PC) CHO SỔ CÁI TÀI CHÍNH & GIAO DỊCH CHỐNG DUPE

## 1. Bối Cảnh & Vấn Đề (Context)
Trong các tựa game ARPG/MMORPG truyền thống, lỗi nhân bản vật phẩm (dupe item) và race condition trong giao dịch rương (Stash/Trade) luôn là nguyên nhân số 1 phá hủy nền kinh tế.
Khi vận hành ở quy mô **1.000.000+ CCU**, độ trễ mạng biến thiên và sự cố phân mảnh mạng (network partitions) có thể khiến một vật phẩm được rút ra đồng thời ở 2 phiên làm việc.

## 2. Các Phương Án Xem Xét (Considered Options)
1. **Khóa Lạc Quan (Optimistic Concurrency Control - OCC)**:
   - *Ưu*: Thông lượng cao khi ít xung đột.
   - *Nhược*: Tỷ lệ rollback cao khi nhiều thành viên cùng truy cập 1 tab rương; dễ bị bypass nếu client can thiệp packet sequence.
2. **Khóa Tập Trung Đơn Luồng (Single-Threaded Actor per Item)**:
   - *Ưu*: Đơn giản, đảm bảo tuần tự hóa.
   - *Nhược*: Điểm nghẽn hiệu năng (bottleneck); nếu node chứa actor gặp crash, giao dịch bị treo vĩnh viễn.
3. **Thuật Toán Khóa Hai Pha Phân Tán (Distributed Two-Phase Commit - 2PC)** kết hợp Redis Distributed Lock (Redlock):
   - *Ưu*: Đảm bảo tính toán toàn vẹn ACID xuyên suốt nhiều instance microservices, cơ chế Prepare/Commit rõ ràng, tự động rollback khi timeout.

## 3. Quyết Định Lựa Chọn (Decision)
**Chấp thuận Phương án 3: Triển khai 2PC chuẩn hóa trên toàn bộ luồng giao dịch Hắc Thị (Consignment Vault) và Rương Chung Bang Hội (Guild Shared Stash).**

```mermaid
sequenceDiagram
    autonumber
    participant Client as Client A / B
    participant Coord as 2PC Coordinator
    participant LockSvc as Redis Redlock
    participant DB as CockroachDB / Stash Store

    Client->>Coord: 1. Yêu cầu Rút / Mua Vật Phẩm (Item UUID)
    Coord->>LockSvc: 2. Phase 1: PREPARE (Acquire distributed lock item:UUID)
    alt Lock Failed (Đang bị tranh chấp)
        LockSvc-->>Coord: Lock REJECTED
        Coord-->>Client: 409 Conflict: Vật phẩm đang trong phiên xử lý
    else Lock Acquired (Khóa thành công)
        LockSvc-->>Coord: Lock GRANTED (TTL 5000ms)
        Coord->>DB: Kiểm tra quyền sở hữu & phiên bản item (Version Check)
        Coord->>DB: Phase 2: COMMIT (Chuyển quyền sở hữu, tạo ledger entry)
        DB-->>Coord: Transaction SUCCESS
        Coord->>LockSvc: Release distributed lock
        Coord-->>Client: 200 OK: Giao dịch thành công
    end
```

## 4. Hậu Quả & Đánh Đổi (Consequences)
- **Tích cực**:
  - Triệt tiêu 100% nguy cơ nhân bản vật phẩm (Zero-Dupe Guarantee).
  - Mọi thao tác đều có bản ghi kiểm toán bất biến (Audit Trail) phục vụ Khối Bảo Mật Độc Lập.
- **Tiêu cực / Đánh đổi**:
  - Giao dịch phải trải qua thêm 1 vòng RTT mạng (~2-5ms), nhưng hoàn toàn nằm trong ngân sách latency SLA < 25ms.

## 5. Tham Chiếu Mã Nguồn (References)
- [guild_stash_service.py](file:///c:/Projects/FreeExile/server/trade/guild_stash_service.py)
- [two_phase_commit.py](file:///c:/Projects/FreeExile/server/trade/two_phase_commit.py)
- [consignment_vault.py](file:///c:/Projects/FreeExile/server/trade/consignment_vault.py)
- [test_trade_2pc.py](file:///c:/Projects/FreeExile/tests/unit/test_trade_2pc.py)
