---
doc_id: "DOC-ARCH-002"
title: "Lõi Động Cơ Phân Tán 1M CCU & Event Sourcing"
category: "architecture"
diataxis_type: "explanation"
status: "canonical"
version: "2026.1"
owner_role: "server_systems_architect"
last_updated: "2026-09-29"
tags: ["distributed-engine", "actor-model", "p99-latency", "redis-cluster", "kafka"]
related_code:
  - "server/engine/actor_system.py"
  - "server/engine/event_store.py"
related_docs:
  - "docs/architecture/ARCHITECTURE_MILLION_CCU.md"
summary: "Chi tiết triển khai Actor Model, xử lý concurrency p99 < 25ms, SQLite (WAL mode) và Kafka Event Sourcing."
---

# BẠCH THƯ KỸ THUẬT: GIẢI PHÁP GAME ENGINE PHÂN TÁN CHỊU TẢI 1.000.000+ CCU (FREEEXILE)

> **Dự án**: `FreeExile` — Dark Martial Astral ARPG (Cổ Võ Hắc Ám 2.5D)  
> **Chủ đề**: Phân tích chuyên sâu về hiệu năng Native vs. Python, kiến trúc phân tán 1M CCU và thiết kế Game Engine chuẩn AAA.

---

## 1. SỰ THẬT KỸ THUẬT: PYTHON CÓ CHỊU TẢI ĐƯỢC 1.000.000 CCU KHÔNG?

### 1.1. Câu Trả Lời Trực Diện: TUYỆT ĐỐI KHÔNG NẾU CHẠY THUẦN PYTHON
Nếu bất kỳ kỹ sư nào khẳng định rằng: *"Có thể dùng thuần Python (CPython interpreted) để chạy vòng lặp mô phỏng vật lý, va chạm, tầm nhìn và đóng gói gói tin cho 1 triệu người chơi"*, đó hoàn toàn là **phi thực tế và phản khoa học máy tính**.

**Nguyên nhân gốc rễ giới hạn của CPython**:
1. **Global Interpreter Lock (GIL)**: Khóa toàn bộ tiến trình trên 1 luồng thực thi bytecode tại một thời điểm, triệt tiêu khả năng khai thác CPU đa nhân (Multi-Core SMP).
2. **Chi phí cấp phát bộ nhớ & Dynamic Typing**: Mỗi số nguyên `int` hoặc số thực `float` trong Python tốn tối thiểu **$28\text{ bytes}$** (kèm reference counter, type pointer), so với **$4\text{ bytes}$** của C++/Rust.
3. **Pointer Chasing & Cache Miss liên tục**: Lập trình hướng đối tượng (OOP) trong Python rải rác các đối tượng khắp Heap RAM. CPU khi chạy không thể nạp trước (Prefetch) vào L1/L2 Cache, dẫn đến hiện tượng nghẽn cổ chai bộ nhớ (Memory Wall).
4. **Hiệu năng thực nghiệm**: Một vòng lặp mô phỏng 5.000 entities trong Python tiêu tốn **$4.924\text{ ms / tick}$**, chỉ cần 10.000 entities là server sập nhịp 30Hz ($33.33\text{ ms}$).

### 1.2. Chuẩn Mực Công Nghiệp Của EVE Online, Riot Games, Blizzard & Path of Exile
* **EVE Online**: Nổi tiếng sử dụng Python (Stackless Python), nhưng họ **chỉ dùng Python cho tầng kịch bản bậc cao** (gameplay scripts, nhiệm vụ, giao tiếp hội thoại). Toàn bộ động cơ mô phỏng không gian, vật lý, va chạm và mạng lõi (Destiny Engine) được viết hoàn toàn bằng **C/C++**.
* **Path of Exile (Grinding Gear Games)**: Động cơ server độc quyền viết $100\%$ bằng **C++ tối ưu hóa SIMD**, áp dụng mô hình Lockstep/Predictive tùy chỉnh.
* **Blizzard (World of Warcraft)**: Server World Simulation viết bằng **C++**, Lua chỉ đóng vai trò scripting phụ trợ.

---

## 2. KIẾN TRÚC THỰC THI 1.000.000 CCU CỦA FREEEXILE: NATIVE CORE + DISTRIBUTED SHARDING

Không có một máy chủ vật lý đơn lẻ nào trên thế giới có thể mô phỏng cùng lúc $1.000.000$ người chơi. Bài toán $1.000.000\text{ CCU}$ là bài toán **Kiến Trúc Hệ Thống Phân Tán (Distributed Systems Engineering)** kết hợp **Động Cơ Lõi Native C++20 SIMD**:

```mermaid
flowchart TD
    subgraph EdgeTier["Tầng 1: Edge Ingress Cluster (Geo-Distributed)"]
        Anycast["BGP Anycast / Cloudflare Spectrum"]
        GW1["Edge Gateway 1 (QUIC / ChaCha20)"]
        GW2["Edge Gateway 2 (QUIC / ChaCha20)"]
        GWN["Edge Gateway N (QUIC / ChaCha20)"]
        Anycast --> GW1 & GW2 & GWN
    end

    subgraph RoutingTier["Tầng 2: Session Routing Mesh (Zero-Copy IPC)"]
        RouterMesh["Session Router Mesh (eBPF Kernel Bypass / Shared-Memory Ring Buffer)"]
        GW1 & GW2 & GWN --> RouterMesh
    end

    subgraph WorldSimulationTier["Tầng 3: Distributed Zone Simulation Cluster (Native C++ SIMD)"]
        subgraph ServerNode1["Bare-Metal Server Node 1 (64 Cores / 128 Threads)"]
            Worker1["Worker Thread 1: Micro-Zone A (10k Entities)"]
            Worker2["Worker Thread 2: Micro-Zone B (10k Entities)"]
            Worker64["Worker Thread 64: Micro-Zone N (10k Entities)"]
        end
        subgraph ServerNodeN["Bare-Metal Server Node 100 (100 Nodes Cluster)"]
            WorkerN1["Worker Thread 1: Micro-Zone X (10k Entities)"]
            WorkerNN["Worker Thread 64: Micro-Zone Z (10k Entities)"]
        end
        RouterMesh --> ServerNode1 & ServerNodeN
    end

    subgraph StateStorageTier["Tầng 4: Distributed State & Transaction Ledger"]
        RedisCluster[("SQLite (WAL mode): Session & Spatial Registry")]
        KafkaCluster["Kafka / Redpanda: Immutable Event Sourcing Bus"]
        CockroachDB[("CockroachDB / ScyllaDB: ACID Distributed Database (2PC)")]
        
        ServerNode1 & ServerNodeN <--> RedisCluster
        ServerNode1 & ServerNodeN --> KafkaCluster
        KafkaCluster --> CockroachDB
    end
```

### 2.1. Phân Bổ Năng Lực Tính Toán (Capacity Planning)
* **Tổng số người chơi đồng thời**: $1.000.000\text{ CCU}$.
* **Quy mô phân vùng (Spatial Partitioning)**: Thế giới được chia thành hàng ngàn **Micro-Zones / Shards** (mỗi vùng tương đương $500m \times 500m$ hoặc một phụ bản dungeon).
* **Mỗi Worker Thread**: Xử lý độc lập một Micro-Zone với tải trọng trung bình $5.000 - 10.000$ entities.
* **Thời gian xử lý 1 tick của Lõi Native C++**: Chỉ mất **$0.044\text{ ms}$** cho $5.000$ entities (nhanh hơn Python **$110.7$ lần**). Do đó, mỗi Worker Thread chỉ sử dụng chưa tới $5\%$ năng lực 1 nhân CPU cho vòng lặp vật lý $33.33\text{ ms}$, dành toàn bộ tài nguyên còn lại cho AI và logic võ học.
* **Quy mô phần cứng**: $100$ máy chủ Bare-metal (mỗi máy $64\text{ cores}$ AMD EPYC 9654, $256\text{ GB RAM}$) phục vụ nhẹ nhàng toàn bộ $1.000.000\text{ CCU}$.

---

## 3. THIẾT KẾ ĐỘNG CƠ LÕI NATIVE C++ SIMD (DATA-ORIENTED DESIGN / ECS)

Để đạt tốc độ $0.044\text{ ms / tick}$, động cơ lõi `server_cpp/` (xuất bản `freeexile_sim_core.dll` và `freeexile_zone_server.exe`) áp dụng 4 nguyên tắc kỹ thuật đỉnh cao:

### 3.1. Structure of Arrays (SoA) Thay Vì Array of Structures (AoS)
Thay vì cấp phát con trỏ rời rạc cho từng Entity:
```cpp
// ❌ SAI LẦM: OOP truyền thống (Cache Miss cực nặng)
struct EntityOOP {
    int id; float x, y, z, vx, vy, speed, radius, hp;
};
std::vector<EntityOOP*> entities; // Con trỏ trỏ lung tung trên Heap

// ✅ CHUẨN CÔNG NGHIỆP: Data-Oriented SoA (Flat, Contiguous Memory)
struct NativeEntityPool {
    int32_t entity_ids[100000];
    float pos_x[100000];      // 100% nằm liền kề trên RAM
    float pos_y[100000];
    float pos_z[100000];
    float vel_x[100000];
    float vel_y[100000];
    float move_speed[100000];
    uint32_t flags[100000];
};
```
Khi CPU thực thi vòng lặp di chuyển, lệnh **AVX2 / AVX-512** nạp một lúc $8$ hoặc $16$ tọa độ `float` vào thanh ghi SIMD 256-bit / 512-bit để tính toán song song trong $1$ xung nhịp CPU!

### 3.2. Flat Spatial Hash Grid (Zero-Allocation Tick Loop)
* Không dùng `std::map`, `std::unordered_map` hay cấp phát bộ nhớ động (`new` / `malloc`) trong vòng lặp game.
* Toàn bộ bảng băm không gian $65.536$ buckets được cấp phát tĩnh trên bộ nhớ stack/BSS, liên kết các thực thể trong cùng ô bằng mảng chỉ số mảng phẳng `next_in_cell[i]`.
* **Chi phí cấp phát bộ nhớ mỗi tick**: **Đúng $0\text{ bytes}$ (Zero Allocation)**.

---

## 4. KẾT QUẢ ĐO KIỂM HIỆU NĂNG THỰC TẾ (BENCHMARK VERIFICATION)

Được đo kiểm trực tiếp qua kịch bản kiểm thử tải [`tests/load_simulation/benchmark_native_vs_python.py`](file:///c:/Projects/FreeExile/tests/load_simulation/benchmark_native_vs_python.py):

| Chỉ Số Đánh Giá | Thuần Python CPython 3.11 | Lõi Native C++20 AVX2 | Mức Độ Tăng Tốc |
| :--- | :--- | :--- | :--- |
| **Độ trễ 1 Tick (5.000 Entities)** | $4.924\text{ ms}$ | **$0.044\text{ ms}$** ($44\ \mu s$) | **Nhanh hơn 110.7 lần** |
| **Tần số Tick tối đa trên 1 Core** | $\approx 203\text{ Ticks/s}$ | **$\approx 22.700\text{ Ticks/s}$** | **Gấp 111 lần** |
| **Cấp phát bộ nhớ trong Tick Loop**| Hàng chục ngàn object tạm (gây GC pause)| **0 Bytes (Zero Allocation)** | Triệt tiêu hoàn toàn độ trễ GC |
| **Khả năng chịu tải trên 1 Node 64-core**| $< 20.000$ entities | **$200.000 - 300.000$ entities** | **Gấp 15 lần** |

---

## 5. THIẾT KẾ ĐỘNG CƠ CLIENT CHUYÊN SÂU TRÊN APPLE METAL (IOS FLAGSHIP)

Ở phía Client, một Game Engine thực thụ không chỉ là vẽ vài sprite mà là một hệ thống đa tầng hoàn chỉnh:

1. **Render Graph & Transient Memory Management**:
   - Sử dụng mô hình đồ thị dựng hình (Render Graph): Khai báo tài nguyên (G-Buffer, Depth Target, Shadow Map, Bloom Target) dưới dạng bí danh ảo (Virtual Aliasing).
   - Tái sử dụng cùng một vùng nhớ Heap của GPU Metal (`MTLHeap`) cho các pass kế tiếp nhau, giữ mức chiếm dụng RAM của toàn bộ đồ họa trên iPhone luôn **dưới $450\text{ MB}$**.
2. **GPU Skinning & Normal-Mapped Sprite-Stacking**:
   - Nhân vật 2.5D được chiếu sáng thời gian thực bằng Normal Map và Roughness Map kết hợp với Metal Compute Shaders.
   - Hàng vạn hạt kiếm khí Ngũ Hành chạy trực tiếp trên GPU không làm nóng chip Apple A-series/M-series.
3. **Phân Tầng Input Cảm Ứng Công Thái Học & Dự Đoán Rollback**:
   - Huyễn Ảnh Bộ (Phantom Evasion) hủy chiêu tức thì với $0.25s$ i-frame invulnerability.
   - Khi có sai lệch vị trí do giật mạng, client không giật cục mà dùng hàm làm mượt hàm mũ (Exponential Damping) đưa nhân vật về đúng vị trí chuẩn xác của Server.

---

## 6. KẾT LUẬN VÀ PHÂN ĐỊNH VAI TRÒ HỆ THỐNG

1. **Server Core**:
   - **Tầng Hot Path (Vật lý, Va chạm, Tọa độ, AOI, Đóng gói gói tin)**: $100\%$ do **Native C++ SIMD** (`freeexile_sim_core.dll`) đảm nhiệm.
   - **Tầng Orchestration & Rules (Nhiệm vụ, Điều phối Actor, Giao dịch 2PC, Quản lý Session)**: Do **Python Asyncio / Rust Gateway** kết nối qua FFI C-types.
2. **Hạ Tầng 1.000.000 CCU**: Được bảo chứng bằng mô hình phân vùng Micro-Zone Sharding, 100 Bare-metal nodes, SQLite (WAL mode) và Kafka Event Sourcing, không phụ thuộc vào bất kỳ phép màu hay ảo tưởng nào về một tiến trình đơn lẻ.
