形式陈述 ​
PN-Counter 的状态是一对G-Counter
副本
查询为
内部状态在乘积偏序中始终膨胀;用户读值却可以增加、减少或不变。这正说明 CRDT 的单调性属于信息状态,而非 query 数值。
每个 actor 对
PN-Counter 没有原生 reset。把两向量清零会向下移动并让旧状态复活;若需要 epoch reset,必须为 epoch 建立可合并的排序和成员协议,或创建新对象身份。读值为负在数学模型中完全合法,查询本身无需截断。
直觉
直接把三减成二会遗忘“三曾经包含哪些 increment”,旧快照三再次出现时无法判断它过期。PN-Counter 不删除正历史,而是新增一条负历史;查询时才把二者抵消。网络层看到的仍是两份只会向上的知识。
这与会计账本相似:收入和支出分别累计,余额是差。两个副本可以并发记录不同方向的变化,merge 不需决定哪一笔“最后发生”。同一快照重复传播也只把各账本前缀取最大。
代价是元数据与语义分离。余额为零可能来自从未更新,也可能来自一百次增、一百次减;内部状态不能据 query 相等而压成零,否则迟到副本会造成重复或丢失。两个状态读值相同也未必可替换,例如
例子与边界
设 actor 为 A、B。A 执行三次 increment 和一次 decrement:
B 执行一次 increment 和两次 decrement:
交换状态后分别取最大,得到
所以读值为
若业务规定库存不得小于零,A、B 从一件库存同时各 decrement 一次,合并后读值为
批量 decrement
若实现试图在本地直接执行
推论与应用
PN-Counter 可表达投票净值、资源变化量和增减指标,并保留 G-Counter 对乱序、重复状态的宽容。按批次加减
动态成员和状态压缩仍是主要成本。可以把永久退役 actor 的正负贡献迁移进稳定汇总分量,但迁移必须恰好一次且阻止旧身份重返;否则汇总与迟到原分量会双重计入。
参考资料
- Marc Shapiro et al., “A Comprehensive Study of Convergent and Commutative Replicated Data Types,” INRIA RR-7506, 2011, Specification 7.
- Nuno Preguiça, Carlos Baquero, and Marc Shapiro, “Conflict-Free Replicated Data Types,” Encyclopedia of Big Data Technologies, Springer, 2018, counter entries.
- Paulo Sérgio Almeida, “Approaches to Conflict-Free Replicated Data Types,” ACM Computing Surveys 56(3), Article 76, 2024, Sec. 3.2.