写入架构
BlockDB 为区块链计算场景设计:上游数据总是按区块粒度产出,天然就是一批一批的行。因此 BlockDB 的写入以 batch 批量写为预设,而不是传统的单行写。区别只在于 batch 的规模——小的、近实时的 batch 走实时写;大的、回填场景的 batch 走批量写。一切写均为异步
BlockDB 一切写操作均为异步:SDK 不暴露sync 参数,所有写入接口返回 WriteResult { affectedRows, jobID },不代表数据已立即落库。
因此,普通的写入接口不满足经典的写后读一致性——写请求返回后立刻读,不保证能读到刚写入的数据。
但这个”缺口”在 BlockDB 的逻辑模型中被弥补:
- Block 表:写入成功后,write 服务通过 Kafka 发布
BlockSubscribeEvent。下游通过Subscribe接收事件后再读取该区块的数据,BlockDB 保证此时数据已落库可见。在订阅驱动的计算链路中:写 → 事件 → 读,是严格满足写后读一致性的。 - Time 表:写入后通过
GetValue对_archive表查询,同样能获取已落库的历史桶数据。
SDK 写接口总览
实时写
批量写(S3 中转,上限 1000 万行)
批量写统一走一个 gRPC 服务BatchWriteService。在 InitWriteJob 请求中,通过选择 strategy 字段来指定目标表类型:
WriteResult { affectedRows, jobID }。
实时写架构
实时写由简单的无状态 writer 负责,内部采用内存异步队列 + 多线程响应式写入:- 入队:写入请求进入内存异步队列(
asyncqueue),立即返回jobID。用户不会因后端落库速度而阻塞。 - 消费:多个 worker 线程并发从队列中取任务,批量写入底层物理数据库。
- 流量整形:队列容量有上限,当后端落库跟不上时触发拒绝(返回
QUEUE_OVERLOAD),将无上限的实时流量转为有上限的写入流量,保护底层数据库。
批量写架构
当写入规模达到百万行级别(上限 1000 万行)时,实时写的内存队列不可行。批量写通过 S3 对象存储中转 + 异步 worker 实现:任务生命周期
InitWriteJob:客户端发起写入任务申请。BlockDB 在表的_write表中创建一条 job 记录,返回 S3 presigned 上传 URL 与jobID。- 上传数据文件:客户端将数据上传到返回的 S3 URL。
CommitWriteJob:客户端调用提交接口,BlockDB 将 job 状态置为待处理,后台 worker 开始消费。- Worker 执行:worker 从 S3 拉取任务文件,执行排序、去重、批量插入等步骤后落库。
架构特点
- 提交吞吐无上限:任务通过 S3 中转,不占用实时内存通路,可连续高吞吐提交。
- 落库速度快:worker 以批处理方式工作,实际写入速度可达数十万~百万行/s(视表类型与底层数据库规模)。
- 可取消:堆积的写入任务可通过
CancelWriteJobAPI 取消,释放 S3 资源及_write表中的对应 job 记录。 - 任务状态可查:job 在
_write表中维护,包括已初始化、已提交、处理中、完成或失败等状态,便于运维排查。