Move语言:如何与Move VM缓存交互及持久化缓存变更
Diem中Move VM缓存的交互逻辑与持久化流程
一、缓存层级与分工
Move VM里的两类缓存各司其职,形成两层缓存架构:
- TransactionDataCache:单事务隔离的缓存,每个交易执行时会创建独立实例。它是VM状态操作的直接入口,负责记录当前交易全量的状态变更(包括资源增删改、模块发布/更新、账户序列数修改等),确保事务的原子性——只有交易执行成功,这些变更才会被提交。
- AccountCache:节点级的复用缓存,跨交易共享。它主要缓存账户的基础元数据(是否存在、序列数)和已加载的Move模块,目的是减少对持久化存储的重复读取,提升执行效率。
二、交互与持久化时机
1. 交易执行前
节点会先从持久化存储中加载当前交易涉及账户的基础状态到AccountCache,然后为该交易初始化TransactionDataCache,后者会依赖AccountCache的已有数据作为初始视图。
2. 交易执行中
VM的所有状态读写操作都会被缓存拦截:
- 读操作:优先查询TransactionDataCache(当前交易的临时变更),如果未命中则查AccountCache,最后才会访问底层持久化存储,读取到的数据会逐级存入缓存。
- 写操作:所有修改直接写入TransactionDataCache,不会同步到AccountCache或持久化存储,这样可以保证交易失败时不会污染全局状态。
3. 交易执行后
- 成功场景:TransactionDataCache中的变更集会被合并到AccountCache,同时生成结构化的变更批量数据,一次性写入到持久化KV存储(Diem中用RocksDB)。整个过程是原子性的,要么全量提交,要么全部回滚。
- 失败场景:TransactionDataCache直接被销毁,AccountCache和持久化状态不会有任何变更,保证状态一致性。
三、移植到其他区块链时的缓存复用方案
如果你想避开实现DataStore trait,直接复用VM的缓存能力并将变更同步到自己的KV数据库,可以按以下步骤操作:
- 复用VM原生缓存实例
直接初始化TransactionDataCache和AccountCache,不需要自己实现完整的DataStore。只需要写一个极简的底层存储适配层,实现缓存需要的基础读写接口(比如读取账户状态、模块二进制数据)即可,缓存逻辑完全交给VM处理。 - 提取变更集并批量持久化
交易执行成功后,通过TransactionDataCache的公开方法(比如into_changes())提取所有变更记录,这些记录包含:- 账户元数据的修改(序列数、余额等)
- Move模块的增删改
- 全局资源的增删改
将这些变更批量写入你的KV数据库,必须保证原子性——要么全部写入成功,要么全部回滚,避免出现部分状态更新的情况。
- 维护AccountCache的一致性
跨交易或跨区块时,需要让AccountCache与你的KV存储保持同步。比如当外部交易或区块修改了某个账户的状态,要及时清理AccountCache中对应的条目,防止读取到过期数据。
内容的提问来源于stack exchange,提问作者a6i09per5f
相关产品推荐
相关产品推荐

