关键词:Rust/区块链/EVM/并发编程/日志分析/tokio/governor/moka/高性能架构🧭导读这不是一篇单纯讲Rust的文章。而是一篇从一台机器、一个节点、到每天处理百日区块数据的性能奇迹诞生记。如果你:正在用RPC拉链上
关键词:Rust / 区块链 / EVM / 并发编程 / 日志分析 / tokio / governor / moka / 高性能架构
这不是一篇单纯讲 Rust 的文章。
而是一篇从一台机器、一个节点、到每天处理百日区块数据的性能奇迹诞生记。
如果你:
那你一定不能错过这篇文章。
我将详细剖析从 性能病秧子到百万级吞吐系统的全过程。
7 天都跑不完
到 24小时处理 100 天
需求看起来很“简单”:
日志有业务顺序依赖问题
,无法做到完全并发,需要处理区块1的日志才能处理区块2日志实际运行中暴露出多个挑战:
困难项 | 描述 |
---|---|
数据量巨大 | 总量达 数亿级区块,每个区块 平均约150条 交易日志记录 |
时间戳缺失 | 需要 额外调用 get_block 获取每条日志时间戳 |
API 限流 | 每节点每秒最多 10 req/s,超过容易封禁 |
节点资源有限 | 仅有 10 个节点可用,高并发成本受限 |
并发复杂度高 | 需要调度任务、缓存时间戳、并发写入、异常容错等 |
初始用一个基础 tokio 异步服务模型:
for block in block_range {
let logs = get_logs(block).await?;
let ts = get_block(block).await?.timestamp;
write(logs, ts).await?;
}
结果:
简直就是一台 Rust 写的“病秧子爬虫”。
📌 问题归纳如下:
模块 | 问题描述 |
---|---|
RPC 限流 | 每秒 10 请求,稍超就触发限制 |
请求串行 | 所有逻辑全在主线程执行,延迟极高 |
重复请求 | get_block 每个区块都打一次 |
IO 阻塞 | 写入操作阻塞主线程,无法并发 |
错误处理 | 崩溃需手动重跑,无断点恢复机制 |
我将系统重构为 4 层职责模型:
get_logs
和 get_block
每个 RPC 节点绑定 governor 限流器:
let limiter = RateLimiter::direct(Quota::per_second(nonzero!(10)));
limiter.until_ready().await;
配合轮询调度器,分摊 10 个节点的调用压力。
任务流程:调度 → 请求 → 缓存 → 业务处理+落库
pub trait ProcessTask {
type TaskInput;
type TaskOutput;
async fn process(&self, task: Self::TaskInput) -> anyhow::Result<Self::TaskOutput>;
}
结合通用 worker pool 可调度日志拉取器、时间戳补全器、写入器等。
// moka 时间戳缓存
let cache = moka::sync::Cache::new(10_000);
cache.insert(block_number, timestamp, Duration::from_secs(3600));
// dashmap 状态管理
let map: DashMap<u64, TaskStatus> = DashMap::new();
设计 checkpoint 模块保存任务状态:
{
"123000": "Done",
"123001": "Failed(RPC timeout)",
"123002": "Pending"
}
阶段 | 吞吐量 | 日处理区块 | 时间戳支持 | 容错能力 |
---|---|---|---|---|
初版(串行) | 56 logs/sec | < 5 天/天 | ❌ | ❌ |
多线程改版 | 3000 logs/sec | ~40 天/天 | ✅ | ❌ |
缓存优化后 | 10000+ logs/s | 100+ 天/天 | ✅ | ✅ |
高峰突破状态 | 4.X 秒/批 | 最快处理极限 | ✅ | ✅ |
曾经,我以为处理亿级链上数据必须靠 Spark、分布式、云服务……
现在我只用一台机器 + Rust 服务,就能每天处理百日区块。
Rust 改变了我处理数据的方式,也让我更加相信:架构与实现,决定你是否能把性能压榨到极致。
如果你:
欢迎留言或私信我,我们一起在 Rust 的道路上,把“慢服务”干成“猛兽”!
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!