前言
在今天的互联网环境下,网站的访问量已经十分巨大,而且越来越多的网站开始付费或者收费提供服务,高并发场景下如何保持数据库的稳定性成为了一个非常重要的问题。相信大家都知道数据库与业务的解耦合是非常重要的,因为如果我们只是在代码层面去优化,那么可能会引发数据库的性能问题。针对这一问题,本文将介绍在高并发场景下使用 MongoDB 的技巧,包括数据分片、副本集等。
MongoDB 介绍
MongoDB 是一种 NoSQL 的数据库,是面向文档的。它将数据存储在 BSON 格式的文档中,这个文档可以是任何类型的,它们之间彼此独立,也可以嵌套结构。从本质上来说,MongoDB 是一个高性能、高扩展、易部署的开源数据库,可以存储非常大的数据,并且可以跨越多台机器进行复制和共享。它作为一个 NoSQL 数据库,优点非常突出,尤其是在高并发的场景下。下面,我们将详细介绍如何使用 MongoDB 保证高并发场景下的稳定性。
数据分片
在高并发的场景下,单个 MongoDB 数据库很快就会达到数据吞吐量瓶颈,导致请求过慢,影响用户体验以及整个系统的性能。因此, MongoDB 引入了数据分片的概念,可以将整个数据库中的数据分散到多个服务器上。数据分片的目的就是减少单个服务器的负载,从而提高整个系统的性能。具体实现方式如下:
- 创建 Shard 集群:Shard 集群只是一个普通的集群。不同的是,你要使用不同的 shard 关键字,来区分 shard 集群。
sh.addShard(“shard1/ip:port,ip:port”) sh.addShard(“shard2/ip:port,ip:port”) sh.addShard(“shard3/ip:port,ip:port”)
- 开启 Sharding 功能:开启 Sharding 功能的命令为 enableSharding,该功能目的是在集合中指定一个字段作为 shard 的结果,使其具有不同的范围。
sh.enableSharding("mydb") db.runCommand({ shardCollection: "mydb.users", key: { age: 1}});
当以上命令执行完之后,mongodb 会自动将 users 这个集合按照 age 这个字段建立索引,并分成不同的数据分片。在分片的时候,可以设置每个分片的大小阈值 $chunkSize,以便在对 chunk 进行哈希分拆时,获取到更为平衡的分片粒度。其代码如下:
db.runCommand({ shardCollection: "mydb.users", key: { age: 1}, chunkSize: 20});
副本集
MongoDB 的副本集是一种灾备解决方案,通过在多台服务器之间复制数据来提高数据库的可用性和可靠性。同时,副本集还提供了一些额外的功能,例如自动故障检测和自动故障转移等。下面是副本集的一些概念:
- Primary:每个副本集都有一个 Primary,它负责接收所有的写操作,并且将这些操作传播给 Secondary。
- Secondary:所有 Secondary 都从 Primary 复制数据,以便当 Primary 发生故障时,副本集可以选择一个 Secondary 作为新的 Primary,以维护系统的可用性。
- Arbiter:Arbiter 是一个不持有数据的 MongoDB 实例,它只是在副本集中扮演一个仲裁者的角色。当 Primary 挂掉时,Arbiter 负责选择一个 Secondary 作为新的 Primary。
- Priority:每个节点都有一个优先级,该优先级是一个整数,它描述了每个节点在选举新 Primary 时的相对重要性。
- ElectionTimeoutMillis:选举超时(即选举时间)是一个参数,用于指定某个节点在到达选举时间后未能成为 Primary,那么其他节点将从其角色中撤回该节点。
MongoDB 如何实现副本集
下面,我们来介绍如何实现 MongoDB 的副本集。首先,需要创建一个副本集。可以使用以下命令来创建一个副本集,例如:rs0。
rs.initiate()
然后,我们需要将其他的 MongoDB 服务器加入到这个副本集中。例如,添加一个节点,ip为127.0.0.1,端口号为27001:
rs.add("127.0.0.1:27001")
接着,在完成节点添加之后,我们需要确保每个节点的副本集名称是相同的。例如,我们现在的副本集名称为rs0,我们可以通过以下命令来检查:
rs.status()
最后,我们需要设置每个节点的优先级和选举时间。以设置 rs0 节点为 Primary,并将其优先级设置为1,选举时间设置为3秒为例。在 rs0 执行以下命令即可:
rs.conf() rs.reconfig({ _id: "rs0", members: [ { _id: 0, host: "ip1:port1", priority: 1 }, { _id: 1, host: "ip2:port2", priority: 0.5 }, { _id: 2, host: "ip3:port3", priority: 0.25, votes: 0, electionTimeoutMillis: 3000 } ] })
示例代码
最后,提供一个使用 MongoDB 的示例代码,以便更好地理解 MongoDB 的使用场景。
const client = new MongoClient(url, { useNewUrlParser: true }); client.connect(function(err, client) { assert.equal(err, null); const db = client.db(dbName); const collection = db.collection(collectionName); const doc = { a: 1, b: 2, c: 3 }; // 插入一条文档 collection.insertOne(doc, function(err, r) { assert.equal(err, null); assert.equal(1, r.insertedCount); // 查找文档 collection.find({}).toArray(function(err, docs) { assert.equal(err, null); assert.equal(1, docs.length); client.close(); }); }); });
总结
本文介绍了 MongoDB 在高并发场景下的使用技巧,包括数据分片、副本集。希望本文可以帮助大家更好地了解 MongoDB 在实际项目中的应用。在实际的开发中,只有真正深入了解 MongoDB,才能更好的利用 MongoDB 的优点,结合应用的需求来达到更好的使用效果。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65a327a1add4f0e0ffb4207d