为什么分片是了不起的:揭开分片技术特性的神秘面纱 | Vitalik Buterin

  • Unitimes
  • 更新于 2021-04-12 11:05
  • 阅读 3614

分片 (Sharding) 是以太坊扩容的未来,它将是帮助以太坊生态系统支持每秒成千上万笔交易的关键,并允许世界上大部分人以负担得起的成本定期地使用该平台。

撰文:Vitalik Buterin

编辑:南风

特别感谢 Dankrad Feist 和 Aditya Asgaonkar 的校审。

分片 (Sharding) 是以太坊扩容的未来,它将是帮助以太坊生态系统支持每秒成千上万笔交易的关键,并允许世界上大部分人以负担得起的成本定期地使用该平台。然而,分片也是以太坊生态系统和更广泛的区块链生态系统中更容易被误解的概念之一。它指的是一组非常具体的具有特定属性的想法,但它经常与那些具有非常不同且通常更弱的安全性属性的技术混为一谈。本文的目的是解释分片提供了哪些特定的属性,它与其他分片技术的区别,以及分片系统为了实现这些属性需要做出哪些权衡。

*上图:*以太坊分片版本的一个描述。初始结构图来自 Hsiao-wei Wang,由Quantstamp设计。

扩容的三难困境

描述分片的最佳方式,可以从形成和激发分片解决方案的问题开始:扩容的三难困境

扩容的三难困境指出,区块链尝试拥有三个属性,如果你坚持使用“简单”的技术,你只能获得这三个属性中的两个。这三个属性分别是:

  • 可扩展性:整个区块链能够处理的事务 (transactions,也译作“交易”) 比单个普通节点 (比如一台消费型笔记本电脑) 能够验证的事务要多。
  • 去中心化:区块链可以在不依赖于一小群大型中心化参与者的情况下运行。这通常理解为不应该对一组你无法通过一台消费级电脑加入其中的节点有任何信任 (或者甚至不应该假设多数节点将保持诚实);
  • 安全性:区块链能够抵抗大量试图攻击它的参与节点。

现在我们来看看三种“简单的解决方案”,这些解决方案只获得了上述三个属性中的两个:

  • 传统区块链——包括比特币、PoS/分片之前的以太坊、莱特币和其他类似的区块链。这些区块链依赖于每个参与者运行一个完整的节点来验证每个事务 (交易),因此这些区块链具有去中心化和安全性,但没有可扩展性。
  • 高 TPS 的区块链——包括 DPoS 家族,但也有许多其他的链。这些区块链依赖于少量的节点 (通常是10-100个) 来维持节点之间的共识,用户不得不信任这些节点中的大多数。这种链是可扩展的和安全的 (基于上面的定义),但不是去中心化的。
  • 多链生态系统——这指的是“横向扩展”的一般概念,即让不同的应用运行在不同的链上,并使用跨链通信协议使它们之间进行通信。这种生态系统是去中心化和可扩展的,但不安全,因为攻击者只需要控制了这些链中的其中一条链的多数共识节点 (通常是整个生态系统的

分片是一种让你拥有所有这三大属性的技术。一条使用分片技术的区块链是:

  • 可扩展的:它能够处理比单个节点多得多的事务;
  • 去中心化的:它能够完全依靠消费型笔记本电脑来生存下去,而不依赖任何“超级节点”;
  • 安全的:攻击者无法用少量的资源攻击系统的一小部分;而只能试图控制和攻击整条链。

本文的其余部分将描述分片区块链如何做到这一点。

通过随机抽样进行分片

最容易理解的分片版本是通过随机抽样 (random sampling) 进行分片。与我们正在以太坊 (2.0) 生态系统中构建的分片形式相比,通过随机抽样进行分片具有更弱的信任属性,但它使用的技术更简单。

其核心理念如下:假设有一条拥有很大数量 (比如 10000 名) 验证者的 PoS 区块链,并且该链有大量 (比如100个) 区块需要验证。没有任何一台计算机有能力在下一组区块到来之前,将所有这些区块进行验证。

因此,我们所做的就是随机地划分验证工作。我们随机洗牌 (打乱) 验证者列表,然后将经打乱的验证者列表中的前 100 名验证者分配去验证第一个区块,将列表中接下来的 100 名验证者分配去验证第二个区块,以此类推。这样的一组经随机选中的验证者 (被分配去验证某个区块或执行一些其它任务),我们称之为一个委员会 (committee)。见下方示例图:

当一名验证者验证某个区块时,该验证者会发布一个签名 (signature) 来证明自己验证了该区块。其它验证者现在仅需验证 10000 个签名,而不是验证 100 个完整的区块 -- 这样一来,工作量就小得多了,尤其是通过使用 BLS 签名聚合 (注:也即将多个签名聚合成一个签名)。每个区块不是通过同一个 P2P 网络进行广播,而是在不同的子网络中广播,且节点只需加入与它们负责的区块 (或因其它原因感兴趣的区块) 相对应的子网络。

想象一下,如果每个节点的计算能力增加 2 倍将会发生什么。由于每个节点现在能够安全地验证多 2 倍的签名,你 (指区块链) 可以减少最低 Staking 质押金,从而支持多 2 倍的验证者数量,这样你就可以有 200 个委员会,而不是 100 个。因此,你在每个 slot 可以验证 200 个区块,而不是只有 100 个。此外,每个单独的区块还可以大 2 倍。这样以来,你 (在每个 slot) 就验证了多 2 倍的的区块,且每个区块的大小还增加了 2 倍,也即是说,整个区块链的容量增加了 4 倍。

我们可以引入一些数学术语来讨论这是怎么回事。借助大O表示法,我们用“O(C)”表示单个节点的计算能力。传统的区块链可以处理大小为 O(C) 的区块;而一条采用如上所述的分片技术的区块链可以并行处理 O(C) 区块 (请记住,每个节点间接验证每个区块的成本是 O(1),因为每个节点仅需验证固定数量的签名),且每个区块有着 O(C) 的容量,因此整个分片区块链的总容量将是O(C**2)这就是为何我们将这种类型的分片称之为二次分片** (quadratic sharding),且这种效果是我们认为从长远来看,分片是扩展区块链的最佳方式的关键原因。

常见问题:分成100个委员会和分成100条独立的链有什么不同?

有两个关键区别:

  1. 随机抽样防止了攻击者将他们的能力集中在某一个分片上。在一个有着 100 条链的多链生态系统中,攻击者只需要控制 stake (质押金) 总量的 约0.5% 就可以造成破坏:他可以集中对单条链发起 51% 攻击;相比之下,在一个分片区块链系统中,攻击者必须控制近 30-40% 的 stake 总量才可能做出同样的事情 (换句话说,整条链有着共享的安全性)。当然,攻击者可以等待好运气,即通过随机的方式让他获得单个分片的 51% 的控制权,即使该攻击者所控制的 stake 数量不到整条链的 stake 总量的 50%。如果攻击者的质押量少于整条链质押总量的 30%,那上述这种情况几乎不可能发生。
  2. 紧密耦合:即便某个分片出现了一个非法区块 (bad block),整条区块链可以通过重组来抛弃该区块。在实施分片的区块链中,存在一个社会契约(在本文档后面的章节中,我们将描述一些从技术上强制执行该契约的方法),也即,即便某个分片中存在一个非法区块,那整条区块链也是不会接受的,应该在发现该非法区块时立即将之驱逐出去。从区块链内的应用程序的角度来说,这确保了完美的安全性:合约 A 可以信赖合约 B,因为如果合约 B 由于链上发生攻击而出现不当行为,那么整个历史记录将被逆转恢复,包括由于合约 B 中的故障导致合约 A 中发生的不当交易。

这两个差异确保分片为应用程序创建了这样一个环境,该环境保留着一个单链环境所拥有的关键安全属性,而这是多链生态系统根本无法做到的。

使用更好的安全模型改进分片

比特币圈中一个常见的说法,也是我完全同意的一个说法是,像比特币 (或以太坊) 这样的区块链并不完全依赖于「诚实大多数的假设」。如果对这样的区块链发起 51% 的攻击,那么攻击者可以做出一些令人讨厌的事情,比如逆转或审查交易,但他们不能添加无效的交易。而且,即使它们确实逆转或审查交易,运行常规节点的用户也可以很容易地检测到这种行为,因此,如果社区希望通过一个削弱攻击者算力的分叉来协调解决该攻击,他们可以很快做到这一点

缺乏这种额外的安全性正是那些更加中心化的高 TPS 区块链的一个关键弱点。这样的区块链没有,也不可能会有普通用户运行节点的文化,因此其主要节点和生态参与者可以更容易地聚集起来,强制执行一项社区非常厌恶的协议更改。更糟糕的是,用户的节点将默认接受这种更改。一段时间后,用户会注意到这种更改,但到那时,这种强制的更改已经是一个既成事实:用户将承担拒绝这项更改带来的协调负担,他们将不得不做出痛苦的决定,逆转每个人都认为已经被敲定的一天或更多的活动。

理想情况是,我们希望有一种分片形式,避免 51% 的信任假设,并保留传统区块链通过全网验证获得的强大安全保障。这正是我们在过去几年里所做的研究。

1. 可扩展的计算验证

我们可以把防 51% 攻击的、具有可扩展性的验证分为两种情况:

  • 验证计算:检查某些计算是被否正确地完成,这假设你拥有计算的所有输入 (inputs);
  • 验证数据的可用性:检查计算本身的输入是否以某种形式被存储,当你真的需要,你可以下载这些输入;应该在无需实际下载整个输入的情况下执行此检查 (因为数据可能太大,无法下载每个区块)。

验证区块链中的某个区块,涉及对计算数据可用性同时**进行检查:你需要确信,1) 该区块中包含的交易是有效的,且该区块新的状态根哈希是执行这些交易的正确结果;但你也需要确信,2) 有足够多来自该区块的数据已经被发布,这样下载该数据的用户就可以对该状态进行计算,并继续处理这条链。这第二部分是一个非常微妙但却很重要的概念,我们称之为[数据可用性问题**](https://github.com/ethereum/research/wiki/A-note-on-data-availability-and-erasure-coding),稍后再详细介绍

首先,以可扩展的方式验证计算是相对容易实现;有两类技术:欺诈证明 (fraud proofs) 和 ZK-SNARKs(简洁的非交互式零知识证明)。

*欺诈证明是一种具有可扩展计算*验证方法

这两种技术可以简单地描述如下:

  • 欺诈证明 (fraud proofs) 是这样一个系统,即如果要接受某个计算结果,你需要一个质押了一笔存款 (deposit) 的人签署一条这样的消息:“我证明,如果你对输入 X 执行计算 C,你会得到输出 Y”。在默认情况下,你会信任这些消息,但是你也会留给其他质押了存款的人一个发起挑战的机会 (即提交一条签名消息,表示“我不同意,输出应该是Z”)。只有当存在挑战时,所有节点才会运行计算。双方中的任何一方错了,将失去自己的存款,且所有依赖于该计算结果的计算都将被重新计算。
  • ZK-SNARKs 是一种加密证明,它直接证明了“对输入 X 执行计算 C,将得到输出 Y”的说法。这个证明在密码学上是“合理的”:如果 C(X) 等于 Y,在计算上无法对此进行有效证明。该证明也可以快速得以验证,即便运行 C 计算本身需要大量的时间。关于 ZK-SNARKs 的更多数学细节,请参阅这篇文章:https://vitalik.ca/general/2021/01/26/snarks.html

基于欺诈证明的计算是可扩展的,因为“在正常情况下”,你可以通过验证单个签名来代替运行复杂的计算。也有例外的情况,即由于有人发起了挑战,你必须在链上验证计算,但这种例外情况非常罕见,因为触发这种情况的成本非常昂贵 (最初的证明者或者发起挑战者,其中一方将损失一大笔存款)。

ZK-SNAKRs 在概念上更简单 -- 它们只是用更便宜的证明验证代替了计算 -- 但其工作原理背后的数学运算要复杂得多。

当前,有一类半扩展 (semi-scalable) 的 Layer 2 系统,它仅仅以可扩展的方式 (即使用欺诈证明或者 ZK-SNARKs) 验证计算同时仍然要求每个节点对所有数据进行验证。通过使用一套压缩技巧可以非常有效地实现这一点。这就是 rollups

2. 可扩展的数据可用性验证要更加困难

欺诈证明不能用于验证数据的可用性。计算的欺诈证明依赖于这样一个事实,即计算的输入在最初的证明被提交的那一刻就发布在链上,因此如果有人发起挑战,那么挑战的执行与最初证明的执行是完全发生在同一个“环境”中的。但在检查数据可用性时,你不能这么做,因为问题恰恰在于,有太多的数据需要检查,不能全部发布到链上。因此,针对数据可用性的欺诈证明方案遇到了一个关键问题:某人可以声称“数据 X 是可用的”而不公布该数据,等待被挑战,然后才会在链上公布数据 X,从而使发起挑战者被网络上的其它人视为不正确。

这在渔夫的困境 中到了进一步的阐述:

「渔夫的困境」的核心概念是存在两个“世界”:一个世界中,V1 是个邪恶的数据发布者,V2 是个诚实的挑战者;另一个世界中,V1 是个诚实的数据发布者,V2 是个邪恶的挑战者。对于当时没有试图下载这一特定数据的人来说,是无法对此进行区分的。当然,在一个可扩展的去中心化区块链中,每个单独的节点可以只下载一小部分数据,因此,除了存在分歧这一事实之外,只有一小部分节点可以看到发生了什么。

由于不可能区分谁对谁错,因此不可能有一个有效的数据可用性欺诈证明方案。

常见问题:如果某些数据不可用怎么办?通过 ZK-SNARK,你就可以确定一切都是有效的,这还不够吗?

不幸的是,仅仅只有有效性是不足以确保正确运行区块链的。这是因为,如果区块链是有效的,但是所有的数据都是不可用的,那么用户就没有办法更新他们所需的数据来生成用于验证未来区块的有效性的证明。如果一个攻击者生成了一个有效但不可用的区块,然后该攻击者又消失了,那么他就可以有效地暂停这条链。某个人可能会劫持某个特定用户的账户数据,直到该用户支付赎金,所以这个问题并不纯粹是区块链活性问题。

有一些强有力的信息-理论观点认为这个问题十分重大,没有什么明智的方式来规避。详情请参阅这篇文章:

https://eprint.iacr.org/2009/612.pdf

那么,如何在不下载的情况下检查 1MB 数据是否可用呢?这听起来不可能!

其中的关键是一种称为数据可用性抽样 (data availability sampling) 的技术。数据可用性抽样的工作方式如下:

  1. 使用一种叫做纠删码 (erasure coding) 的工具,将一段包含 N 个数据块的数据扩展成一段包含 2N 个数据块的数据,这样,其中任意 N 个数据块都可以恢复整个数据。
  2. 为了检查数据的可用性,无需下载整个数据,用户只是简单地在该区块中随机选择一个固定数量的位置 (比如 30 个位置),且只有当用户在所有他们选择的位置成功地找到这些数据块时,才会接受该区块。

纠删码将“检查100%可用性”(即检查每一段数据都是可用的) 这一问题转变成了“检查50%的可用性”(即至少有一半的数据是可用的)。随机抽样解决了 50% 的可用性问题。如果不到 50% 的数据是可用的,那么至少有一次检查几乎肯定会失败;如果至少 50% 的数据是可用的,同时某些节点可能无法识别出某个区块是可用的,那么只需要一个诚实节点运行纠删码重构过程,就能将该区块剩余的 50% 数据恢复。因此,不需要下载 1 MB 来检查 1MB 区块的可用性,你只需要下载几 KB这使得对每个区块进行数据可用性检查是可行的。可以通过这篇文章来了解这种检查如何在 P2P 子网络中有效地实现:

https://hackmd.io/@vbuterin/sharding_proposal#Blob-publication-process

可以使用 ZK-SNARK 来验证对一段数据进行的纠删码是否正确地被执行,然后可以使用 Merkle 分支来验证单个数据块。或者,你可以使用多项式承诺 (例如 Kate (又名KZG) 承诺),本质上是在一个简单的组件中进行纠删码、证明单个元素和正确性验证——这就是以太坊分片所使用的。

概述:我们又是如何确保一切都是正确的?

假设有 100 个区块,你想要在不依赖委员会的情况下有效地验证所有区块的正确性。我们需要做以下工作:

  • 每个客户端对每个区块进行数据可用性采样以验证每个区块中的数据的可用性,同时客户端对每个区块只下载几 KB,即使整个区块的大小有 1MB 或更大。只有当某个区块的所有数据可用性挑战都被正确地相应时,客户端才会接受该区块。
  • 既然我们已经验证了数据的可用性,那么验证正确性就变得更容易了。有两种方法:
  • 我们可以使用欺诈证明:一些质押了存款的参与者可以对每个区块的正确性进行签名。而其它节点,被称为挑战者 (或者渔夫),会随机检查并尝试完整地处理区块。由于我们已经检查了数据的可用性,所以总是可以下载数据并完整地处理任何特定的区块。如果他们 (挑战者) 发现一个无效的区块,他们会发布一个每个人都会验证的挑战。如果这个区块被证明是无效的,那么这个区块以及依赖于它的所有后续区块都需要重新计算。
  • 我们也可以使用 ZK-SNARKs。每个区块都将附带一个 ZK-SNARK 来证明其正确性。
  • 在上述任何一种情况下,每个客户端只需要对每个区块做少量的验证工作,无论区块有多大。在使用欺诈证明的情况下,偶尔需要在链上完整地验证区块,但这应该是非常罕见的,因为触发哪怕一个挑战的成本都是非常昂贵的。

就是这样!就以太坊分片而言,近期计划是将分片区块仅用于数据;也就是说,分片纯粹是一个“数据可用性引擎”,而 Layer 2 Rollups 将使用这个安全的数据空间,同时使用欺诈证明或 ZK-SNARKs,来实现高吞吐量的安全交易处理能力。但是,完全可以创建这样一个内置系统来添加“本地”高吞吐量执行。

分片系统的关键属性是什么?有哪些权衡?

分片的关键目标是尽可能复制传统 (非分片) 区块链最重要的安全属性,但不需要每个节点亲自验证每笔交易。

在传统的区块链中:

  • 无效区块无法通过,因为验证节点会发现它们无效并忽略它们。
  • 不可用的区块无法通过,因为验证节点无法下载它们并忽略它们。

在一个具有高级安全特征的分片区块链中:

  • 无效区块无法通过,因为:
  • 欺诈证明会迅速抓住无效区块,并通知整个网络该区块的无效性,并严惩该区块的创造者;或者
  • ZK-SNARK 证明正确性,并且你不能为一个无效区块创建一个有效的 ZK-SNARK 证明。
  • 不可用的区块无法通过,因为:
  • 如果一个区块的数据只有不到 50% 可用,那么对于每个客户端来说,至少会有一个数据可用性抽样检查会失败,从而导致客户端拒绝该区块。
  • 如果一个区块至少有 50% 的数据可用,那么实际上整个区块都是可用的,因为只需要一个诚实的节点就可以重构该区块的其余部分。

没有实施分片的传统高 TPS 区块链 (比如 DPoS 链) 无法提供这些保证;多链生态系统也没有办法避免攻击者选择其中一条链作为攻击目标并轻易控制该条链的问题 (这些链可能会共享安全性,但如果这方面做不好,整个多链生态系统将实际上变成一条传统的高 TPS 的链,并具有后者的所有缺点;如果在共享安全性方面做好了,这个多链生态就只是成了上述分片技术的一个更复杂的实现而已)。

侧链 (sidechains) 高度依赖于具体实现,但它们通常容易受到传统高 TPS 区块链的弱点的影响 (如果它们共享矿工/验证者),或受到多链生态系统的弱点的影响 (如果它们不共享矿工/验证者)。采用分片的区块链 (注:译者在下文中简称为“分片区块链”或“分片系统”)能够避免这些问题。

然而,分片系统的盔甲上也有一些裂缝。尤其是:

  • 依赖于委员会的分片区块链容易受到**自适应敌手 (adaptive adversaries) 的攻击**,而且问责制也较弱。也就是说,如果对手有能力实时入侵 (或关闭) 他们选择的任意节点,那么他们只需要攻击少量节点就可以破坏单个委员会。此外,如果敌人 (无论是一名自适应的敌手还是一名控制有 50% 总质押金的攻击者) 打破了某个委员会,只有他们的少数一些节点 (即攻击者在该委员会中控制的少数节点) 会被公开地被证实参与了此次攻击,因此只有少数的质押金会被惩罚。这也是为什么数据可用性抽样与欺诈证明或 ZK-SNARKs 结合起来是随机抽样技术的重要补充的另一个关键原因。
  • 只有当有足够数量的客户端在线,它们共同发出足够的数据可用性采样请求时,数据可用性抽样才安全。在实践中,这意味着必须有几百个客户端在线 (并且这个数字随着系统容量与单个节点容量的比率的增加而增加)。这是一个 few-of-N 信任模型——通常是相当可信的,但肯定没有非分片区块链中节点对数据可用性无需信任那么健壮。
  • 如果分片区块链依赖于欺诈证明,那么它依赖于及时性假设;如果网络太慢,节点可能会在用于证明某个区块不正当的欺诈证明出现之前接受某个区块是被敲定了。幸运的是,如果你严格遵循一旦发现无效区块就逆转所有无效区块的规则,那么这个阈值是一个用户设置的参数:每个用户选择他们可以等待最终敲定的时间,如果他们不愿等待太长时间,那么就会遭受损失,但更加谨慎的用户是安全的。即便如此,这还是削弱了用户体验。
  • 需要传送的原始数据数量要大得多,这增加了在极端网络条件下发生传输失败的风险。与大量数据相比,少量数据更容易发送 (如果强大的政府试图审查这条链,也更容易安全地隐藏数据)。区块浏览器需要存储更多的数据,如果它们想要支持整条链的话。
  • 分片区块链依赖于分片 P2P 网络,每个单独的 P2P“子网络”(即分片链) 更容易受到攻击,因为它有更少的节点用于数据可用性抽样的子网络模型 可以缓解这种情况,因为子网络之间存在一些冗余,但仍然存在风险。

以上这些都是合理的担忧,尽管在我们看来,允许更多的应用运行在区块链上,而不是通过中心化的 Layer 2 服务运行,是更为令人担忧的问题。话虽如此,这些担忧,尤其是后两个问题,实际上是限制分片区块链吞吐量超过某个点的真正因素。二次分片的二次性是有限制的。

顺便说一句,如果分片区块链的吞吐量变得太高,那么它的安全风险会越来越大,这也是为什么扩展到超二次分片的努力在很大程度上被放弃的关键原因;似乎保持二次分片的二次性才是最好的方法。

为何不以中心化的方式进行区块生产,同时对验证进行分片?

人们经常提出的一种分片替代方案是,搭建一条结构类似于中心化的高 TPS 链的区块链,但这条链上面使用数据可用性抽样和分片,以实现对有效性和可用性的验证。

这改进了目前存在的中心化高 TPS 区块链,但仍然比分片系统弱得多。这有几个原因:

  1. 在一个高 TPS 的区块链中,区块生产者更难以监测到审查。发现审查要求:(i) 能够看到每一笔交易,并验证没有这样的交易存在:该交易明显值得被打包,但莫名其妙地未被打包进区块;或者 (ii) 在区块生产者中建立一个 1-of-N 信任模型,并验证没有区块没能进入链中。在一条中心化的高 TPS 链中,(i) 是不可能的,(ii) 更难以实现,因为较少的节点总数甚至会使 1-of-N 信任模型更容易崩溃,而且,如果区块链的出块时间对于 DAS 来说太快了 (就像大多数中心化的高 TPS 链一样),就很难证明某个节点生产的区块不是因为发布速度太慢而被拒绝。
  2. 如果大多数区块生产者和生态系统成员试图强行通过一项不受社区欢迎的协议变更,虽然用户的客户端肯定会检测到该变更,但对于社区来说,反抗和通过分叉来拒绝该变更是非常困难的,因为他们需要启动一组新的非常昂贵的高吞吐量节点来维护一条保持旧规则的链。
  3. 中心化的基础设施更容易受到外部行为者的审查。生产区块的节点有着高吞吐量,这使得它们非常容易被发现,并更容易被关闭。在政治和逻辑上,审查专门的高性能计算也比审查个人用户的笔记本电脑更容易。
  4. 将高性能计算转移到中心化云服务的压力更大,增加了整条链将在 1-3 家公司的云服务内运行的风险,因此会增加由于许多区块生产者同时出现故障而导致整条链崩溃的风险。而有着在用户自己的硬件上运行验证者的文化的分片区块链不容易受到这种影响。

适当进行分片的系统作为基础层更好。给定一个实施分片的基础层,你总是可以通过构建一个 Rollup 来在其上创建一个中心化的生产系统。但是,如果你有一个依赖于中心化的区块生产的基础层,那你就无法在上面构建一个更加去中心化的 Layer 2。

原文链接:

https://vitalik.ca/general/2021/04/07/sharding.html

本文首发于Unitimes App

-END-

【发布文章仅为传播更有价值的信息,文章版权归原作者所有,其内容与观点不代表Unitimes立场。本微信平台出现的图片均在互联网收集而来,版权归版权所有人所有,若版权者认为其作品不宜供大家浏览或不应无偿使用,请添加微信unitimes2018联系我们,本平台将立即更正。】

点赞 0
收藏 1
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Unitimes
Unitimes
江湖只有他的大名,没有他的介绍。