MongoDb 的分片不会改进实验室设置中的应用程序

MongoDb's Sharding does not improve application in a Lab setup

我目前正在开发一个由 Mongo 数据库提供支持的移动应用程序,但是现在一切正常,我们想添加 Sharding 为将来做好准备。

为了对此进行测试,我们创建了一个实验室环境(Hyper-V 中的 运行ning)来测试各种场景:

已创建以下服务器:

已使用 C# 创建了一个小型控制台应用程序,以便能够测量执行插入的时间。

此控制台应用程序确实导入了具有以下属性的 10.000 人: - 姓名 - 名 - 全名 - 出生日期 - 编号

所有 10.000 条记录仅“_id”不同,所有记录的所有其他字段都相同。

重要的是要注意每个测试恰好 运行 3 次。 每次测试后,数据库都会被删除,因此系统会再次干净。

查找下面的测试结果:

不分片插入 10.000 条记录

Writing 10.000 records | Non-Sharding environment - Full Disk IO #1: 14 Seconds.
Writing 10.000 records | Non-Sharding environment - Full Disk IO #2: 14 Seconds.
Writing 10.000 records | Non-Sharding environment - Full Disk IO #3: 12 Seconds.

使用单个数据库分片插入 10.000 条记录

注意: Sharding key 已经设置为hashed _id字段。 有关(部分)分片信息,请参阅下面的 Json:

shards:
  {  "_id" : "shard0000",  "host" : "192.168.137.12:27017" }

databases:
  {  "_id" : "DemoDatabase",  "primary" : "shard0000",  "partitioned" : true }
          DemoDatabase.persons
                  shard key: { "_id" : "hashed" }
                  unique: false
                  balancing: true
                  chunks:
                          shard0000       2
                  { "_id" : { "$minKey" : 1 } } -->> { "_id" : NumberLong(0) } on : shard0000 Timestamp(1, 1)
                  { "_id" : NumberLong(0) } -->> { "_id" : { "$maxKey" : 1 } } on : shard0000 Timestamp(1, 2)

结果:

Writing 10.000 records | Single Sharding environment - Full Disk IO #1: 1 Minute, 59 Seconds.
Writing 10.000 records | Single Sharding environment - Full Disk IO #2: 1 Minute, 51 Seconds.
Writing 10.000 records | Single Sharding environment - Full Disk IO #3: 1 Minute, 52 Seconds.

使用双数据库分片插入 10.000 条记录

注意: Sharding key 已经设置为hashed _id字段。 有关(部分)分片信息,请参阅下面的 Json:

shards:
  {  "_id" : "shard0000",  "host" : "192.168.137.12:27017" }
  {  "_id" : "shard0001",  "host" : "192.168.137.13:27017" }

databases:
  {  "_id" : "DemoDatabase",  "primary" : "shard0000",  "partitioned" : true }
          DemoDatabase.persons
                  shard key: { "_id" : "hashed" }
                  unique: false
                  balancing: true
                  chunks:
                          shard0000       2
                  { "_id" : { "$minKey" : 1 } } -->> { "_id" : NumberLong("-4611686018427387902") } on : shard0000 Timestamp(2, 2)
                  { "_id" : NumberLong("-4611686018427387902") } -->> { "_id" : NumberLong(0) } on : shard0000 Timestamp(2, 3)
                  { "_id" : NumberLong(0) } -->> { "_id" : NumberLong("4611686018427387902") } on : shard0001 Timestamp(2, 4)
                  { "_id" : NumberLong("4611686018427387902") } -->> { "_id" : { "$maxKey" : 1 } } on : shard0001 Timestamp(2, 5)

结果:

Writing 10.000 records | Single Sharding environment - Full Disk IO #1: 49 Seconds.
Writing 10.000 records | Single Sharding environment - Full Disk IO #2: 53 Seconds.
Writing 10.000 records | Single Sharding environment - Full Disk IO #3: 54 Seconds.

根据上面执行的测试,分片确实有效,我添加的分片越多,性能越好。 但是,我不明白为什么我在使用分片而不是使用单个服务器时会面临如此巨大的性能下降。

我需要快速阅读和写作,我认为分片是解决方案,但似乎我在这里遗漏了一些东西。

谁能给我指出正确的方向?

亲切的问候

路由服务器和配置服务器、路由服务器和数据节点之间的层增加了延迟。 如果您有 1ms ping * 10k 插入,则有 10 秒的延迟不会出现在未分片设置中。

根据您配置的写入关注级别(如果您配置了任何级别的写入确认),由于在收到来自数据节点。

如果您的写关注设置为确认并且您有副本节点,那么您还必须等待写入传播到您的副本节点,从而增加额外的网络延迟。 (虽然您似乎没有副本节点)。并且根据您的网络拓扑,如果您使用默认设置允许链式复制(辅助从其他辅助同步),写入问题可能会增加多层网络延迟。 https://docs.mongodb.org/manual/tutorial/manage-chained-replication/。如果您有额外的索引和写入问题,则每个副本节点都必须在返回写入确认之前写入该索引(尽管可以在副本节点上禁用索引)

没有分片和复制(但有写确认),虽然您的插入仍然会阻塞在插入上,但网络层不会造成额外的延迟。

对 _id 字段进行散列处理也有一个成本,对于 10k,该成本可能累积到总共几秒钟。您可以使用具有高度随机性的 _id 字段来避免散列,但我认为这不会对性能产生太大影响。