1. CRDT 概念与课程项目结构

CRDT(Conflict-free Replicated Data Type)是一类能够在多副本环境中自动合并更新、无需中心协调的数据结构,其数学基础保证了副本间的最终一致性。本章从核心思想出发,拆解状态与操作两种模型,并完成课程示例项目(G-Counter 计数器)的目录搭建与构建配置。

1.1 CRDT 核心思想

CRDT 的设计目标是「无冲突收敛」:任意两个副本经过同步后,最终状态一致,且合并操作满足交换律、结合律、幂等律。这消除了传统分布式系统中冲突检测与回滚的复杂逻辑。

  • 最终一致性:副本允许临时不一致,但所有合法更新最终会到达所有节点。
  • 无中心协调:任何副本可在离线状态下修改数据,合并时无需全局锁或领导节点。
  • 自动合并:合并结果由数据结构本身的性质决定,不依赖应用程序决策。
性质含义CRDT 如何满足
交换律A ∘ B = B ∘ A合并操作与顺序无关
结合律(A ∘ B) ∘ C = A ∘ (B ∘ C)多副本可任意分组合并
幂等律A ∘ A = A重复传递同一更新不会改变结果

1.2 状态模型与操作模型

CRDT 按同步方式分为两类,课程将同时实现两种模型以对比差异:

  • 基于状态(State-based / CvRDT):每个副本周期性地发送完整状态(或增量状态),接收方执行 merge() 函数。适用带宽富余但网络可能中断的场景。
  • 基于操作(Operation-based / CmRDT):每个副本广播仅本次更新操作,接收方在本地重放。适用低带宽、高频率更新的场景,但需要可靠广播通道。
关键区别:状态模型对网络质量要求低(允许丢包后重传),但状态体积可能较大;操作模型体积小,但要求操作不丢失且不重复传递(需配套因果序机制)。
CRDT 分类与同步模型 CRDT 基于状态 (CvRDT) 基于操作 (CmRDT) 全状态同步 merge() 合并 增量操作广播 本地重放应用 最终状态收敛 (Eventual Consistency) 示例:G-Counter, PN-Counter 示例:LWW-Register, OR-Set

1.3 课程项目目录规划与搭建

课程将实现一个完整的 G-Counter(Grow-Only Counter),支持状态与操作两种同步方式,并附带单元测试与基准测试。项目使用 CMake 构建,目录布局如下:

crdt-course/
├── CMakeLists.txt          # 顶层构建文件
├── README.md               # 课程项目简介与使用说明
├── .gitignore
├── src/
│   ├── gcounter_state.h    # 基于状态的 G-Counter 声明
│   ├── gcounter_state.cpp  # 实现
│   ├── gcounter_op.h       # 基于操作的 G-Counter 声明
│   ├── gcounter_op.cpp     # 实现
│   └── main.cpp            # 演示与基准入口
├── tests/
│   ├── CMakeLists.txt
│   ├── test_state.cpp     # 状态模型单元测试
│   └── test_op.cpp        # 操作模型单元测试
└── benchmarks/
    ├── CMakeLists.txt
    └── bench_sync.cpp     # 同步性能基准

1.4 构建配置与首次编译

项目依赖 C++17 及符合 OpenMP 标准的编译器(用于性能测试)。顶层 CMakeLists.txt 核心配置:

cmake_minimum_required(VERSION 3.18)
project(crdt-course LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_executable(crdt_demo src/main.cpp src/gcounter_state.cpp src/gcounter_op.cpp)

find_package(OpenMP)
if(OpenMP_CXX_FOUND)
  target_link_libraries(crdt_demo PRIVATE OpenMP::OpenMP_CXX)
endif()

enable_testing()
add_subdirectory(tests)
add_subdirectory(benchmarks)
快速开始:在项目根目录执行以下命令即可编译并运行演示程序:
mkdir build && cd build
cmake .. && cmake --build .
./crdt_demo

1.5 常见错误与调试指引

问题原因解决方案
未找到 OpenMP编译器未启用 OpenMP 或缺少库安装 libomp-dev(Linux)或启用 MSVC 的 OpenMP 支持
merge() 结果不符合预期未正确实现偏序 lattice 操作确认 max() 或 join 函数对所有副本向量逐元素处理
操作丢失导致状态不一致重放操作未按因果序交付添加版本向量(Version Vector)追踪依赖关系
注意:本章建立的目录结构是整个课程的基础。后续所有章节(GCounter → PN-Counter → LWW-Register → OR-Set → 分布式同步层)都会在此骨架中添加文件。请确保 CMake 版本 ≥ 3.18,否则无法使用 add_subdirectory 和 enable_testing 的正确行为。