MongoDB分片的实例实施,以及与Etehreum(以太坊)分片的比较
0. 目录
-
首先,
- 首先,
-
- Sharding(分片)的概述;
-
- MongoDB的Sharding(分片)操作;
-
- MongoDB中Sharding(分片)的示例实现;
-
- 在进行MongoDB的Sharding(分片)时需要考虑的事项;
- 6. 以Ethereum(以太坊)为例的区块链Sharding(分片)技术。
首先(关于MongoDB中的Sharding(分片))分片(Sharding)是一种技术,被关注为扩展以太坊等区块链的方式,但它本质上是一种将常规数据库分散到多个服务器的功能。采用NoSQL结构的MongoDB数据库早在开发初期就被设计为支持分片(Sharding)。它旨在实现数据和处理的分散,而无需单一故障点。
为了讨论区块链技术中使用的分片技术Sharding,本文将使用MongoDB来探讨数据分散中的Sharding。我们将通过查看实际示例并执行样本来深入理解Sharding等复杂的机制,并按照以下顺序进行讨论。
-
- Sharding(シャーディング)とは何か。なぜ重要となるのか。
-
- MongoDBではどのように実装されているのか。
- MongoDBにおけるSharding(シャーディング)のサンプル実装
2. Sharding(分片)的概述在各种分布式系统中,如区块链等,经常会出现备份的情况,但每个备份中通常都复制了其他备份的数据。在比特币和以太坊等区块链网络中,参与作为矿工的所有节点(备份)实际上都持有并处理整个区块链网络的全部数据。然而,随着数据大小的增加以及对更频繁和更大量的读写吞吐量的需求,处理能力会达到极限。对于这样的问题,将数据库和网络分散到多个节点集是一个解决方案。具体来说,进行分片(Sharding)的优点包括以下几点。
-
CPUやI/O負荷を分散させる
- CPUやI/O負荷を分散させる
-
- メモリやストレージの分散によるコストパフォーマンスの向上。必要に応じた容量の追加も可能。
- (メモリ64GB一枚より、4GB16枚の方が安い。)
Mongodb是一种引入了此类机制的NOSQL数据库,从开发初期就已经旨在实现Sharding(分片)。特别是在现有机制中,Sharding(分片)不是自动执行而是手动执行的,通过自动化这一过程,更多的工程师能够实现Sharding(分片),这是MongoDB的一大特点。
3. MongoDB的Sharding(分片)操作
3-1. 用语说明3-1. 用语解释
3-1. 以用语说明
3-1. 解释用语
分片()
是存储分散数据集的mongod进程的集合体。
mongos服务器是Sharding路由过程中的进程。mongos进程通过将所有读写请求分配到适当的Shard上与客户端进行协作。通过mongos,客户端可以看到数据存储具有一致性。mongos服务器本身不存储状态或数据。
配置服务器
mongod进程,用于管理Sharding(分片)的元数据。其职责是确保每个分片组的正确状态被保存。元数据包括全局分片组的配置、每个数据库和集合的位置、特定范围数据的存储位置以及分片数据迁移历史的变更日志。
此外,这些元数据在确保分片正常运行方面扮演着核心角色,每次启动mongos进程时,它都会从配置服务器检索元数据的副本。
建议使用多个配置服务器来配置,以避免成为单一故障点。在准备多个配置服务器时,需要非常强大的一致性保障,因此会使用2PC(Two-Phase Commit)来进行同步。(详细信息请参考”在构建区块链的分布式系统中的容错性”一文。)
集合数据比数据库更细粒度的数据组。在区块链中对应于区块。
分布式数据库的键范围,该键范围用于分散数据。 MongoDB通过自动调整分片键来平衡数据的不均衡。
块(chunk)是分散数据的单位。一组交易。
3-2. 由于Shard Key的范围,数据被分散。为了更清楚地理解Sharding(分片)是通过哪些实际操作来分散数据的,让我们以例子来看一下。
在MongoDB中,通过指定分片键可以确定每个服务器存储的数据范围。服务器之间不会存在重复数据,一个数据只会存储在由分片键范围确定的一个服务器上。例如,考虑一个具有以下集合(数据组)的电子表格管理应用程序。
{
_id: ObjectID ("34x78rfcnNne3792c")
filename:"spreadsheet-1",
updated_at: ISODate("・・・"),
username: "adam",
data: "raw document data"
}
如果用户数量增加,且在MongoDB中需要Sharding(分片)时,可以从上述集合中选择一个字段作为分片键声明。在这种情况下,选择username和id作为组合分片键可能是合适的。连续的数据在分片键的范围内被分成了以下的块。每个块都有起始值和结束值,并且每个块都被分配给了各个分片。
開始値終了値シャード_∞adamBadamdaytonAdaytonharrisBharrsinorrisAnorris∞C尽管每个块表示一个连续值的范围,但每个块都可以分配到任何分片中,这是它的特点。而且,块是逻辑上而不是物理上的存在。换句话说,以上面的例子为例,以harris开头以norris结尾的块在分片A中只表示所有文档都存储在这个分片键范围内,而不关注其顺序或连续性。
在Sharding(分片)中,对块的分割和迁移进行操作。对于Chunk的分割和迁移,在Sharding(分片)中扮演着核心机制的角色。
在MongoDB的Sharding(分片)中,当一个chunk的大小超过了预设的阈值时,它会自动分割。chunk的默认最大大小是64MB或者100,000个文档,当其中一个条件被超过时,chunk将被分割。
在设计分片(Sharding)系统时,最困难的部分之一是确保数据在分割后始终保持均衡。MongoDB通过在分片间随时移动数据块(chunk)来实现平衡。这个过程被称为迁移,由名为负载均衡器(Balancer)的软件进程来管理。负载均衡器会追踪每个分片上的数据块数量,当差距达到一定阈值时,会将最多数据块的分片中的数据迁移到数据块最少的分片中。
3-4. MongoDB上的分片(Sharding)执行过程总结迄今为止,我们已经解释了在MongoDB上如何进行Sharding(分片)的过程。简要总结如下。
コレクションというデータ群の生成
フィールどの中からシャードキーを定義してさらに小さなまとまりであるチャンクに分割する
データ量が増える程チャンクが細かく分割されていき、自動で各シャードに振り分けられる
シャード間のチャンク数に偏りが生じた場合、バランサーによってチャンクの移行が行われ均等になる
以上就是Sharding(分片)的大致流程。
在MongoDB中,Sharding(分片)的示例实现。本章将通过在MongoDB上运行示例,并实施Sharding来更详细地解释Sharding。总体而言,在MongoDB上进行Sharding的步骤如下:
1. 必要なmongodを全て用意し起動する
2. 必要なconfigサーバーを全て用意し起動する
3. mongosを用意し起動する
4. シャードクラスタに各シャードを追加する
5. データベースのシャーディングを有効化する
6. シャードキーを定義してコレクションをシャード化する
7. シャード化されたクラスタにデータを書き込む
8. データ量が大きくなれば、自動で細かいチャンクに分割され、各シャードに振り分けられる
9. シャード間のチャンクの数に偏りが生じればバランサーがチャンクを移行させる
接下来,我们将使用Sharding(分片)的示例来了解实际的实现方法。在本次示例中,分片集群的配置如下,按以下方式准备两个分片A和B。
《MongoDB实战(第9章分片)》
在MongoDB上进行分片(Sharding)所需的mongod必须全部准备并启动。
首先,在进行分片(Sharding)时,需要创建两个数据目录集,用于作为分片A和分片B的两个副本集。
$ mkdir /data/rs-a-1
$ mkdir /data/rs-a-2
$ mkdir /data/rs-a-3
$ mkdir /data/rs-b-1
$ mkdir /data/rs-b-2
$ mkdir /data/rs-b-3
如果能创建目录,接下来需要启动用于Sharding(分片)的mongodb。为每个进程准备一个终端窗口,并加上–shardsvr选项来设置它们将被放置在哪个分片上。如果加上–fork选项,还可以在后台运行。
<启动复制集1(shard-a)中的mongod>
$ mongod --shardsvr --replSet shard-a --dbpath /data/rs-a-1 \
--port 30000 --logpath /data/rs-a-1.log
$ mongod --shardsvr --replSet shard-a --dbpath /data/rs-a-2 \
--port 30001 --logpath /data/rs-a-2.log
$ mongod --shardsvr --replSet shard-a --dbpath /data/rs-a-3 \
--port 30002 --logpath /data/rs-a-3.log
<启动复制集2(shard-b)的mongod>
$ mongod --shardsvr --replSet shard-b --dbpath /data/rs-b-1 \
--port 30100 --logpath /data/rs-b-1.log
$ mongod --shardsvr --replSet shard-b --dbpath /data/rs-b-2 \
--port 30101 --logpath /data/rs-b-2.log
$ mongod --shardsvr --replSet shard-b --dbpath /data/rs-b-3 \
--port 30102 --logpath /data/rs-b-3.log
一旦启动后,连接到每个复制集并执行 rs.initiate() 进行初始化,然后逐渐添加节点到节点组中。
$ mongo localhost:30000
> rs.initiate()
在此,等待大约1分钟直到初始节点变为主节点,当显示PRIMARY时,继续添加剩余的节点。
> rs.add("localhost:30001")
> rs.add("localhost:30002", {arbiterOnly: true})
在这种情况下,第三个节点可以是仲裁者。稍后会详细解释,仲裁者是指仅保存副本集的配置数据,因此不需要准备专用服务器。
只需要一个选项,以下是对原文的中文翻译:
如果执行第二个复制集,只需与上述相同即可。可以通过在每个复制集的shell中运行rs.status()命令来确认用于分片的复制集是否处于在线状态以及该分片中mongod成员的状态。
shard-a:PRIMARY> rs.status()
{
"set" : "shard-a",
"date" : ISODate("・・・"),
"myState" : 1,
・・・
"members" : [
{
"_id" : 0,
"name" : "localhost:30000",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
・・・
},
{
"_id" : 1,
"name" : "localhost:30001",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
・・・
・・・
・・・
在MongoDB上实现Sharding所需的所有config服务器都已准备好并启动。如果能够确认MongoDB已经启动,就可以启动所有需要设置Sharding(分片)所需的配置服务器。我们需要为每个配置服务器创建数据目录,并使用–configsvr选项来启动。
$ mkdir /data/config-1
$ mongod --configsvr --replSet config --dbpath /data/config-1 --port 27019 \
--logpath /data/config-1.log
$ mkdir /data/config-2
$ mongod --configsvrr --replSet config --dbpath /data/config-2 --port 27020 \
--logpath /data/config-2.log
$ mkdir /data/config-3
$ mongod --configsvrr --replSet config --dbpath /data/config-3 --port 27021 \
--logpath /data/config-3.log
可以通过从每个shell连接进入来确认config服务器是否已经启动。然后,在这三台机器上建立一个集群。在其中一台机器上使用rs.initiate()命令进行初始化,以创建Primary的Config服务器。
准备并启动在MongoDB上实施Sharding所需的mongos。mongos启动时必须使用–configdb选项。请确保在指定配置服务器地址时不要包含空格。
$ mongos --configdb config/localhost:27019,localhost:27020,localhost:27021 \
--logpath ./data/mongos.log --port 40000
进行Sharding(分片)所需的MongoDB集群配置。由于准备并启动了进行Sharding(シャーディング)所需的所有配置要素,接下来将对集群进行配置以进行Sharding(シャーディング)执行。使用Sharding(シャーディング)的辅助方法,并通过sh对象进行执行。
使用sh.addShard()方法,将之前创建的两个副本集添加到分片中。对于每个副本集,指定两个非仲裁成员的地址。
$ mongo localhost:40000
> sh.addShard("shard-a/localhost:30000,localhost:30001")
{ "shardAdded" : "shard-a", "ok" : 1 }
> sh.addShard("shard-b/localhost:30100,localhost:30101")
{ "shardAdded" : "shard-b", "ok" : 1 }
执行以下命令即可查看注册在设置数据库上的分片信息。
> db.getSiblingDB("config").shards.find()
{ "_id" : "shard-a", "host" : "shard-a/localhost:30000,localhost:30001" }
{ "_id" : "shard-b", "host" : "shard-b/localhost:30100,localhost:30101" }
在MongoDB上启用数据库分片(Sharding)。sh.enableSharding()コマンドによって、MongoDB上のデータベースのSharding(シャーディング)を有効化できる。今回のデータベースはcloud-docsという名前なので、以下のようにSharding(シャーディング)を有効化することができる。
> sh.enableSharding("cloud-docs")
通过执行以下命令,可以确认该数据库是否启用了Sharding(分片)功能。
> db.getSiblingDB("config").databases.find()
{ "_id" : "admin", "partitioned" : false, "primary" : "config" }
{ "_id" : "cloud-docs", "partitioned" : true, "primary" : "shard-a" }
4-6.MongoDB上でSharding(シャーディング)するため、コレクションのシャード化を行う次にコレクションをシャード化する。今回、コレクションの名前はspreadsheetsとなっている。コレクションをシャード化する際には、シャードキーを定義する。今回のMongoDBにおけるSharding(シャーディング)では、チャンクの範囲がわかりやすく、かつデータをうまく分散できることから、複合シャードキーとして{user- name: 1, _id: 1}を用いる。
> sh.shardCollection("cloud-docs.spreadsheets", {username: 1, _id: 1})
同样,可以确认集合是否设置了数据分片化。
> db.getSiblingDB("config").collections.findOne()
{
"_id" : "cloud-docs.spreadsheets",
"lastmod" : ISODate("・・・"),
"dropped" : false,
"key" : {
"username" : 1,
"_id" : 1
},
"unique" : false
}
4-7.MongoDB上でシャード化されたクラスタにデータを書き込んでSharding(シャーディング)を試す
在这次的样本数据库中,我们将使用一个表格来表示数据。每条数据包括五个字段:_id / 文件名 / 更新时间 / 用户名 / 数据。
{
_id: ObjectId("4d6f29c0e4ef0123afdacaeb"),
filename: "sheet-1",
updated_at: new Date(),
username: "Aaron",
data: "RAW DATA"
}
今回は、dataフィールドに5KBを挿入したデータを200個用意する為にRubyのスクリプトを用意した。外部ファイルを二つインストールしてから実行すれば、データがMongoDB内のデータベース内に保存される。
require 'rubygems'
require 'mongo'
require 'faker'
#<start id="write_docs">
@con = Mongo::Client.new(['127.0.0.1:40000'], options = {database: "cloud-docs"})
@col = @con[:spreadsheets]
@data = "abcde" * 1000
def write_user_docs(iterations=0, name_count=200)
iterations.times do |n|
name_count.times do |n|
doc = { :filename => "sheet-#{n}",
:updated_at => Time.now.utc,
:username => Faker::Name.first_name,
:data => @data
}
@col.insert_one(doc)
end
end
end
#<start id="write_docs">
if ARGV.empty? || !(ARGV[0] =~ /^\d+$/)
puts "Usage: load.rb [iterations] [name_count]"
else
iterations = ARGV[0].to_i
if ARGV[1] && ARGV[1] =~ /^\d+$/
name_count = ARGV[1].to_i
else
name_count = 200
end
write_user_docs(iterations, name_count)
end
https://github.com/yodash/mongodb分片
$ gem install mongo
$ gem install faker
$ ruby load.rb 1 200
只需要一个选项, 以下是中文本地化的改述版本:
当实际连接到mongos并检查数据库时,可以确认有200人的数据。
$ mongo localhost:40000
> use cloud-docs
> db.spreadsheets.count()
200
> db.spreadsheets.stats().size
1019496
> db.spreadsheets.findOne({}, {data: 0})
{
"_id" : ObjectId("4d6d6b191d41c8547d0024c2"),
"username" : "Aaron",
"updated_at" : ISODate("・・・"),
"filename" : "sheet-0"
}
4-8.MongoDB的Sharding(分片)Chunk分割与迁移
然后我们进行了800次数据写入,并确认进行了Sharding(分片)以更细分区块的方式分割数据,并将其分配到各个分片中。
$ ruby load.rb 800 200
因为时间会花费很久,所以在这里吃一些Pocky并休息一下吧。按照以下方法,我们可以确认数据写入是否成功。
> use config
> db.chunks.count()
21
> db.chunks.count({"shard": "shard-a"})
11
> db.chunks.count({"shard": "shard-b"})
10
通过执行sh.status()命令,我们可以确认在本次情况中,每个分片分配了10至11个块。同时,我们也可以通过该命令更详细地查看每个分片和块的信息。
此外,我们还可以通过以下方式来确认块的划分和迁移情况。在本例中,我们可以看到块的划分发生了20次,同时通过负载均衡器进行了6次块的迁移。
> db.changelog.count({what: "split"})
20
> db.changelog.find({what: "moveChunk.commit"}).count()
6
在进行MongoDB分片(Sharding)时需要考虑的事项。在这一部分,我们通过实际样例来解释Sharding(分片)的实现。本章将讨论设计Sharding(分片)时需要特别注意的要点。这些讨论适用于在像以太坊等区块链中进行Sharding(分片)的多种情况。
5-1. 在分片(Sharding)中的查询及其类型在Sharding(分片)中,查询可以分成两种类型。一种是仅包含分片键的特定查询,另一种是不包含分片键的全局查询。
请记住,使用分片键来决定每个分片上的每个数据块被分配到哪个分片。换句话说,在第一个查询的情况下,mongos能够快速找到包含查询结果集的数据属于哪个分片,但在第二个查询的情况下,必须访问所有分片来查找数据块。
此外,在执行全局查询时,有时在执行查询之前生成索引会更好。例如,可以通过生成”updated_at: 1″索引来显著提高查询最新文档的效率。
5-2. 在分片(Sharding)中选择分片键的方法一旦决定的分片键无法更改,而且插入和查询(写入和读取)的性能很大程度上取决于是否正确设置分片键。在这里,我们将讨论进行分片时理想的分片键设置方法。
首先,不适当的碎片密钥是指什么样的?
○Sharding(シャーディング)でデータ分散が十分に行われない例えば、タイムスタンプのような単調に増加するフィールドをシャードキーとした場合を考えてみてほしい。シャードキーが連続した範囲がチャンクとして分けられるため、新しい挿入は全て連続した狭い範囲内で行われることになる。
所有这样的插入都被分配给一个chunk,换句话说,就是负载会集中在一个shard上。这无法实现原本Sharding的目的。
分片(Sharding)上的本地性不足。先に述べたように、増加していくシャードキーは明らかな方向性をもつ。一方、完全にランダムなシャードキーは全く方向性をもたない。前者は分散が不十分となるが、後者は分散させすぎることになり、この場合もSharding(シャーディング)における効率を低下させる。これは直感的にはわからないが、ローカリティを考慮すれば理解できる。
ここでのローカリティの概念は、「ある期間内にアクセスされたデータが多くの場合関連性がある」ということを指す。この近接性はつまり、最適化の余地があるということを意味する。完全にランダムにデータのSharding(シャーディング)を行えば、何度も全てのシャードにアクセスする必要が生まれる。しかし、例えばユーザーIDのような一段階粒度の荒いシャードキーを用いた場合、少数もしくは一つのシャードと通信を行うだけで済み、パフォーマンスを大きく向上させることができる。
○Sharding(シャーディング)内のチャンクが十分に分割できないシャードキーが粗過ぎると、チャンクの分割が十分にできない場合がある。例えば、ユーザーIDのみをシャードキーに選ぶと、何百万回ものアクセスを行う一人のユーザーがいるかもしれない。この場合、チャンクが分割できず、シャード間のデータや負荷がアンバランスになってしまう恐れがある。
在Sharding(分片)中,理想的分片键根据以上所述,我们能够理解理想的分片键应该具备哪些特征。最佳的分片键应满足以下特征:
-
挿入がシャード間で均等に分散させられるか
-
CRUD操作においてローカリティの利点を活かせるか
チャンクが分割可能な粒度であるか
これらの条件を満たすシャードキーは、概して二つのフィールドから構成されるもので、一つ目は粗い粒度、二つ目は細かい粒度のフィールドが選択される。今回の例では{username: 1, _id: 1} という複合シャードキーを使ったが、これは、一人のユーザーがどれだけ大量のドキュメントを作成してもチャンクの分割可能性を保証できるような最適なシャードキーであるといえる。
5-3. 在Sharding(分片)上的部署在配置进程的方式也是一个重要的问题。如果要为设置服务器和mongos等所有内容提供独立的机器,那么成本将非常高。然而,通常情况下并不需要这样,只要满足以下最低条件,就可以保持一定的容错性。(有关容错性的详细信息,请参阅“在构成区块链的分布式系统中的容错性”一文。)
-
一つのシャード及びレプリカセットの各メンバーは、それが完全なレプリカなのか、アービターなのかに寄らず、別々のマシンに置かなければならない。
-
レプリケーションを行う全てのレプリカセットのメンバーには、専用のマシンを割り当てる必要がある。
-
レプリカセットのアービターは軽量なので、他のプロセスと共存させても良い。
設定サーバは、マシンを他と共用しても構わない。設定クラスタ中のすべての設定サーバ群は、別々のマシン上になければならない。
例えば、今回のサンプルにおける実装例では、必要なプロセスは9つだったが、以下のように4つのマシンを用意すれば十分である。もし、高い可用性や保守性が求められるようなサービスにおいては、アービターを通常のノードとし、各シャード内に三つのノードを用意することでリカバリが効くようになる。
《MongoDB实战》(第九章 分片)
5-4. 在分片(Sharding)时添加新的分片。新しいシャードを追加する際は、バランサーによって古いシャードからチャンクを移行して新しいシャードにも割り当てることになる。この時、例えばMondoDBにおいてはバランサーによるチャンクの移行は現状一つずつしか行えないため、多大な時間を要する事になる。Sharding(シャーディング)システム全体が異常をきたさないよう、必要な際は早い段階でシャードを追加することが必要となる。
6. Ethereum(イーサリアム)をはじめとしたブロックチェーンのSharding(シャーディング)MongoDB上のSharding(シャーディング)との比較しながら、EthereumのようなブロックチェーンでSharding(シャーディング)を行った場合、どのようになるかを考えていく。
6-1. 分散系统 × 分散系统区块链是一种由多个节点处理交易的分布式系统。而分片也正如之前所述,是将数据库分割成块并将整个系统分散化的技术。换句话说,通过在以太坊等区块链上进行分片,实际上就是将分布式系统分散化的行为。
在之前的文章中,我们提到了在分布式系统中实现一致性的复制、同步以及容错性的重要性,并解释了其中所伴随的复杂性和困难性。要实现分布式系统,需要进行更精密的系统设计。
尤其是在处理像加密货币这样有着重要价值的区块链时,网络破坏如双重支付即使出现一丁点,也是致命的,因此非常需要严格的容错性。
6-2. 在区块链的分片中,切片之间的通信和同步在MongoDB的Sharding(分片)中,我们只需将数据分配到各个分片并保存起来即可。然而,区块链涉及处理账户、交易和智能合约。这些不是独立存在的数据,而是彼此之间有机影响的数据。例如,在智能合约向多个账户进行币的支付时,经常需要跨分片进行交互。
在比特币和以太坊等区块链系统中,为了在分布式系统上进行同步,采用了近似于分布式算法的排他控制和领导者选举算法来达成共识。当在区块链上进行分片(Sharding)时,除了在各分片内进行符合共识算法的同步通信外,还需要在分片之间进行同步通信。这就是所谓的分片间通信问题。在以太坊中,讨论已经朝着通过交换日志信息(receipt)而非状态传输的方式进行分片间通信。
在区块链的分片技术中,单一分片内的去中心化的需求。另外,在MongoDB的Sharding中,只需要注意数据的分配即可。然而,在像以太坊这样的区块链的Sharding中,同时也需要考虑如何分配每个节点。
通常情况下,在区块链中通过双重支付等手段进行篡改,需要PoW时需要达到网络整体计算量的51%的共谋。在大规模网络中,这并不容易,但Sharding(分片)的情况却不同。在一个被分成100个分片的网络中,只需要达到整体计算量的1%即可对分片内的数据进行篡改。
以下是中文的一个选项:
https://medium.com/@icebearhww/ethereum-sharding-and-finality-65248951f649 的内容可以简述如下。
因此,以太坊的设计考虑了节点验证称为“验证器”的交易的随机排列。在Zilliqa中,除了每个纪元都会持续对矿工进行随机排列,还采用了引入PBFT型共识算法的多签名机制,以防止分岔现象发生。
在区块链的Sharding(分片)中,选择适当的分片键和块的分配方式。ブロックチェーンでのSharding(シャーディング)において適切なシャードキーの設定とはどのようなものだろうか。MongoDBでの適切なシャードキーとは、以下のような特徴を持つものであった。
-
挿入がシャード間で均等に分散させられるか
-
CRUD操作においてローカリティの利点を活かせるか
チャンクが分割可能な粒度であるか
在区块链的分片技术(Sharding)中,这些条件也是一样的。但是,由于区块链需要具备高度容错性,因此还需要进一步满足防止网络破坏(如双重支付)的条件。
Zilliqaでは、シャードキーの選択について一つの解を出している。送信者のアドレスに基づいてトランザクションを各シャードに振り分けるとしているのである。この時、単一の送信者によるトランザクションは、常に同じシャード内に振り分けられることになる。これによって、シャード内のコンセンサスが明確に取れていれば、シャード間通信が遅れていても二重支払い問題を防止することができる。
然而,通过这种分片键设置,当一个用户同时执行大量的写入和读取操作时,将会向一个分片发送极端的事务。因此,在MongoDB中,通过设置事务ID和用户名的复合分片键,可以将分块进行划分。然而,如果将一个发送者的事务分散到多个分片中,就会增加双重支付的风险,如前所述。在区块链中,人们普遍认为应该牺牲一些效率,以保持高容错性。
仅需要一种选择,以下是原文的汉语本地化释义:
The text should be fully available in either American or British English, providing the full range of options.
《MongoDB实战》
https://livebook.manning.com/#!/book/mongodb-in-action/chapter-9/1
以太坊维基碎片化(Sharding)
https://github.com/ethereum/wiki/wiki/Sharding-introduction-R&D-compendium
Zilliqa白皮书
https://docs.zilliqa.com/whitepaper.pdf
3-1. 用语说明3-1. 用语解释
3-1. 以用语说明
3-1. 解释用语
分片()
是存储分散数据集的mongod进程的集合体。
mongos服务器是Sharding路由过程中的进程。mongos进程通过将所有读写请求分配到适当的Shard上与客户端进行协作。通过mongos,客户端可以看到数据存储具有一致性。mongos服务器本身不存储状态或数据。
配置服务器
mongod进程,用于管理Sharding(分片)的元数据。其职责是确保每个分片组的正确状态被保存。元数据包括全局分片组的配置、每个数据库和集合的位置、特定范围数据的存储位置以及分片数据迁移历史的变更日志。
此外,这些元数据在确保分片正常运行方面扮演着核心角色,每次启动mongos进程时,它都会从配置服务器检索元数据的副本。
建议使用多个配置服务器来配置,以避免成为单一故障点。在准备多个配置服务器时,需要非常强大的一致性保障,因此会使用2PC(Two-Phase Commit)来进行同步。(详细信息请参考”在构建区块链的分布式系统中的容错性”一文。)
集合数据比数据库更细粒度的数据组。在区块链中对应于区块。
分布式数据库的键范围,该键范围用于分散数据。 MongoDB通过自动调整分片键来平衡数据的不均衡。
块(chunk)是分散数据的单位。一组交易。
3-2. 由于Shard Key的范围,数据被分散。为了更清楚地理解Sharding(分片)是通过哪些实际操作来分散数据的,让我们以例子来看一下。
在MongoDB中,通过指定分片键可以确定每个服务器存储的数据范围。服务器之间不会存在重复数据,一个数据只会存储在由分片键范围确定的一个服务器上。例如,考虑一个具有以下集合(数据组)的电子表格管理应用程序。
{
_id: ObjectID ("34x78rfcnNne3792c")
filename:"spreadsheet-1",
updated_at: ISODate("・・・"),
username: "adam",
data: "raw document data"
}
如果用户数量增加,且在MongoDB中需要Sharding(分片)时,可以从上述集合中选择一个字段作为分片键声明。在这种情况下,选择username和id作为组合分片键可能是合适的。连续的数据在分片键的范围内被分成了以下的块。每个块都有起始值和结束值,并且每个块都被分配给了各个分片。
在Sharding(分片)中,对块的分割和迁移进行操作。对于Chunk的分割和迁移,在Sharding(分片)中扮演着核心机制的角色。
在MongoDB的Sharding(分片)中,当一个chunk的大小超过了预设的阈值时,它会自动分割。chunk的默认最大大小是64MB或者100,000个文档,当其中一个条件被超过时,chunk将被分割。
在设计分片(Sharding)系统时,最困难的部分之一是确保数据在分割后始终保持均衡。MongoDB通过在分片间随时移动数据块(chunk)来实现平衡。这个过程被称为迁移,由名为负载均衡器(Balancer)的软件进程来管理。负载均衡器会追踪每个分片上的数据块数量,当差距达到一定阈值时,会将最多数据块的分片中的数据迁移到数据块最少的分片中。
3-4. MongoDB上的分片(Sharding)执行过程总结迄今为止,我们已经解释了在MongoDB上如何进行Sharding(分片)的过程。简要总结如下。
コレクションというデータ群の生成
フィールどの中からシャードキーを定義してさらに小さなまとまりであるチャンクに分割する
データ量が増える程チャンクが細かく分割されていき、自動で各シャードに振り分けられる
シャード間のチャンク数に偏りが生じた場合、バランサーによってチャンクの移行が行われ均等になる
以上就是Sharding(分片)的大致流程。
在MongoDB中,Sharding(分片)的示例实现。本章将通过在MongoDB上运行示例,并实施Sharding来更详细地解释Sharding。总体而言,在MongoDB上进行Sharding的步骤如下:
1. 必要なmongodを全て用意し起動する
2. 必要なconfigサーバーを全て用意し起動する
3. mongosを用意し起動する
4. シャードクラスタに各シャードを追加する
5. データベースのシャーディングを有効化する
6. シャードキーを定義してコレクションをシャード化する
7. シャード化されたクラスタにデータを書き込む
8. データ量が大きくなれば、自動で細かいチャンクに分割され、各シャードに振り分けられる
9. シャード間のチャンクの数に偏りが生じればバランサーがチャンクを移行させる
1. 必要なmongodを全て用意し起動する
2. 必要なconfigサーバーを全て用意し起動する
3. mongosを用意し起動する
4. シャードクラスタに各シャードを追加する
5. データベースのシャーディングを有効化する
6. シャードキーを定義してコレクションをシャード化する
7. シャード化されたクラスタにデータを書き込む
8. データ量が大きくなれば、自動で細かいチャンクに分割され、各シャードに振り分けられる
9. シャード間のチャンクの数に偏りが生じればバランサーがチャンクを移行させる
接下来,我们将使用Sharding(分片)的示例来了解实际的实现方法。在本次示例中,分片集群的配置如下,按以下方式准备两个分片A和B。
《MongoDB实战(第9章分片)》
在MongoDB上进行分片(Sharding)所需的mongod必须全部准备并启动。
首先,在进行分片(Sharding)时,需要创建两个数据目录集,用于作为分片A和分片B的两个副本集。
$ mkdir /data/rs-a-1
$ mkdir /data/rs-a-2
$ mkdir /data/rs-a-3
$ mkdir /data/rs-b-1
$ mkdir /data/rs-b-2
$ mkdir /data/rs-b-3
$ mkdir /data/rs-a-1
$ mkdir /data/rs-a-2
$ mkdir /data/rs-a-3
$ mkdir /data/rs-b-1
$ mkdir /data/rs-b-2
$ mkdir /data/rs-b-3
如果能创建目录,接下来需要启动用于Sharding(分片)的mongodb。为每个进程准备一个终端窗口,并加上–shardsvr选项来设置它们将被放置在哪个分片上。如果加上–fork选项,还可以在后台运行。
<启动复制集1(shard-a)中的mongod>
$ mongod --shardsvr --replSet shard-a --dbpath /data/rs-a-1 \
--port 30000 --logpath /data/rs-a-1.log
$ mongod --shardsvr --replSet shard-a --dbpath /data/rs-a-2 \
--port 30001 --logpath /data/rs-a-2.log
$ mongod --shardsvr --replSet shard-a --dbpath /data/rs-a-3 \
--port 30002 --logpath /data/rs-a-3.log
<启动复制集2(shard-b)的mongod>
$ mongod --shardsvr --replSet shard-b --dbpath /data/rs-b-1 \
--port 30100 --logpath /data/rs-b-1.log
$ mongod --shardsvr --replSet shard-b --dbpath /data/rs-b-2 \
--port 30101 --logpath /data/rs-b-2.log
$ mongod --shardsvr --replSet shard-b --dbpath /data/rs-b-3 \
--port 30102 --logpath /data/rs-b-3.log
一旦启动后,连接到每个复制集并执行 rs.initiate() 进行初始化,然后逐渐添加节点到节点组中。
$ mongo localhost:30000
> rs.initiate()
在此,等待大约1分钟直到初始节点变为主节点,当显示PRIMARY时,继续添加剩余的节点。
> rs.add("localhost:30001")
> rs.add("localhost:30002", {arbiterOnly: true})
在这种情况下,第三个节点可以是仲裁者。稍后会详细解释,仲裁者是指仅保存副本集的配置数据,因此不需要准备专用服务器。
只需要一个选项,以下是对原文的中文翻译:
如果执行第二个复制集,只需与上述相同即可。可以通过在每个复制集的shell中运行rs.status()命令来确认用于分片的复制集是否处于在线状态以及该分片中mongod成员的状态。
shard-a:PRIMARY> rs.status()
{
"set" : "shard-a",
"date" : ISODate("・・・"),
"myState" : 1,
・・・
"members" : [
{
"_id" : 0,
"name" : "localhost:30000",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
・・・
},
{
"_id" : 1,
"name" : "localhost:30001",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
・・・
・・・
・・・
在MongoDB上实现Sharding所需的所有config服务器都已准备好并启动。如果能够确认MongoDB已经启动,就可以启动所有需要设置Sharding(分片)所需的配置服务器。我们需要为每个配置服务器创建数据目录,并使用–configsvr选项来启动。
$ mkdir /data/config-1
$ mongod --configsvr --replSet config --dbpath /data/config-1 --port 27019 \
--logpath /data/config-1.log
$ mkdir /data/config-2
$ mongod --configsvrr --replSet config --dbpath /data/config-2 --port 27020 \
--logpath /data/config-2.log
$ mkdir /data/config-3
$ mongod --configsvrr --replSet config --dbpath /data/config-3 --port 27021 \
--logpath /data/config-3.log
$ mkdir /data/config-1
$ mongod --configsvr --replSet config --dbpath /data/config-1 --port 27019 \
--logpath /data/config-1.log
$ mkdir /data/config-2
$ mongod --configsvrr --replSet config --dbpath /data/config-2 --port 27020 \
--logpath /data/config-2.log
$ mkdir /data/config-3
$ mongod --configsvrr --replSet config --dbpath /data/config-3 --port 27021 \
--logpath /data/config-3.log
可以通过从每个shell连接进入来确认config服务器是否已经启动。然后,在这三台机器上建立一个集群。在其中一台机器上使用rs.initiate()命令进行初始化,以创建Primary的Config服务器。
准备并启动在MongoDB上实施Sharding所需的mongos。mongos启动时必须使用–configdb选项。请确保在指定配置服务器地址时不要包含空格。
$ mongos --configdb config/localhost:27019,localhost:27020,localhost:27021 \
--logpath ./data/mongos.log --port 40000
进行Sharding(分片)所需的MongoDB集群配置。由于准备并启动了进行Sharding(シャーディング)所需的所有配置要素,接下来将对集群进行配置以进行Sharding(シャーディング)执行。使用Sharding(シャーディング)的辅助方法,并通过sh对象进行执行。
$ mongos --configdb config/localhost:27019,localhost:27020,localhost:27021 \
--logpath ./data/mongos.log --port 40000
使用sh.addShard()方法,将之前创建的两个副本集添加到分片中。对于每个副本集,指定两个非仲裁成员的地址。
$ mongo localhost:40000
> sh.addShard("shard-a/localhost:30000,localhost:30001")
{ "shardAdded" : "shard-a", "ok" : 1 }
> sh.addShard("shard-b/localhost:30100,localhost:30101")
{ "shardAdded" : "shard-b", "ok" : 1 }
执行以下命令即可查看注册在设置数据库上的分片信息。
> db.getSiblingDB("config").shards.find()
{ "_id" : "shard-a", "host" : "shard-a/localhost:30000,localhost:30001" }
{ "_id" : "shard-b", "host" : "shard-b/localhost:30100,localhost:30101" }
在MongoDB上启用数据库分片(Sharding)。sh.enableSharding()コマンドによって、MongoDB上のデータベースのSharding(シャーディング)を有効化できる。今回のデータベースはcloud-docsという名前なので、以下のようにSharding(シャーディング)を有効化することができる。
> sh.enableSharding("cloud-docs")
> sh.enableSharding("cloud-docs")
通过执行以下命令,可以确认该数据库是否启用了Sharding(分片)功能。
> db.getSiblingDB("config").databases.find()
{ "_id" : "admin", "partitioned" : false, "primary" : "config" }
{ "_id" : "cloud-docs", "partitioned" : true, "primary" : "shard-a" }
4-6.MongoDB上でSharding(シャーディング)するため、コレクションのシャード化を行う次にコレクションをシャード化する。今回、コレクションの名前はspreadsheetsとなっている。コレクションをシャード化する際には、シャードキーを定義する。今回のMongoDBにおけるSharding(シャーディング)では、チャンクの範囲がわかりやすく、かつデータをうまく分散できることから、複合シャードキーとして{user- name: 1, _id: 1}を用いる。
> sh.shardCollection("cloud-docs.spreadsheets", {username: 1, _id: 1})
> sh.shardCollection("cloud-docs.spreadsheets", {username: 1, _id: 1})
同样,可以确认集合是否设置了数据分片化。
> db.getSiblingDB("config").collections.findOne()
{
"_id" : "cloud-docs.spreadsheets",
"lastmod" : ISODate("・・・"),
"dropped" : false,
"key" : {
"username" : 1,
"_id" : 1
},
"unique" : false
}
4-7.MongoDB上でシャード化されたクラスタにデータを書き込んでSharding(シャーディング)を試す
在这次的样本数据库中,我们将使用一个表格来表示数据。每条数据包括五个字段:_id / 文件名 / 更新时间 / 用户名 / 数据。
{
_id: ObjectId("4d6f29c0e4ef0123afdacaeb"),
filename: "sheet-1",
updated_at: new Date(),
username: "Aaron",
data: "RAW DATA"
}
{
_id: ObjectId("4d6f29c0e4ef0123afdacaeb"),
filename: "sheet-1",
updated_at: new Date(),
username: "Aaron",
data: "RAW DATA"
}
今回は、dataフィールドに5KBを挿入したデータを200個用意する為にRubyのスクリプトを用意した。外部ファイルを二つインストールしてから実行すれば、データがMongoDB内のデータベース内に保存される。
require 'rubygems'
require 'mongo'
require 'faker'
#<start id="write_docs">
@con = Mongo::Client.new(['127.0.0.1:40000'], options = {database: "cloud-docs"})
@col = @con[:spreadsheets]
@data = "abcde" * 1000
def write_user_docs(iterations=0, name_count=200)
iterations.times do |n|
name_count.times do |n|
doc = { :filename => "sheet-#{n}",
:updated_at => Time.now.utc,
:username => Faker::Name.first_name,
:data => @data
}
@col.insert_one(doc)
end
end
end
#<start id="write_docs">
if ARGV.empty? || !(ARGV[0] =~ /^\d+$/)
puts "Usage: load.rb [iterations] [name_count]"
else
iterations = ARGV[0].to_i
if ARGV[1] && ARGV[1] =~ /^\d+$/
name_count = ARGV[1].to_i
else
name_count = 200
end
write_user_docs(iterations, name_count)
end
https://github.com/yodash/mongodb分片
$ gem install mongo
$ gem install faker
$ ruby load.rb 1 200
只需要一个选项, 以下是中文本地化的改述版本:
当实际连接到mongos并检查数据库时,可以确认有200人的数据。
$ mongo localhost:40000
> use cloud-docs
> db.spreadsheets.count()
200
> db.spreadsheets.stats().size
1019496
> db.spreadsheets.findOne({}, {data: 0})
{
"_id" : ObjectId("4d6d6b191d41c8547d0024c2"),
"username" : "Aaron",
"updated_at" : ISODate("・・・"),
"filename" : "sheet-0"
}
4-8.MongoDB的Sharding(分片)Chunk分割与迁移
然后我们进行了800次数据写入,并确认进行了Sharding(分片)以更细分区块的方式分割数据,并将其分配到各个分片中。
$ ruby load.rb 800 200
$ ruby load.rb 800 200
因为时间会花费很久,所以在这里吃一些Pocky并休息一下吧。按照以下方法,我们可以确认数据写入是否成功。
> use config
> db.chunks.count()
21
> db.chunks.count({"shard": "shard-a"})
11
> db.chunks.count({"shard": "shard-b"})
10
通过执行sh.status()命令,我们可以确认在本次情况中,每个分片分配了10至11个块。同时,我们也可以通过该命令更详细地查看每个分片和块的信息。
此外,我们还可以通过以下方式来确认块的划分和迁移情况。在本例中,我们可以看到块的划分发生了20次,同时通过负载均衡器进行了6次块的迁移。
> db.changelog.count({what: "split"})
20
> db.changelog.find({what: "moveChunk.commit"}).count()
6
在进行MongoDB分片(Sharding)时需要考虑的事项。在这一部分,我们通过实际样例来解释Sharding(分片)的实现。本章将讨论设计Sharding(分片)时需要特别注意的要点。这些讨论适用于在像以太坊等区块链中进行Sharding(分片)的多种情况。
5-1. 在分片(Sharding)中的查询及其类型在Sharding(分片)中,查询可以分成两种类型。一种是仅包含分片键的特定查询,另一种是不包含分片键的全局查询。
请记住,使用分片键来决定每个分片上的每个数据块被分配到哪个分片。换句话说,在第一个查询的情况下,mongos能够快速找到包含查询结果集的数据属于哪个分片,但在第二个查询的情况下,必须访问所有分片来查找数据块。
此外,在执行全局查询时,有时在执行查询之前生成索引会更好。例如,可以通过生成”updated_at: 1″索引来显著提高查询最新文档的效率。
5-2. 在分片(Sharding)中选择分片键的方法一旦决定的分片键无法更改,而且插入和查询(写入和读取)的性能很大程度上取决于是否正确设置分片键。在这里,我们将讨论进行分片时理想的分片键设置方法。
首先,不适当的碎片密钥是指什么样的?
○Sharding(シャーディング)でデータ分散が十分に行われない例えば、タイムスタンプのような単調に増加するフィールドをシャードキーとした場合を考えてみてほしい。シャードキーが連続した範囲がチャンクとして分けられるため、新しい挿入は全て連続した狭い範囲内で行われることになる。
所有这样的插入都被分配给一个chunk,换句话说,就是负载会集中在一个shard上。这无法实现原本Sharding的目的。
分片(Sharding)上的本地性不足。先に述べたように、増加していくシャードキーは明らかな方向性をもつ。一方、完全にランダムなシャードキーは全く方向性をもたない。前者は分散が不十分となるが、後者は分散させすぎることになり、この場合もSharding(シャーディング)における効率を低下させる。これは直感的にはわからないが、ローカリティを考慮すれば理解できる。
ここでのローカリティの概念は、「ある期間内にアクセスされたデータが多くの場合関連性がある」ということを指す。この近接性はつまり、最適化の余地があるということを意味する。完全にランダムにデータのSharding(シャーディング)を行えば、何度も全てのシャードにアクセスする必要が生まれる。しかし、例えばユーザーIDのような一段階粒度の荒いシャードキーを用いた場合、少数もしくは一つのシャードと通信を行うだけで済み、パフォーマンスを大きく向上させることができる。
○Sharding(シャーディング)内のチャンクが十分に分割できないシャードキーが粗過ぎると、チャンクの分割が十分にできない場合がある。例えば、ユーザーIDのみをシャードキーに選ぶと、何百万回ものアクセスを行う一人のユーザーがいるかもしれない。この場合、チャンクが分割できず、シャード間のデータや負荷がアンバランスになってしまう恐れがある。
在Sharding(分片)中,理想的分片键根据以上所述,我们能够理解理想的分片键应该具备哪些特征。最佳的分片键应满足以下特征:
-
挿入がシャード間で均等に分散させられるか
-
- 挿入がシャード間で均等に分散させられるか
-
- CRUD操作においてローカリティの利点を活かせるか
- チャンクが分割可能な粒度であるか
これらの条件を満たすシャードキーは、概して二つのフィールドから構成されるもので、一つ目は粗い粒度、二つ目は細かい粒度のフィールドが選択される。今回の例では{username: 1, _id: 1} という複合シャードキーを使ったが、これは、一人のユーザーがどれだけ大量のドキュメントを作成してもチャンクの分割可能性を保証できるような最適なシャードキーであるといえる。
5-3. 在Sharding(分片)上的部署在配置进程的方式也是一个重要的问题。如果要为设置服务器和mongos等所有内容提供独立的机器,那么成本将非常高。然而,通常情况下并不需要这样,只要满足以下最低条件,就可以保持一定的容错性。(有关容错性的详细信息,请参阅“在构成区块链的分布式系统中的容错性”一文。)
-
一つのシャード及びレプリカセットの各メンバーは、それが完全なレプリカなのか、アービターなのかに寄らず、別々のマシンに置かなければならない。
- 一つのシャード及びレプリカセットの各メンバーは、それが完全なレプリカなのか、アービターなのかに寄らず、別々のマシンに置かなければならない。
-
- レプリケーションを行う全てのレプリカセットのメンバーには、専用のマシンを割り当てる必要がある。
-
- レプリカセットのアービターは軽量なので、他のプロセスと共存させても良い。
- 設定サーバは、マシンを他と共用しても構わない。設定クラスタ中のすべての設定サーバ群は、別々のマシン上になければならない。
例えば、今回のサンプルにおける実装例では、必要なプロセスは9つだったが、以下のように4つのマシンを用意すれば十分である。もし、高い可用性や保守性が求められるようなサービスにおいては、アービターを通常のノードとし、各シャード内に三つのノードを用意することでリカバリが効くようになる。
《MongoDB实战》(第九章 分片)
5-4. 在分片(Sharding)时添加新的分片。新しいシャードを追加する際は、バランサーによって古いシャードからチャンクを移行して新しいシャードにも割り当てることになる。この時、例えばMondoDBにおいてはバランサーによるチャンクの移行は現状一つずつしか行えないため、多大な時間を要する事になる。Sharding(シャーディング)システム全体が異常をきたさないよう、必要な際は早い段階でシャードを追加することが必要となる。
6. Ethereum(イーサリアム)をはじめとしたブロックチェーンのSharding(シャーディング)MongoDB上のSharding(シャーディング)との比較しながら、EthereumのようなブロックチェーンでSharding(シャーディング)を行った場合、どのようになるかを考えていく。
6-1. 分散系统 × 分散系统区块链是一种由多个节点处理交易的分布式系统。而分片也正如之前所述,是将数据库分割成块并将整个系统分散化的技术。换句话说,通过在以太坊等区块链上进行分片,实际上就是将分布式系统分散化的行为。
6-1. 分散系统 × 分散系统区块链是一种由多个节点处理交易的分布式系统。而分片也正如之前所述,是将数据库分割成块并将整个系统分散化的技术。换句话说,通过在以太坊等区块链上进行分片,实际上就是将分布式系统分散化的行为。
在之前的文章中,我们提到了在分布式系统中实现一致性的复制、同步以及容错性的重要性,并解释了其中所伴随的复杂性和困难性。要实现分布式系统,需要进行更精密的系统设计。
尤其是在处理像加密货币这样有着重要价值的区块链时,网络破坏如双重支付即使出现一丁点,也是致命的,因此非常需要严格的容错性。
6-2. 在区块链的分片中,切片之间的通信和同步在MongoDB的Sharding(分片)中,我们只需将数据分配到各个分片并保存起来即可。然而,区块链涉及处理账户、交易和智能合约。这些不是独立存在的数据,而是彼此之间有机影响的数据。例如,在智能合约向多个账户进行币的支付时,经常需要跨分片进行交互。
在比特币和以太坊等区块链系统中,为了在分布式系统上进行同步,采用了近似于分布式算法的排他控制和领导者选举算法来达成共识。当在区块链上进行分片(Sharding)时,除了在各分片内进行符合共识算法的同步通信外,还需要在分片之间进行同步通信。这就是所谓的分片间通信问题。在以太坊中,讨论已经朝着通过交换日志信息(receipt)而非状态传输的方式进行分片间通信。
在区块链的分片技术中,单一分片内的去中心化的需求。另外,在MongoDB的Sharding中,只需要注意数据的分配即可。然而,在像以太坊这样的区块链的Sharding中,同时也需要考虑如何分配每个节点。
通常情况下,在区块链中通过双重支付等手段进行篡改,需要PoW时需要达到网络整体计算量的51%的共谋。在大规模网络中,这并不容易,但Sharding(分片)的情况却不同。在一个被分成100个分片的网络中,只需要达到整体计算量的1%即可对分片内的数据进行篡改。
以下是中文的一个选项:
https://medium.com/@icebearhww/ethereum-sharding-and-finality-65248951f649 的内容可以简述如下。
因此,以太坊的设计考虑了节点验证称为“验证器”的交易的随机排列。在Zilliqa中,除了每个纪元都会持续对矿工进行随机排列,还采用了引入PBFT型共识算法的多签名机制,以防止分岔现象发生。
在区块链的Sharding(分片)中,选择适当的分片键和块的分配方式。ブロックチェーンでのSharding(シャーディング)において適切なシャードキーの設定とはどのようなものだろうか。MongoDBでの適切なシャードキーとは、以下のような特徴を持つものであった。
-
挿入がシャード間で均等に分散させられるか
- 挿入がシャード間で均等に分散させられるか
-
- CRUD操作においてローカリティの利点を活かせるか
- チャンクが分割可能な粒度であるか
在区块链的分片技术(Sharding)中,这些条件也是一样的。但是,由于区块链需要具备高度容错性,因此还需要进一步满足防止网络破坏(如双重支付)的条件。
Zilliqaでは、シャードキーの選択について一つの解を出している。送信者のアドレスに基づいてトランザクションを各シャードに振り分けるとしているのである。この時、単一の送信者によるトランザクションは、常に同じシャード内に振り分けられることになる。これによって、シャード内のコンセンサスが明確に取れていれば、シャード間通信が遅れていても二重支払い問題を防止することができる。
然而,通过这种分片键设置,当一个用户同时执行大量的写入和读取操作时,将会向一个分片发送极端的事务。因此,在MongoDB中,通过设置事务ID和用户名的复合分片键,可以将分块进行划分。然而,如果将一个发送者的事务分散到多个分片中,就会增加双重支付的风险,如前所述。在区块链中,人们普遍认为应该牺牲一些效率,以保持高容错性。
仅需要一种选择,以下是原文的汉语本地化释义:
The text should be fully available in either American or British English, providing the full range of options.
《MongoDB实战》
https://livebook.manning.com/#!/book/mongodb-in-action/chapter-9/1
以太坊维基碎片化(Sharding)
https://github.com/ethereum/wiki/wiki/Sharding-introduction-R&D-compendium
Zilliqa白皮书
https://docs.zilliqa.com/whitepaper.pdf