MongoDB 是一种开源文档数据库,被广泛应用于许多 Web 应用程序和大型企业级环境中。在实际应用中,为了提高数据库的性能和可靠性,我们需要将读操作和写操作拆分到不同的服务器中,这就是 MongoDB 的读写分离方案。
读写分离方案简介
在 MongoDB 读写分离方案中,我们将主要的写操作指向一个专门的主节点,然后将所有的读操作分发到多个副本节点中。这个过程将会显著提高数据的读取速度和负载均衡能力。另外,在主节点出现故障时,副本节点可以接管主节点的职责,保证数据库的可靠性和稳定性。
读写分离方案基于 MongoDB 的 replica set 实现。一个 replica set 由一个主节点和多个副本节点组成。主节点负责所有的写操作,并将数据同步到副本节点中。副本节点负责读取数据,但不会接受写操作。
读写分离方案实践
下面,我们将演示如何在 MongoDB 中实现读写分离方案:
第一步:启动主节点
在启动 MongoDB 实例时,我们需要使用 --replSet
参数来指定 replica set 的名称。我们将使用 rs0
作为示例:
$ mongod --replSet rs0
第二步:初始化 replica set
在主节点上,我们需要初始化 replica set。使用 mongo
命令行工具连接到 MongoDB,然后执行 rs.initiate()
命令:
$ mongo > rs.initiate()
这个命令将自动创建一个名为 rs0
的新 replica set。
第三步:添加副本节点
在次要节点上,我们需要启动 MongoDB 实例,并指定 replica set 的名称。然后使用 rs.add()
命令将节点添加到 replica set 中。例如,我们添加两个副本节点:
$ mongod --replSet rs0 $ mongo > rs.add("192.168.1.100:27017") > rs.add("192.168.1.101:27017")
这样,我们就将两个副本节点加入了 rs0
replica set 中。
第四步:查询 replica set 状态
使用 rs.status()
命令可以查询当前 replica set 的状态。在主节点上,执行该命令会显示所有的节点,并且会标注出主节点和副本节点。
-- -------------------- ---- ------- - ----------- - ----- - ------ ------ - ------------------------------------ --------- - -- ------ - -------------- ----------- - --- --------- - - - ----- - -- ------ - ------------------ -------- - -- ------- - -- ---------- - ---------- -------- - --- -------- - - ---- - --------------------- --- --- - ------------- -- --------------- - - ---- - --------------------- --- --- - ------------- -- ------------ - -------------------------------- ------------------- - -------------------------------- --------------- - ------------------------------------ ------------------- - ------------------------------------ -------- - -------------- ---------------------- - -- -- - ----- - -- ------ - ---------------------- -------- - -- ------- - -- ---------- - ------------ -------- - ---- -------- - - ---- - --------------------- --- --- - ------------- -- --------------- - - ---- - --------------------- --- --- - ------------- -- ------------ - -------------------------------- ------------------- - -------------------------------- --------------- - ------------------------------------ ------------------- - ------------------------------------ -------- - -------------- ---------------------- - -- -- - ----- - -- ------ - ---------------------- -------- - -- ------- - -- ---------- - ------------ -------- - ---- -------- - - ---- - --------------------- --- --- - ------------- -- --------------- - - ---- - --------------------- --- --- - ------------- -- ------------ - -------------------------------- ------------------- - -------------------------------- --------------- - ------------------------------------ ------------------- - ------------------------------------ -------- - -------------- ---------------------- - -- - -- ---- - -- --------------- - --------------------- --- -------------- - - ------------- - --------------------- --- ----------- - - ------ - ------------------------------------------ ------- - ------------- - - -
第五步:读写分离配置
我们需要向应用程序提供读写分离的配置。在 mongodb://
URI 中,我们可以指定 readPreference
参数来实现读写分离。该参数有三个值:
primary
:只从主节点读取数据,用于执行写操作。secondary
:从副本节点读取数据,用于执行读操作。primaryPreferred
:优先从主节点读取数据,但如果主节点不可用,则从副本节点读取数据。
示例代码:
const uri = "mongodb://localhost:27017,192.168.1.100:27017,192.168.1.101:27017/?replicaSet=rs0&readPreference=secondary";
优化读写分离方案
读写分离方案虽然可以提高 MongoDB 的性能和可靠性,但是在实际应用中,我们还需要优化它。下面给出几个优化建议:
配置读写关系
我们可以将某些特定的集合或数据库的读写关系配置为不同的读优先级。例如,在读写分离方案中,实时数据应该从主节点读取,而报表数据则可以从副本节点读取。
-- -------------------- ---- ------- ----- ------ - - ------------- - ------- ---------- ------ ------------ ------------ --------------- -------------- -- ------------- - ------- ---------- ------ --------------------- ------------ --------------- -------------- - --
在这个示例中,我们将 /database1
的写操作指定到主节点,读操作指定到副本节点。对于 /database2
,我们将写操作指定到主节点,但是读操作优先从副本节点读取。
避免不必要的读请求
为了避免发送不必要的读请求数,我们可以使用 readPreference
参数的 maxStalenessSeconds
选项。这个选项指定了数据可以过期多长时间,如果节点的数据比这个时间更旧,那么就不会返回数据。
const uri = "mongodb://localhost:27017,192.168.1.100:27017,192.168.1.101:27017/?replicaSet=rs0&readPreference=secondary&maxStalenessSeconds=10";
在这个示例中,如果副本节点的数据比主节点新不到 10 秒钟,那么就会使用副本节点返回数据。
避免写操作和读操作的争用
为了避免写操作和读操作的争用,我们可以在客户端和服务端上使用事务。事务可以在多个文档中执行多个操作,并允许多个客户端同时更新数据,而不会导致数据损坏或冲突。
在 MongoDB 中,事务在 replica set 中自动执行。我们可以使用 session.startTransaction()
方法开启一个事务,在事务中发出多个写操作和读操作。
-- -------------------- ---- ------- ----- ------- - ---------------------- --------------------------- --- - -- ---- ----- ------------------------------------------------- ----- ------ -- - -------- ------- --- ----- ------------------------------------------------- ----- ------ -- - ----- - ----- ------- - -- - -------- ------- --- ----- ---------------------------- - ----- ------- - ----- --------------------------- -
结论
读写分离方案是 MongoDB 中非常重要的性能优化手段之一。在实际应用中,我们应该合理配置读写关系,避免发送不必要的读请求,并使用事务避免写操作和读操作的争用。通过这些优化,我们可以更好地提高 MongoDB 的性能和可靠性。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/672ed618eedcc8a97c8afc87