作者: ck
排版:MetaCat

写在前面

用这个标题不是为了哗众取宠,而是最近使用 MUD 框架(框架是更恰当的称谓)过程中,内心真实的想法。初步的答案是:MUD Indexer 是个最不坏的设计。本文会详细解释这个结论,并试图探讨可能的更优解,只是最粗浅的探讨,尚未找到满意的答案。顺手记录下这些想法,权当抛砖引玉。

来源:https://mud.dev/

数据库本位

《全链版 2048:我们从 MUD 引擎使用中学到了什么?》中我们提到,MUD 框架的设计遵循“数据库本位”思想。在 MUD 框架中,故事的主线围绕链上数据的读写展开,数据“”由 Store 承担;数据“”主要由 Indexer 承担。这里说“主要”,是因为在链上的数据读取职能,由 Store 承担,而链下(或者叫客户端)的数据读取由 Indexer 承担

来源:https://mud.dev/introduction

用户等待时间

Indexer 本质上是链上数据(以类似关系型数据库的形式存在)的客户端副本。在基于浏览器的 DApp 场景下,这意味着每次刷新页面,都需要重新建立客户端数据副本。由于数据“链式存储”的缘故,随着时间推移,建立数据副本所需的时间会不断增加,这也就意味着用户等待时间也增加、用户体验同步下降。

来源:https://www.mud2048.fun/

以 mud2048.fun 为例,目前大约需要等待 10-20 秒才能进入游戏主页面,这样的体验简直让人抓狂。本文以此为起点,探讨 MUD Indexer 设计的优缺点、有哪些可能的改进空间,进而讨论链上应用开发框架该如何设计数据读写模式

在期待以太坊 Layer 2 链上应用爆发的语境下,这样的讨论具有相当的现实意义,甚至可以说是决定 Layer 2 链上应用能否爆发的“元问题”。若该问题被解决,则以太坊 Layer 2 应用爆发的基础设施障碍被扫清,只需静待模式创新引发应用爆发。

MUD Store 是链上数据写入的更优方案

Store 的数据写入方式是比 Solidity 原生数据打包(Data Packaging)更紧凑的方式,这带来了更低的存储费用。此外,将链上数据存储“映射”为工程领域充分验证的“关系型数据库”,对开发者非常友好。因此,相较 Solidity 原生的数据写入方式,Store 的数据写入方案是更优的。但这也一定程度上导致了数据读取的效率问题,泰戈尔说:最好的东西不是独来的, 它伴了所有的东西同来:)

来源:https://mud.dev/store/tables

这种数据写入方式,或者换句话说,将数据写入区块链,导致数据读取/查询只有两种途径:

途径一,直接从链上读取。缺点是效率低下,且无法支持复杂查询。

途径二,将链上数据“拷贝”到链下,在链下完成复杂查询(MUD 采用的方案),但这同时带来两个问题:

1> 随着时间推移,同步“拷贝”数据所需时间不断增加,从而导致用户体验越来越差;

2> 在每个客户端副本都做一遍全局性查询/运算(比如排行榜),造成一定程度的资源浪费。

开发 mud2048.fun 的过程中,我们针对问题一,跟 MUD 团队有过简单沟通,得出了一些临时性解决方案,但治标不治本。下图红框处是 MUD 框架自带的链上数据“拷贝”过程。

来源:https://www.mud2048.fun/

终极之问:全链上应用该如何实现高效数据读取?

从互联网产品的发展中我们知道,在绝大多数产品超过90%时间是数据读取,只有不到10%的时间是对数据的写入。因此,一个高效的数据读取方案,直接决定产品的用户体验。

而数据读取问题,在区块链领域有个类似的词汇“数据可用性层”(Data Availability Layer)。虽然描述的不是同一个层面的问题,但似乎对我们思考当前问题的解法有一定帮助,姑且拿来一用

来源:https://www.alchemy.com/overviews/data-availability-layer

区块链领域常见 DA(Data Availability)方案大体可分为:链上 DA 和链下 DA 两种。比特币铭文属于链上 DA 方案(铭文数据存储在比特币区块链上,但数据解释在链外),以太坊 Layer 2 属于链下 DA 方案(ZK Rollup 和 OP Rollup 在以太坊 Layer 1 上以 CALLDATA 的形式存储数据)。两种方案目前仍在竞争中,尚未有一方明显胜出,不过这正好给我们思考当前问题的解法,提供了正反两方面的参考案例。

无法照搬 Web2 方案

在 Web2 领域,当数据库读性能不足时,我们会在数据库前面加一层缓存层(Cache),或者通过增加多个数据库从库来提升数据读的能力。

典型 Web2 服务架构。来源:https://smartbuilds.io/scaling-web3-social-media-blockchain-cache-layer/

但在区块链领域,这些方案目前看来都行不通,一方面服务提供模式从中心化变成了去中心化,另一方面数据存储由结构化存储变成了链式存储。这些基础模式的变化,导致其上的解决方案也必须相应的变化,只是目前尚未找到针对区块链的“缓存”或“从库”方案。

也有参考 Web2 缓存方案的 DApp 案例,但明显不具有普适性。如果站在 MUD 框架的视角,则该方案的整合引入了更多中心化因素,因此也不是很理想。

融合了缓存方案的DApp架构。来源:https://smartbuilds.io/scaling-web3-social-media-blockchain-cache-layer/

Indexer 是最不坏的方案

就 MUD 本身来说,已经是应用链领域很大的进步,因为它同时解决了三个问题:

1> 智能合约中数据与逻辑耦合,导致逻辑升级困难的问题

2> 链和客户端之间缺乏数据同步机制,导致数据状态不一致的问题

3> 区块链缺乏统一的访问控制机制,导致了一定程度的重复劳动和互操作性障碍。

MUD 解决数据读取问题的思路是,在客户端放置一个只关心当前合约数据的“全节点”,MUD 官方称其为“Namespaced Full-node”,也即我们所说的 Indexer。

来源:https://youtu.be/tLGdup5wmck?si=ykgQ4qwut4VLgimF

这个方案在应用链领域来说,属于从无到有,显然是一大进步。虽然谈不上完美,但已经是不错的开始,后人可以站在巨人的肩膀,探索更优的方案。总的来说,MUD Indexer 是最不坏的方案,但我们还需要更好的