我目前正在开发一个由Mongo数据库驱动的移动应用程序,但是现在一切正常,我们希望添加Sharding
以备将来使用。
为了测试这一点,我们创建了一个实验室环境(在Hyper-V中运行)来测试各种场景:
已创建以下服务器:
在C#中创建了一个小型控制台应用程序,以便能够测量执行插入的时间。
此控制台应用程序确实导入具有以下属性的10.000人: - 名称 - 名字 - 全名 - 出生日期 - Id
所有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条记录
注意:已将分片键设置为哈希_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条记录
注意:已将分片键设置为哈希_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.
根据上面执行的测试,分片确实有效,我添加的分片越多,性能越好。 但是,我不明白为什么我在使用分片而不是使用单个服务器时会遇到如此巨大的性能下降。
我需要快速阅读和写作s我认为分片会是解决方案,但似乎我在这里遗漏了一些东西。
任何人为什么能指出我正确的方向?
亲切的问候
答案 0 :(得分:1)
路由服务器和配置服务器,路由服务器和数据节点之间的层增加了延迟。 如果你有1毫秒ping * 10k插入,你有一个10秒的延迟,没有出现在未整理的设置中。
根据您配置的写入级别(如果您配置了任何级别的写入确认),由于阻塞直到从数据节点收到确认,您在分片环境中的基准测试可能还有10秒钟。
如果您的写入问题设置为确认并且您有副本节点,那么您还必须等待写入传播到副本节点,从而增加额外的网络延迟。 (尽管你似乎没有副本节点)。并且,如果使用默认设置允许链式复制(辅助节点与其他辅助节点同步),则根据您的网络拓扑结构,写入问题可能会增加多层网络延迟。 https://docs.mongodb.org/manual/tutorial/manage-chained-replication/。如果您有其他索引和写入问题,则每个副本节点必须在返回写入确认之前写入该索引(尽管可以在副本节点上禁用索引)
没有分片和没有复制(但具有写入确认),虽然插入仍然会阻塞插入,但由于网络层没有额外的延迟。
散列_id字段的成本也可累计到10k,总计几秒钟。您可以使用具有高度随机性的_id字段来避免散列,但我认为这不会影响性能。