入职 Web3 运维日记 · 第 11 日:从 Hex 到 SQL —— 自建链上数据仓库 (Data Warehouse)

时间 :入职第 11 天,上午 10:30 天气 :晴,适合看报表 事件:产品经理 (PM) 的灵魂拷问

刚过完试用期,我心情不错。 产品总监 (Head of Product) 拿着一杯咖啡走过来:"Alen,听说节点很稳。那你能不能帮我拉一个数据:过去 7 天,Bybit 用户充值最多的 Top 10 币种是什么?以及这些用户的平均持仓时间是多少?"

我差点把刚喝的水喷出来。 "老大,Geth 节点不是 MySQL。它没有 SELECT * FROM transactions WHERE... 这种命令。你要查这个,我得写脚本把过去 7 天的 50,000 个区块全部遍历一遍,大概要跑 3 个小时。"

产品总监皱眉:"别的交易所都能实时看,我们为什么不行?数据的价值在于实时。 我不管你用什么办法,我要一个 Dashboard。"

任务 :搭建一套 链上数据索引系统 (Indexer) ,把区块链数据实时清洗进 SQL 数据库

🧩 1. 上午 11:30:架构选型 ------ 为什么 Geth 不行?

我召集了数据组的同事,画了一个架构图。

痛点分析

  • Geth (LevelDB):是 KV 存储。

    • Get(Key) 极快。

    • Count(*) 不可能。

    • 数据全是 0x... 的十六进制,人类不可读。

  • 目标 :我们需要一个 OLAP (在线分析处理) 数据库。

技术栈选型

  1. ETL (抽取层) :用 Python (Web3.py) 写一个"爬虫",实时从 Geth 节点 eth_getBlock

  2. Queue (缓冲层) :用 AWS MSK (Managed Kafka)。区块链有时候会爆发(比如 NFT 抢购),直接写数据库会崩,需要 Kafka 削峰。

  3. DB (存储层)ClickHouse

    • 为什么不用 MySQL?因为以太坊历史交易有十几亿笔,MySQL 查不动。

    • 为什么用 ClickHouse?它是列式存储,聚合查询(Sum, Count, Avg)快得令人发指,单机每秒处理几亿行。

🛠️ 2. 下午 02:00:编写 ETL 脚本 ------ 与"大整数"的斗争

我开始写 Python 脚本。 逻辑很简单:Loop Block -> Get Txs -> Decode -> Push Kafka

但很快我遇到了 Web3 数据分析的第一个巨坑精度问题

代码片段:

复制代码
# etl_worker.py
from web3 import Web3

w3 = Web3(Web3.HTTPProvider("http://localhost:8545"))

def process_block(block_num):
    block = w3.eth.get_block(block_num, full_transactions=True)
    for tx in block.transactions:
        # 坑点:tx.value 是一个 uint256 (比如 100 ETH = 100000000000000000000)
        # 普通的数据库 Int64 根本存不下!
        # 如果转成 Float,精度会丢失,财务会杀了我。
        
        record = {
            "hash": tx.hash.hex(),
            "from": tx['from'],
            "to": tx['to'],
            # 解决方案:存成 String 或者 Decimal(38, 0)
            "value_raw": str(tx.value), 
            "gas_price": tx.gasPrice,
            "block_number": block_num,
            "timestamp": block.timestamp
        }
        kafka_producer.send("ethereum_txs", record)

Alen 的经验 : 在金融数据仓库里,永远不要用 Float 存钱。 要么存 String,要么用数据库的高精度 Decimal 类型。

🚀 3. 下午 04:00:ClickHouse 的魔法

数据通过 Kafka 流入了 ClickHouse。 我在 ClickHouse 里建了一张表:

复制代码
CREATE TABLE ethereum.transactions (
    hash String,
    from String,
    to String,
    value_raw Decimal(38, 0), -- 完美支持 uint256
    block_number UInt64,
    timestamp DateTime
) ENGINE = MergeTree()
PARTITION BY toYYYYMM(timestamp) -- 按月分区
ORDER BY (block_number, from);   -- 排序索引

测试查询: 产品总监要的那个需求(过去 7 天 Top 10 充值):

复制代码
SELECT 
    to, 
    sum(value_raw) / 1e18 AS total_eth 
FROM ethereum.transactions 
WHERE 
    to IN (SELECT address FROM exchange_wallets) -- 我们的充值钱包列表
    AND timestamp > now() - INTERVAL 7 DAY
GROUP BY to 
ORDER BY total_eth DESC 
LIMIT 10;

结果 : ClickHouse 在 0.05 秒 内返回了结果。 而在 Geth 上,这个查询即使写脚本跑,也需要 3 个小时

🔄 4. 下午 05:30:处理 Reorg (回滚) 的麻烦

就在我得意洋洋的时候,Day 9 的那个幽灵又回来了------Reorg

如果我的 Python 脚本刚把 Block 100 写入 ClickHouse,结果链上发生了回滚,Block 100 变了。 那我的数据库里就有了脏数据

解决方案:延迟入库 + 版本控制

  1. 实时流 (Hot):直接展示,但在前端标记为"未确认 (Unconfirmed)"。

  2. 确认流 (Cold):只有当区块经过 12 个确认(Safe Block)后,才写入最终的分析表。

  3. ClickHouse 的 ReplacingMergeTree: 利用 ClickHouse 的去重引擎。如果有同一个 Block Number 的新数据进来,自动覆盖旧数据。

SQL

复制代码
-- 引擎改为支持去重的
ENGINE = ReplacingMergeTree(block_timestamp)
ORDER BY (block_number, hash)

📊 5. 下午 06:30:交付 Superset 看板

最后,我部署了一个开源的 BI 工具 Apache Superset,连上 ClickHouse。 拖拖拽拽,画出了几个图表:

  • ETH 每日充值趋势图

  • Gas 费消耗热力图

  • 大户监控列表 (Whale Alert)

我把链接发给产品总监。 他点开后,看着实时跳动的数字,沉默了三秒,然后说:"Alen,这比 Etherscan 也就是强了大概 100 倍吧。这周给你加鸡腿。"


1. 什么是 ClickHouse?是 AWS 上面的服务吗?如果不是,为什么要自建?

Alen 的回答:

  • 什么是 ClickHouse?

    • 它是一个开源的 列式数据库 (Columnar DBMS) ,专门用于 OLAP (在线分析处理)

    • 特点 :快。非常快。对于海量数据(比如几十亿行交易记录)的聚合查询(求和、计数、平均值),它比传统的 MySQL/PostgreSQL 快 100-1000 倍

    • Web3 标配:在区块链行业,几乎所有的顶尖数据分析平台(如 Dune Analytics, Nansen, Etherscan)底层都在用 ClickHouse 或类似技术。

  • 是 AWS 的服务吗?

    • 不是。 AWS 没有"Amazon ClickHouse"这个原生服务(不像 Amazon RDS 或 Amazon Redshift)。

    • 虽然市面上有 ClickHouse Cloud 这种托管服务,但在 AWS 上使用通常意味着:在 EC2 上自建,或者使用第三方托管在 AWS 上的版本。

  • 为什么要自建?(而不是用 AWS Redshift 或 Athena)

    1. 成本 (Cost)

      • 区块链数据是"写多读少"的日志型数据。AWS Redshift 非常贵,而且按节点收费。

      • ClickHouse 对数据压缩率极高(通常 10:1)。同样的 1TB 数据,存 ClickHouse 可能只需要 100GB 硬盘。在 EC2 上自建 ClickHouse,成本只有 Redshift 的 1/5。

    2. 响应速度 (Latency)

      • AWS Athena (基于 Presto) 是按查询扫描量收费的,而且查询通常有几秒延迟。

      • ClickHouse 是毫秒级响应。产品总监要看实时 Dashboard,他不想点个按钮等 10 秒,他要 0.1 秒出图。

    3. 大宽表支持

      • 区块链交易数据字段很多,ClickHouse 极其擅长处理这种"大宽表"。

2. 精度问题是什么问题?

Alen 的回答:

这是区块链开发和传统开发最大的鸿沟------数字太大了

  • 传统世界的数字

    • 数据库里的 Int64 (长整型) 最大能存多少?大约 900 亿亿 (9 \\times 10\^{18})。

    • 浮点数 Float/Double 虽然能存大数,但是会丢精度 (比如存 100.0000001 变成了 100.0)。

  • 区块链世界的数字

    • 以太坊的最小单位是 Wei。1 ETH = 10\^{18} Wei。

    • Solidity 智能合约里常用的数字类型是 uint256

    • uint256 的最大值是 1.15 \\times 10\^{77}

    • 冲突点 :如果不经处理,直接把一个 uint256 的大数塞进 MySQL 的 Int64 字段,数据库会直接报错 "Numeric Overflow" (数值溢出) 。或者如果塞进 Float,财务就会找你拼命,因为钱算不准了。

  • Alen 的解决方案

    • 方法 A (字符串) :存成 String 类型 ("1000000...")。缺点是不能直接做加减乘除运算。

    • 方法 B (高精度小数) :ClickHouse 支持 Decimal256Decimal(38, 0)。这是一种专门用来存超大整数且不丢精度的格式。这是金融系统的唯一正解。


3. 实时流和确认流是什么?是要两种不同的导入到 ClickHouse 吗?

Alen 的回答:

这是为了解决 Day 9 提到的 "回滚 (Reorg)" 问题而设计的数据管道策略。

它们不一定是两条物理网线,而是两条逻辑管道,通常会在代码里处理。

场景:处理"不确定"的未来
  • 实时流 (Hot Stream)

    • 来源 :Geth 的 Latest 区块。

    • 动作:爬虫一抓到新块(比如高度 100),立刻塞进 ClickHouse。

    • 用途:给用户看"待确认"状态,或者给大屏看实时趋势。

    • 风险:这个块可能会被回滚(消失)。

  • 确认流 (Cold Stream)

    • 来源 :Geth 的 Finalized 区块(或延迟 12 个块)。

    • 动作:爬虫再次检查高度 100。确认它没有被回滚,标记为"已确认"。

    • 用途:给财务做账,给风控做审计。

怎么导入 ClickHouse?(Alen 的骚操作)

通常不需要导两次(浪费空间)。Alen 使用了 ClickHouse 强大的 ReplacingMergeTree 引擎

  1. 10:00:00:实时流写入一行数据:

    {Block: 100, Tx: A, Status: "Pending", Version: 1}

  2. 10:15:00(区块已确认):确认流写入一行数据:

    {Block: 100, Tx: A, Status: "Confirmed", Version: 2}

  3. 数据库自动合并

    ReplacingMergeTree 引擎会自动发现:"咦?Block 100 来了个 Version 2。"

    它会自动用 Version 2 覆盖 Version 1

相关推荐
2601_949146537 小时前
Shell语音通知接口使用指南:运维自动化中的语音告警集成方案
运维·自动化
儒雅的晴天7 小时前
大模型幻觉问题
运维·服务器
Gofarlic_OMS8 小时前
科学计算领域MATLAB许可证管理工具对比推荐
运维·开发语言·算法·matlab·自动化
通信大师8 小时前
深度解析PCC策略计费控制:核心网产品与应用价值
运维·服务器·网络·5g
dixiuapp8 小时前
智能工单系统如何选,实现自动化与预测性维护
运维·自动化
Elastic 中国社区官方博客8 小时前
如何防御你的 RAG 系统免受上下文投毒攻击
大数据·运维·人工智能·elasticsearch·搜索引擎·ai·全文检索
小锋学长生活大爆炸8 小时前
【教程】免Root在Termux上安装Docker
运维·docker·容器
进击切图仔8 小时前
常用 Docker 命令备份
运维·docker·容器
SQL必知必会9 小时前
SQL 窗口帧:ROWS vs RANGE 深度解析
数据库·sql·性能优化
NotStrandedYet9 小时前
《国产系统运维笔记》第8期:挑战国产化流媒体部署——银河麒麟+龙芯架构编译SRS实战全记录
运维·kylin·国产化·银河麒麟·龙芯·信创运维·srs编译安装