我的区块链运维日记 · 第 7 日:影子区块的诱惑 —— 多节点下的“重复充值”危机

🚨 序章:好心办坏事的高可用

前几天刚解决了单点故障的隐患,为了让系统达到 99.99% 的可用性(High Availability),我给 Scanner 做了升级:

  • 主力:AWS AMB 节点(稳重,就在自家内网)。

  • 备胎:Infura 和 Alchemy(外部公共节点集群,全球都有)。

我的逻辑是:"三个臭皮匠顶个诸葛亮。AMB 要是挂了,备胎立刻顶上,保证 Scanner 永远有数据抓。"

结果,早上 10 点,客服主管冲进来说:"Henry!有个用户只充了 10 ETH ,但咱们给人家加了 20 ETH!这钱是天上掉下来的吗?"


🎬 第一章:消失的唯一性

我第一时间查了数据库,看到了让我窒息的两行记录:

记录ID 交易哈希 (TxHash) 金额 区块哈希 (BlockHash) 数据来源 时间
#101 0xabc... +10 0x111... (宇宙A) AWS AMB 10:00:01
#102 0xabc... +10 0x222... (宇宙B) Infura 10:00:03

同一笔交易,被记了两次账。 唯一的区别是,它们属于两个完全不同的区块哈希。

这意味着:在那个瞬间,我们的系统同时相信了两个"平行的世界"。


🕵️‍♂️ 第二章:原理复盘 ------ 村口的黑板报

为了搞懂为什么会有两个世界,我给团队画了一个**"区块链村"**的比喻。

1. P2P 网络(传播是有时差的)

区块链村没有广播站,消息全靠村民(节点)之间口口相传。

  • 现象:村东头发生了什么事,传到村西头需要几秒钟。

  • 后果 :在某一秒钟,东头的人以为"王五赢了",西头的人以为"孙七赢了"。这就是分叉(Fork)

2. 节点的性格分析
  • AWS AMB(我们的老村长)

    • 性格:稳重、死板。

    • 行为:他一定要等全村大部分人都确认了(12 个确认数),才肯在自家的黑板上写字。写上去就是**"铁案"**,基本不会擦掉。

    • 缺点:反应慢半拍。

  • Infura(消息灵通的八卦王)

    • 性格:急躁、甚至有点"听风就是雨"。

    • 行为 :他眼线多,只要听到一点风声(比如产生了一个新块),他立刻就会写在黑板上(打草稿)。

    • 风险:如果过了一会儿发现消息是假的(分叉被回滚),他会立刻拿黑板擦擦掉,重写正确的。

3. 事故真相

我们的 Scanner(抄账员)犯了两个错误:

  1. 乱跑:先去了老村长家(AMB)抄了一笔确定的账(宇宙 A)。

  2. 轻信草稿 :紧接着又跑到了八卦王家(Infura),看到黑板上写了个不一样的区块(宇宙 B),以为是新消息,赶紧又抄了一遍。殊不知,那只是 Infura 打的草稿,还没来得及擦掉。


🛠️ 第三章:Henry 的三板斧修复方案

为了防止"假传圣旨",我进行了架构级重构:

1. 数据库层面的"死锁" (The Hard Stop)

我在 RDS 数据库里执行了一条死命令:

ALTER TABLE deposits ADD CONSTRAINT unique_tx UNIQUE (tx_hash);

  • 逻辑 :不管外面有多少个平行宇宙,不管 Scanner 从哪个节点抄来了数据,同一个 TxHash 在数据库里只能存一次

  • 效果 :如果 Scanner 试图插入第二笔 0xabc...,数据库会直接报错,物理隔绝重复充值。

2. "主从锁定"策略 (Primary First)
  • 旧逻辑:随机轮询(Round Robin)。谁有空问谁。

  • 新逻辑独宠 AMB

    • Scanner 永远只问 AMB。

    • 只有当 AMB 彻底断气(Timeout > 1min),才允许去问 Infura。

    • Henry 语录"老村长的消息虽然慢,但是准。管钱的事,要准不要快。"

3. "回溯校验"机制 (Look-Back Check)

如果被迫切换到了 Infura,Scanner 必须执行一套**"对齐仪式"**:

  • 动作 :不查最新块,先查上一个块(N-1)

  • 判定:问 Infura:"你眼里的 N-1 块哈希,跟老村长(AMB)之前记的一样吗?"

    • 如果一样 -> 说明你们在一个频道,继续工作。

    • 如果不一样 -> 说明 Infura 正在看"别的频道",立即停机,等待它同步回来。


📚 第四章:运维深度问答 (Q&A)

Q1: 为什么 Infura 的数据会不准?是它质量不好吗?

  • Henry: 不是质量不好,是角色不同 。Infura 是为了给前端钱包(Metamask)提供极速体验的,所以它必须快,哪怕偶尔有分叉也没关系。但我们做的是后端入账,我们需要的是 Finality(最终确定性)。用跑车的速度去拉货,必然会翻车。

Q2: 为什么 AMB 需要"等很多个同步一样"才发给我们?

  • Henry: AMB 节点通常只连接了有限的几个 Peers(邻居)。它内部有校验机制,会等待这些 Peers 达成共识后,才更新自己的区块头。这就相当于它是经过了"二次过滤"的数据,虽然慢,但过滤掉了大部分网络噪音。

Q3: 所谓的"草稿"和"封存"在技术上是什么?

  • Henry:

    • 打草稿 = 只有一个块头(Block Header),状态是 Canonical 但没经过足够多确认,随时可能变成 Uncle Block(叔块/孤块)。

    • 封存 = 区块后面连接了 12 个以上的新块,攻击成本极高,被全网回滚的概率接近 0。


💡 Henry 的日记结语

"第 7 天的教训告诉我:在分布式系统里,'一致性'是奢侈品。

以前我觉得高可用就是多接几根管子。今天我才知道,管子接多了,流进来的不一定是水,可能是洪水。

给数据库加上'唯一锁',并且学会区分'草稿'和'正文',是每个区块链运维必须修满的学分。"

相关推荐
竹之却1 天前
如何使用 SakuraFrp 做内网穿透
运维·服务器·网络·frp·内网穿透·sakurafrp
SPC的存折1 天前
3、Ansible之playbook模块大全
linux·运维·网络·python
万象.1 天前
docker镜像操作实操
运维·docker·容器
徐子元竟然被占了!!1 天前
DNS-特殊域名
运维
CDN3601 天前
CDN 缓存不生效 / 内容不更新?7 种原因 + 一键刷新方案
运维·网络安全·缓存
野木香1 天前
fnm在win10下安装配置
运维·学习
wydaicls1 天前
什么时候触发负载均衡(kernel 6.12)
运维·负载均衡
kainx1 天前
Linux编译eeprom
linux·运维·c语言·eeprom
三秋树1 天前
Foundry Fuzz 测试完全指南:从入门到生产级智能合约安全测试
区块链
攻城狮在此1 天前
MobaXterm下载安装及SSH远程连接(交换机/路由器/服务器)
linux·运维·服务器·网络