解决以太坊区块重组
突然报告有用户卡在注册流程走不下去,已经注册成功还是不断被要求注册,这是什么问题呢?首先看一下项目架构,前端后端合约端,不了解的请在本专栏第一篇文章中一览详情。查看了用户在区块浏览器上面的 transaction 记录,有一条成功注册的记录,那么中间发生了什么呢?
问题排查
既然用户已经在链上注册成功,为什么数据库中却没有这条记录呢?
那我们从下往上一步一步排查,数据库中的内容来源是 event,后端解析监控到的智能合约发出的 event 来生成一些数据。既然数据库里面没有,我们去看一下 event 记录里面有没有。
在 event 原始数据表中找了一下,并没有找到这个 event,这样就比较奇怪了。折回去看了用户 transaction 所在区块,查了一下表中这个区块中发出的 event,发现这个区块中并没有我们智能合约发出的 event。然后把线上的日志 down 下来排查。
我们给合约发出来的 event 加了一个唯一自增 ID 来保障他的时序性和唯一性,在 event 监控部分的工作中针对他的时序性和唯一性做了处理(同一个 ID 的 event 只处理一次),这下找到问题了:我们发现了一个「并不存在」的区块数据,区块 hash 和链上的区块 hash 不一致,区块重组了。
由于被重组的区块一下占用了十几个 event 的 ID,在它被重组后,最长链上的 ID 进来之后不会被处理了,这就导致在这十几个被占用的 ID 之间有几名用户注册的事件没有按照期望同步到后端。
问题解决
- event 订阅中,是有一个
Removed
字段的,代表这个 event 所在的区块被重组了。 - 我们给收到的 event、由 event 产生的各种数据 加上区块高度和区块 hash 记录,当一个区块被重组时,把对应的 event、产生的 数据清理掉就好了。
- 这里注意:
Removed
字段也并不是 100% 可靠,我司就遇到过节点通知区块被重组,实际上并未被重组的事情。
- 这里注意:
吃一堑长一智
- 项目中重要的功能部分,文档中的每一个字段都要吃透
- 准备学习 Solidity 的小伙伴,每一个修饰符都要吃透
- 做 Dapp 项目的公司,区块重组是必定要考虑在内的因素