Skip to content

区块链基础 ​

最后更新:2026 年 9 月 12 日

本文内容 ​

  • 为什么有些账本会复制验证,以及全节点、轻客户端和许可型模型有何不同
  • 共识、Merkle 树、P2P 和最终性的作用,以及它们各自对基础设施运维造成的限制
  • 为什么区块链节点必须区别于普通有状态服务来管理

问题陈述:在没有可信仲裁方的情况下达成一致 ​

理解区块链的出发点不是技术,而是它所受的限制。

考虑一个普通的分布式系统,例如 Kubernetes etcd 集群。etcd 也会在多个节点间达成共识,但前提是:参与节点由同一个组织运行,节点会故障,但不会说谎。 它能处理节点宕机和网络分区(崩溃故障),但无法应对节点故意宣称不同的值。

区块链的前提不同。

项目etcd(Raft)区块链
参与者同一组织、成员已知彼此未知、成员会变化
假设的故障崩溃故障(宕机、分区)拜占庭故障(说谎、串通、攻击)
参与资格由运营方指定公有链上为任何人
能否撤销运营方可以介入仅能按协议允许的方式处理

许多公有链上的全节点会独立验证交易和共识规则。轻客户端、剪枝/快照同步节点以及许可型设计使用不同的验证/数据分发模型。采用许可型成员机制本身并不能使共识算法具备拜占庭容错能力。

由此可以得出区块链的一项根本属性。

区块链不是为吞吐量而设计的系统。 它会刻意接受冗余,以换取可验证性和抗篡改能力。

理解这一点,下面的每项运维特征就都顺理成章了。

区块与链:为什么叫“链” ​

一组交易构成一个区块,每个区块都包含紧邻的前一个区块的哈希值。

text
Block N-1               Block N                 Block N+1
┌──────────────┐       ┌──────────────┐        ┌──────────────┐
│ prev_hash:.. │       │ prev_hash: ──┼────────│ prev_hash: ──┤
│ merkle_root  │   ┌───│ merkle_root  │        │ merkle_root  │
│ transactions │───┘   │ transactions │        │ transactions │
└──────────────┘       └──────────────┘        └──────────────┘
      hash ────────────────┘

这种结构带来的属性是篡改会沿链传播。 更改区块 N 中的一笔交易 → 区块 N 的哈希值发生变化 → 区块 N+1 的 prev_hash 不再匹配 → 之后的所有区块都无效。

对于 PoW 链,重写历史需要重新完成足够多的、已被接受的工作量;其他链使用不同的最终性和治理假设。哈希链接可以检测篡改,但单靠哈希链接并不能确立最终性,也不能让每一种区块链在经济意义上都不可篡改。

Merkle 树:为什么需要它 ​

问题在于如何概括区块中的交易。可以把所有交易串接起来再计算哈希,但这样一来,要检查“某笔交易是否在这个区块中”就需要整个区块。

Merkle 树是一种二叉树:将交易两两配对并逐层向上计算哈希。

text
                merkle_root
               /            \
         H(AB)                H(CD)
        /     \              /     \
     H(A)    H(B)         H(C)    H(D)
      |        |            |        |
     tx A     tx B         tx C     tx D

由此得到的属性是Merkle 证明。要证明交易 C 位于这个区块中,只需要H(D) 和 H(AB),而不需要整个区块。接收方计算 H(C) → H(CD) → merkle_root,然后进行比较。

证明大小随交易数 N 按 log N 增长。即使区块中有一百万笔交易,证明也只需要约 20 个哈希值。

实际意义:Merkle 证明使轻客户端成为可能。无需保存整条链,也可以验证某笔交易是否包含在其中。将区块链集成到现有系统时,由此可以判断“运行全节点,还是轻量验证就够了”。

共识:谁来写入下一个区块 ​

共识算法需要决定两件事:谁提出区块,以及发生冲突时哪一方是规范链。

主要方法 ​

方法提议者选择成本的实质示例
PoW(工作量证明)最先解出计算难题的节点电力和硬件Bitcoin
PoS(权益证明)按质押权益的比例选择质押资金 + 违规时罚没Ethereum
BFT 系列在明确的拜占庭容错阈值下投票成员/验证者以及法定人数假设Tendermint;Fabric 3.x SmartBFT
许可型 CFT 排序已知副本使用崩溃容错共识无法容忍任意拜占庭式排序行为Fabric Raft

为什么需要成本 ​

这个问题是理解共识的关键。如果提议区块没有成本,就可以创建无限多个候选区块并瘫痪网络。 在允许匿名参与的环境中,单靠身份无法阻止这种情况(Sybil 攻击:一个参与方创建大量身份)。

PoW 将成本设定为计算资源;PoS 将成本设定为资金加上罚没风险。BFT 系列会从一开始就限制参与者,以绕开这个问题,因此适用于联盟链。

公有链与私有链由此分化 ​

类型参与方式共识机制吞吐量主要用途
公有链(无需许可)任何人PoW/PoS低公有资产、互操作性
私有链/联盟链(许可型)获准成员BFT/Raft相对较高企业间账本、受监管环境

许可型设计可以使用已知成员和明确治理,再根据实际威胁模型选择 CFT 或 BFT。金融应用可以使用带有不同控制措施的许可型或公有网络;成员资格和共识机制的名称都不能证明其符合监管要求。

最终性:运维中最重要的概念 ​

最终性描述的是在协议安全假设下交易完成结算的状态。 它并不无条件保证不会发生任何攻击、治理干预或应用层补偿交易。应区分概率置信度、经济最终性和确定性的共识保证。

概率最终性与绝对最终性 ​

类型含义示例
概率最终性区块堆叠得越多,交易被撤销的概率就按指数衰减。但不会精确降到零Bitcoin 的 PoW
经济最终性在权益/罚没假设下,已最终确认的检查点受到保护;但物理上并非绝对不可能被撤销Ethereum PoS
即时最终性在共识轮次结束时完成结算BFT 系列

为什么这是运维问题 ​

节点返回的数据可能尚未最终确认。

向区块链节点询问“这笔交易的结果是什么”,节点会根据它当前已知的最新链来回答。如果该最新区块后来被重组(reorg),回答就会改变。

这会造成以下实际事件模式:

模式结果
根据最新区块确认存款后就执行操作提款已经发出,区块重组却抹掉了存款
健康检查只确认“节点存活”同步落后的节点会返回过期数据
负载均衡器在多个节点之间分配请求各节点区块高度不同 → 同一问题得到不同答案

因此,应用设计必须包含“在 N 次确认后处理”的规则(确认深度),其数值取决于链的最终性特征。 这无法单靠基础设施解决;它是与应用之间的契约。

基础设施可以做到:

  • 将同步状态纳入健康检查:将就绪定义为“落后链头不超过 N 个区块”,而不是“节点存活”
  • 监控节点之间的区块高度差异:差异扩大时,将节点移出负载均衡
  • 将重组事件暴露为指标,让应用可以据此响应

P2P 网络:它为什么不同于普通服务 ​

区块链节点使用点对点通信,而不是客户端/服务器模式。这与 Kubernetes 网络模型之间会产生摩擦。

Gossip 协议 ​

新区块或新交易出现时,会传播给相邻节点,相邻节点再传播给它们的邻居。网络中的所有参与方由此获知该信息。

其特点:

  • 没有中央代理 → 没有单点故障
  • 相同数据会通过多条路径冗余到达 → 带宽消耗在重复数据上
  • 传播需要时间 → 各节点对“最新状态”的认知不同(也会引出上文所述的最终性问题)

在 Kubernetes 环境中的摩擦 ​

区块链 P2P 所需能力Kubernetes 默认情况
稳定的对等节点身份(节点 ID、地址)Pod IP 会在重启后变化
接受入站连接(其他节点连接到本节点)默认情况下,外部无法直接访问 Pod
持久化对等节点列表Pod 替换后状态丢失
公布固定端口由 Service 做端口映射

因此,区块链节点通常默认采用 StatefulSet + 无头 Service,因为它们需要稳定名称和有序标识。接受入站 P2P 连接还需要额外的暴露设计。在 EKS 上运行区块链节点会介绍具体做法。

状态与存储:为什么重建很困难 ​

区块链节点会保存两类数据。

数据特性大小
区块历史只追加日志。过去的记录不可更改持续增长
当前状态余额、合约存储。可以通过重放区块推导也会增长,但小于历史数据

关键属性:状态可以从历史记录重放出来,但重放需要很长时间。

从创世区块开始重放并验证每个区块(全量同步)所需时间与链的历史长度成正比。因此才出现了其他同步方法。

方法做法权衡
全量同步从创世区块开始验证并重放全部数据置信度最高,速度最慢
snap/fast sync获取状态,并根据已接受的状态根验证证明;历史校验取决于客户端/模式速度更快,但明确依赖共识/检查点和具体实现的信任假设;不是盲目信任任意对等节点
检查点同步从可信检查点开始速度最快,但信任检查点来源
恢复快照恢复运营方保存的数据目录速度快,但需要管理快照的新鲜度和一致性

运维结论:替换 Pod 时不能丢失状态。状态丢失会导致节点长时间同步,在此期间它无法提供服务。因此,对区块链节点来说,持久卷不是可选项,而是必需项。

归档节点:需要单独考虑 ​

能够查询“某个任意历史时点的状态”的节点称为归档节点。它需要保留所有中间状态,因此比普通节点需要多得多的存储空间。

这里需要做设计判断:首先确认是否真的需要归档能力。多数应用只需要近期状态;如果需要历史查询,用索引服务或数据仓库处理会更具成本效益。

密钥管理:丢失密钥,一切就结束了 ​

在区块链中,身份和权力都由私钥代表。这与现有系统有决定性差异。

现有系统区块链
忘记密码后可以重置密钥丢失后,资产/权限将永久消失
管理员可以冻结被入侵的账户没有任何参与方能够撤销交易(除非协议允许)
审计日志可用于事后追踪交易签名一旦最终确认,就无法撤销

因此,备份策略的性质也不同。 链数据可以从网络重新获取,备份它的价值较低。与此相反,密钥必须备份,而且备份本身也是暴露风险。

这就是区块链基础设施为何重视 HSM 和 AWS KMS/CloudHSM。验证者尤其面临相互矛盾的要求:密钥必须在线才能签名,却又必须确保不会泄露。金融服务视角会讨论这个问题。

运维特征:由以上内容推导出的结论 ​

汇总这些概念带来的运维特征:

区块链设计对应的运维特征在 Kubernetes 中的含义
复制全节点验证增加副本本身不会提高基础链的写入能力可以提高整体 RPC/读取能力和可用性
状态在本地累积替换 Pod 的成本很高必须使用 StatefulSet + 持久卷,并考虑节点亲和性
链同步存在延迟“存活”和“能够提供服务”是两回事将同步状态纳入就绪检查
最终性不是即时的最新数据不等于最终数据将确认深度作为应用契约
P2P Gossip需要入站连接和稳定身份无头 Service,并额外设计暴露方式
硬分叉会在确定时点启用新规则在激活前升级兼容的二进制文件可以预先通过金丝雀和滚动升级为整个设备群做好准备
密钥代表权限密钥丢失 = 永久损失使用 KMS/HSM,并分别制定密钥与数据的备份策略
冗余验证是设计目标持续消耗 CPU 和 IOPS不适合依赖突发资源供给的设置

这张表是本节的核心。 文档 2 中的每项具体建议都源于此表。

硬分叉:与 Kubernetes 运维模式最大的冲突 ​

不向后兼容的协议变更称为硬分叉。整个网络会在指定区块高度或时间切换到新规则,没有切换的节点会留在另一条链上。

它与 Kubernetes 常见做法的冲突:

Kubernetes 惯例遇到硬分叉时
通过滚动更新逐步过渡激活前可行,前提是所有必需节点都能在截止时间前支持新规则
先对一部分实例做金丝雀测试激活前测试兼容分叉的二进制文件,并在适当的测试网/主网阶段比较行为
遇到问题就回滚回滚会让该节点留在旧链上
升级由运维团队自行安排升级时间由外部确定

实际建议:不要把硬分叉当作一次部署,而要把它当作有截止期限的迁移。订阅客户端发行说明,提前完成升级,并先在测试网上验证。

Ethereum 于 2025 年交付了 Pectra 和 Fusaka,此后采用更频繁的升级节奏。应根据已发布的激活日期和客户端发行说明安排维护,不要假定每年两次的时间表有保证。

总结 ​

  • 比较所选共识和信任模型:etcd/Raft 可容忍崩溃故障;一些区块链使用 BFT;许可型 Fabric 可以使用 CFT Raft 或 SmartBFT。仅有“区块链”这个标签并不代表具备拜占庭容错能力。
  • 许多全节点设计会复制验证过程;轻客户端和许可型模型各不相同。RPC/读取能力可以独立于基础链的写入能力扩展。
  • prev_hash 链会传播篡改,Merkle 树能够生成大小为 log N 的包含证明(这是轻客户端的基础)。
  • 共识需要成本来防御 Sybil 攻击。限制参与者(联盟链)消除了这一需求,因此可以使用吞吐量和最终性更好的 BFT,但去中心化程度会降低。
  • 最终性是运维中最重要的概念。 最新数据不是最终数据,因此就绪检查中应包含同步状态,并将确认深度纳入应用契约。
  • 状态可以重放,但重放需要很长时间,因此必须使用持久卷。
  • 硬分叉的激活时间由外部协调确定;应提前准备兼容客户端,并单独评估激活后的回滚方案。

下一篇:在 EKS 上运行区块链节点将这些特征转化为具体配置。

参考资料 ​

向文档提问

按 Enter 发送,按 Shift+Enter 换行。