- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我有一个 Mongodb 集群,其中包含一个主副本和一个辅助副本作为复制集一起运行。但随着流量的增长,我决定执行分片以获得更快的写入速度。
我根据 tutorial 对“_id”列执行了散列分片。并将数据分成两个分片。然后我进行了一些基准测试,发现在某些情况下,分片集群甚至比非分片集群还要慢。
这是测试结果。
最大吞吐量测试:使用十台机器同时运行“mongoimport”将数据加载到目标db,以测试db的最大写入速度。
结果:
分片集群可以插入 39500 个文档/秒。
非分片集群可以插入 27400 个文档/秒。
单实例 mongoimport 测试:仅使用一台机器运行“mongoimport”将数据加载到目标数据库中。
结果:
分片集群可以插入14285个文档/秒。
非分片集群可以插入 14085 个文档/秒。
mongodb java驱动的单实例数据加载:调用mongodb java驱动的api,只使用一个实例将数据加载到目标数据库中。
结果:
分片集群可以插入 4630 个文档/秒。
非分片集群可以插入 17544 个文档/秒。
第一次测试的结果非常合理。你将 db 分片成一个 2-shard 集群,吞吐量增加了大约 50%,一切都很完美,万岁!
第二个测试有点道理。吞吐量大致相同,但瓶颈可能在数据加载器方面,毕竟我们只使用一个实例加载数据。
但是第三个测试真的让我很烦。分片集群比非分片集群慢得多是没有意义的。另一方面,未分片的数据库具有惊人的速度,甚至比使用 mongoimport 加载数据还要快。
用于加载数据的 java 代码粘贴在下面。我真的无法弄清楚这一点,并提前感谢所有答案。
public static void insert(String host, int port) throws FileNotFoundException,
InterruptedException, ExecutionException {
MongoClient mongoClient = new MongoClient(host, port);
mongoClient.setWriteConcern(WriteConcern.UNACKNOWLEDGED);
MongoDatabase database = mongoClient.getDatabase("my-db");
MongoCollection<Document> collection = database.getCollection("my-collection");
Scanner scan = new Scanner(new File("my-sample-dataset"));
// Pre-load the data into the memory, so that the db load test won't be
// affected by disk I/O time.
Queue<List<String>> resource = new LinkedList<>();
for (int i = 0; i < 100; i++) {
List<String> strs = new ArrayList<>();
for (int j = 0; j < 10000; j++)
strs.add(scan.nextLine());
resource.add(strs);
}
System.out.println("start");
long startTime = System.currentTimeMillis();
while (!resource.isEmpty()) {
List<String> strs = resource.poll();
List<WriteModel<Document>> list = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
list.add(new
InsertOneModel<Document>(Document.parse(strs.get(i))));
}
collection.bulkWrite(list);
}
System.out.println("Finished loading. Time taken: " + (System.currentTimeMillis() - startTime) + "ms");
scan.close();
}
最佳答案
这是可能的罪魁祸首collection.bulkWrite(list);
在批量写入的情况下,mongos 需要将您的批处理分成更小的批处理,然后进入每个分片。
由于您没有指定批处理中文档的插入顺序,因此 MongoDB 必须遵守插入按指定顺序发生的要求。结果是当且仅当它们对应于相同的分片时,才能对连续插入进行批处理。
mongos maintains the original document order, hence only the consecutive inserts which belong to the same shard can be grouped together
例如。考虑“k”是分片键的情况。有两个分片,对应范围
[MinKey, 10], (20, MaxKey]
现在假设我们批量插入以下文档:
[{k: 1}, {k: 25}, {k: 2}]
Doc1 -> Shard1, Doc2 -> Shard2, Doc3 -> Shard3
没有两个连续的文档属于同一个分片,因此调用 getLastError在这种情况下,每个文档之后都需要。
在散列键的情况下,文档将更随机地分布在分片中。即属于相同分片的文档可能更分散,因此会创建更多的批处理 分布越随机,批处理的大小越小,总批处理的数量越多, 产生的成本就越高getLastError
这实际上意味着性能较差。
FIX:指定“ordered: false”
。
collection.bulkWrite(list, new BulkWriteOptions().ordered(false));
这告诉数据库您并不关心严格保留插入发生的顺序。使用 "ordered: false"
,mongos 将为每个分片创建一个批处理,从而避免了额外的 getLastError 调用。每个批处理操作都可以同时在适当的分片上执行,而无需等待上一个批处理的 getLastError
响应。
还有,
MongoClient mongoClient = new MongoClient(host, port);
Creates a Mongo instance based on a single mongodb node and will not be able to discover other nodes in your replica-set or sharded cluster.
在这种情况下,您的所有写入请求都被路由到单个节点,该节点负责由于分片集群而负责所有额外的簿记工作。你应该使用的是
MongoClient(final List<ServerAddress> seeds)
When there is more than one server to choose from based on the type of request (read or write) and the read preference (if it's a read request), the driver will randomly select a server to send a request. This applies to both replica sets and sharded clusters.
Note : Put as many servers as you can in the list and the system will figure out the rest.
关于java - 分片后MongoDB插入速度变慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42522158/
我是ElasticSearch的新手,并且一直在使用它的功能。 我在单个计算机上运行单个节点(master = true,data = true)。我创建一个索引,其中包含3个分片和每个分片1个副本。
我们在14个节点的集群中具有嵌入式Elasticsearch的Java应用程序。所有数据都驻留在中央数据库中,并在elasticsearch中对其进行索引以进行查询。完整的索引编制可以随时进行。 系统
我是 MongoDB 的新手,我想了解这两种技术如何协同工作: 当为你的数据库使用复制时,你有一个主节点和一堆辅助节点。为了保证一致性,建议大家始终从主节点读取,对吧? 因此,当您将复制与分片结合使用
有人告诉我,在一台更强大的机器上使用 100 个分片实现 mongodb 分片以实现更高的并发写入数据库是否有意义,每个 monogod.exe 进程都有一个全局锁?假设这是可能的,这种方法会给我更高
我有一个带有 4x 分片的生产 mongodb 部署 (3.6),它运行良好。我想向集群中添加 4 倍以上的分片。一次添加多个分片是否可以,或者这会引起戏剧性事件吗?我发现添加分片是一项昂贵的操作,在
假设在您的 Web 应用程序中,您需要调用多个 Redis 来呈现页面,例如获取一堆用户哈希。为了加快速度,您可以将 redis 命令包装在 MULTI/EXEC 部分,从而使用流水线,从而避免进行多
我正在查看ES文档,并看到以下内容 Each shard is in itself a fully-functional and independent "index" that can be hos
我有一个 Multi-Tenancy 系统,并且我正在尝试设计ElasticSearch以支持 Multi-Tenancy 。我已经在网上搜索过,但是我发现的所有帖子在实践中均未指定具体操作方法。 基
我已经在 kuberenetes 中使用散列分片设置了分片 MongoDB 集群。我首先创建了配置服务器 Replicaset,然后创建了 2 个分片副本集。最后创建了mongos来连接分片集群。 我
我在调试父子关系查询时遇到问题。我想知道调试问题的方法,而不是简单地发布我的映射、数据、查询并询问问题所在(但我最终保留这样做的权利!)。 为此,首先要检查我的 child 和关联的 parent 是
我正在启动一个 Django 项目,需要对多个可能包含太多行的表进行分片。我浏览了这里和其他地方的线程,并遵循了 Django 多数据库文档,但我仍然不确定它们是如何缝合在一起的。我的模型具有会被分片
我正在尝试使用 docker 创建 mongo 分片.我有: 配置服务器: docker run -it --rm --net=xnet -p 27016:27016 \ --hostname
我正在尝试在一台机器上配置分片,但在尝试添加分片时我不断收到错误消息。我使用以下网站作为引用:http://www.javahotchocolate.com/notes/mongodb-shardin
我刚接触 mongodb。由于我必须存储 +-5000 万份文档,我不得不设置一个带有两个副本集的 mongodb 分片集群 文档看起来像这样: { "_id" : "predefined_u
目前我们运行一个包含 2 个服务器 + 1 个仲裁器的 MongoDB 复制集。 我们在副本集的数据库中存储了大约 150 GB 的数据。 现在我们正在考虑何时开始分片。因为我们想知道是否存在不能再开
我需要并行处理某些项目,所以我使用 TPL Dataflow。 .要注意的是,共享相同键(类似于字典)的项目应按 FIFO 顺序处理,而不是彼此平行(它们可以与具有不同值的其他项目平行)。 正在完成的
问题涉及redis的分片配置。我已经用 Java 实现了一个小型测试应用程序,它以 user:userID 的形式在 Jedis 上创建了 100.000 个用户哈希。每个散列都有元素:姓名、电话、部
您好,我将使用多个 Redis 实例和实例之间的一些分片。 我的问题是,如果加载网页需要访问多个分片,性能是否会受到[明显的影响]。 我的基本概述是在多个 Redis 分片之间实现负载平衡*下面的脚注
Predis 声称拥有客户端分片(支持键的一致性散列)。 http://github.com/nrk/predis 我可以使用连接到一组配置文件(节点)来进行分片,但它不是一致的哈希。当我将另一个节点
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我是一名优秀的程序员,十分优秀!