一条评论引发的考据:kahunakv/kahuna 深度剖析
上周那篇《DrasiWake 更新:用 DotNext.AspNetCore.Cluster 给桥接上 Raft 集群》底下,有条评论挺扎眼:
@sunyuliang:.NET 做 Raft 协议的太少了,Java/Go 好多这种成熟的组件。
我回了一句:Raft 组件还是不少的,NuGet 上有 71 个相关包。
两个人说的其实不冲突,但都没说透。正好这几天我把 kahunakv/kahuna 这个仓库从头到尾翻了一遍,今天拿它当样本,聊聊这件事。
先说清楚:Kahuna 是什么
很多人看名字会以为它是个 Raft 库------不是。
Kahuna 是一个开箱即用的分布式协调服务:分布式锁、强一致 KV、幂等序列号三件套,蹲的是 etcd、ZooKeeper 那个生态位。
真正和 DotNext 平级竞争的,是它底下压着的 Kommander ------一个独立发布的分区化 Raft 共识库。再往下还有一层 Nixie,轻量 Actor 运行时。
Kahuna.Server / Client / CLI / K8s Operator
└── Kahuna.Core(MVCC + 2PC 事务 + Script DSL)
└── Kommander(分区化 Raft 共识)
└── Nixie(Actor 模型)
三层全出自同一个作者------Phalcon 框架的 Andrés Gutiérrez,全部 MIT 协议。也就是说,这哥们儿为了做一个 .NET 版 etcd,先把 Actor 框架和 Raft 库都自己造了一遍。2025 年 2 月开坑,到现在 900 多个 commit,几乎一天没停。
架构拆解:Multi-Raft + MVCC + Percolator 式 2PC

几个值得说道的点:
Multi-Raft 分区架构。 数据切成若干分区,每个分区一个独立的 Raft group。节点在 A 分区当 Leader、在 B 分区当 Follower 是常态,Leader 还能自动均衡。存储层可插拔,RocksDB 或 SQLite 任选。
事务是认真做的。 Percolator 风格的 Prewrite + Commit 两阶段提交,叠上 MVCC 快照隔离,乐观、悲观两种并发模式都有。源码里能看到 prepared_intent、coordinator_decision 这些 protobuf 定义------TiKV 那套味儿很正。docs 目录里甚至躺着一篇完整的分布式事务论文和 30 多篇专题设计文档。
自带脚本 DSL。 它用 GPLEX/GPYACC(yacc/lex 的 .NET 移植)生成了一个服务端脚本解析器,多步操作可以塞进一个事务脚本在集群侧一次跑完,还能注册 C# 自定义函数,省掉客户端来回往返。
最骚的一点: 整个 Core 同时编译 net10.0 和 net10.0-browser。换句话说,这个 Raft 节点能以 thread-free 模式跑在浏览器 WASM 里。我印象里,别的语言的 Raft 实现没谁干这事。
它凭什么算「认真」:Jepsen 见
判断共识实现成不成熟,金标准不是 star 数,是 Jepsen。
Kahuna 配了一整套 Jepsen 测试,独立仓库维护,五个负载(register、lock、append、sequencer、snapshot),故障注入覆盖网络分区、杀进程、进程暂停、成员变更。
更难得的是那份公开的 FINDINGS.md,写得极其诚实:
- register 负载抓到过一个少数派隔离下的脏读------修了;还有一个 term 不采纳的问题挂着 open 状态没关;
- lock 负载抓到过 fencing token 回滚------已修,16/16 验证通过;
- snapshot 负载第一次跑 nightly 就抓到并发 hold 回绕到旧版本的真 bug------已修;
- 就在 10 月 8 日,还在修一个 partition map 的 lost update。
敢把没修完的 bug 公开挂出来,这比一万个 star 都有说服力。
回到那条评论:两边各对了一半
我刚查了 NuGet,搜 "raft" 命中 65~71 个包;下载量也是实的:DotNext.Net.Cluster 十八万+,Kommander 四万八。说「.NET 没有 Raft」,肯定不成立。
但一楼的体感也没错,只是准确的说法应该是:
这七十多个包里,绝大多数是个人实验品。真正同时具备持久化 WAL + 快照 + 动态成员 + 持续维护 + 对抗性验证五要素的,数来数去就 DotNext 和 Kommander 两家。
跟 Java 比,人家有 Apache Ratis、SOFAJRaft、Atomix;跟 Go 比,hashicorp/raft 背后站着 Consul 和 Nomad 多年的生产锤炼,还有 etcd 和 dragonboat。
.NET 缺的从来不是库,是一个被顶级基础设施反复用过、踩过坑的共识底座,以及围绕底座长出来的成品服务。
而这恰恰是 Kahuna 的价值:它把 .NET 从「有可用的 Raft 库」往前推了一步,推到「有 etcd 生态位的成品服务」,并且选择用 Jepsen 而不是营销稿来回答成熟度质疑。Java 和 Go 那些今天看起来很「成熟」的组件,当年也都是这么一路炸过来的。
生态年轻不是病,假装成熟才是。
最后,给 DrasiWake 捎句话
博客里自建的那套「outbox 账本 + 文件锁」,其实 Kahuna 的 fencing 锁加事务 KV 可以直接替掉。就算坚持自建,Kommander 的 expectedTerm 栅栏和 quorum gate,跟善友文里那「三道岗」是同一个思路,值得对照着看。
参考链接
- Kahuna:https://github.com/kahunakv/kahuna
- Kommander:https://github.com/kahunakv/kommander
- Jepsen 测试报告:https://github.com/kahunakv/kahuna-jepsen
- DrasiWake 原文:https://www.cnblogs.com/shanyou/p/23219306