Overview
在本指南中,您可以学习如何配置写关注、读关注和读取偏好选项,以修改 Java 驱动程序在副本集上运行读取和写入操作的方式。
读取和写入设置优先级
您可以在以下级别设置写关注、读关注和读取偏好选项:
客户端,为所有操作执行设置默认值,除非被覆盖
事务
Database
Collection
此列表还指示了选项设置的优先级递增顺序。示例,如果为ACID 事务设立读关注(read concern),它将覆盖从客户端继承的读关注(read concern)设置。
写关注、读关注(read concern)和读取偏好(read preference)选项允许您自定义副本集中数据的因果一致性和可用性。 要查看这些选项的完整列表,请参阅MongoDB Server手册中的以下指南:
配置读取和写入操作
您可以通过设置读取偏好来控制驱动程序如何在副本集成员之间路由读取操作。您还可以通过设置读关注和写关注来控制驱动程序在副本集上等待读取和写入操作确认的方式。
以下部分介绍如何在各个级别配置这些读取和写入设置。
客户端配置
此示例演示如何通过将 MongoClientSettings实例传递给构造函数设立MongoClient实例的读取偏好(read preference)、读关注(read concern)和写关注(write concern)。 该代码配置以下设置:
secondary读取偏好(read preference):读取操作从从节点(secondary node from replica set)副本集成员检索数据。LOCAL读关注(read concern):读取操作会返回实例的最新数据,但不保证该数据已写入大多数副本集成员。W2写关注(write concern):主节点 (primary node in the replica set)副本集成员和一个从节点(secondary node from replica set)成员必须确认写入操作。
MongoClient mongoClient = MongoClients.create(MongoClientSettings.builder() .applyConnectionString(new ConnectionString("mongodb://localhost:27017/")) .readPreference(ReadPreference.secondary()) .readConcern(ReadConcern.LOCAL) .writeConcern(WriteConcern.W2) .build());
或者,您可以在连接 URI 中指定读取和写入设置,该 URI 作为参数传递给MongoClients构造函数:
MongoClient uriClient = MongoClients.create("mongodb://localhost:27017/?readPreference=secondary&w=2&readConcernLevel=local");
事务配置
此示例演示如何通过将 TransactionOptions实例传递给 startTransaction() 方法来设立ACID 事务的读取偏好(read preference)、读关注(read concern)和写关注(write concern)。事务在 会话 中运行,会话是您打算按顺序运行的相关读取或写入操作的分组。在应用ACID 事务选项之前,创建一个 ClientSession实例以启动会话。
该示例配置了以下设置:
primary读取偏好(read preference):读取操作从主节点 (primary node in the replica set)副本集成员检索数据。MAJORITY读关注(read concern):读取操作返回实例已写入大多数副本集成员的最新数据。W1写关注(write concern):主节点 (primary node in the replica set)副本集成员必须确认写入操作。
TransactionOptions tOptions = TransactionOptions.builder() .readPreference(ReadPreference.primary()) .readConcern(ReadConcern.MAJORITY) .writeConcern(WriteConcern.W1) .build(); try (ClientSession clientSession = client.startSession()) { clientSession.startTransaction(tOptions); // Specify transaction operations here }
数据库配置
此示例展示了如何通过将 setter 方法链接到 getDatabase() 方法来设立名为 test_database 的数据库的读取偏好(read preference)、读关注(read concern)和写关注(write concern)。 该代码配置以下设置:
primaryPreferred读取偏好(read preference):读取操作从主节点 (primary node in the replica set)副本集成员检索数据,如果主节点 (primary node in the replica set)不可用,则从从节点(secondary node from replica set)成员检索数据。AVAILABLE读关注(read concern):读取操作会返回实例的最新数据,但不保证该数据已写入大多数副本集成员。MAJORITY写关注(write concern):所有副本集成员中的大多数必须确认写入操作。
MongoDatabase database = mongoClient.getDatabase("test_database") .withReadPreference(ReadPreference.primaryPreferred()) .withReadConcern(ReadConcern.AVAILABLE) .withWriteConcern(WriteConcern.MAJORITY);
集合配置
此示例展示了如何通过将 setter 方法链接到 getCollection() 方法来设立名为 test_collection 的集合的读取偏好(read preference)、读关注(read concern)和写关注(write concern)。 该代码配置以下设置:
secondaryPreferred读取偏好(read preference):读取操作从从节点(secondary node from replica set)副本集成员检索数据,如果没有可用的从从节点(secondary node from replica set)成员,则从主节点 (primary node in the replica set)成员检索数据。AVAILABLE读关注(read concern):读取操作会返回实例的最新数据,但不保证该数据已写入大多数副本集成员。UNACKNOWLEDGED写关注(write concern):副本设立成员不需要确认写入操作。
MongoCollection<Document> collection = database.getCollection("test_collection") .withReadPreference(ReadPreference.secondaryPreferred()) .withReadConcern(ReadConcern.AVAILABLE) .withWriteConcern(WriteConcern.UNACKNOWLEDGED);
高级读取配置
以下部分介绍了进一步自定义Java驱动程序路由读取操作的方式。
分片集群
您可以在连接到分片集群时指定读取偏好(read preference)。MongoDB使用分片按键范围划分数据集,并将数据分布到多个数据库实例。分片集群(或分片的部署中的节点设立)包括以下组件:
分片:包含分片的数据子集的副本副本集。
Mongos:一种查询路由器,在应用程序和分片集群之间提供接口。
配置服务器:存储集群配置设置和元数据的服务器。
提示
要学习;了解有关分片的集群的更多信息,请参阅MongoDB Server手册中的分片。
从副本集分片读取时, mongos会应用您指定的读取偏好(read preference)。对于每个操作,都会重新评估读取偏好(read preference)。
以下示例展示了如何连接到分片集群并在连接字符串中指定 secondary读取偏好(read preference):
MongoClient uriClient = MongoClients.create("mongodb://user:password@mongos1.example.com,mongos2.example.com/?readPreference=secondary");
标签集
在MongoDB Server中,您可以根据您选择的任何条件将键值标签应用副本集成员。然后,您可以使用这些标签来定位一个或多个成员以执行读取操作。
默认情况下,在选择要读取的成员时,Java 驱动程序会忽略标签。要指示 Java 驱动程序优先选择特定标签,请将标签作为列表传递给读取偏好 setter 方法。
假设您连接到一个副本集,其中包含托管在美国多个数据中心的节点。您希望驱动程序优先按以下顺序从从节点副本集成员中读取:
来自 纽约数据中心 的节点,标记为
("dc", "ny")来自旧金山数据中心的节点,标记为
("dc", "sf")任何从从节点(secondary node from replica set)
此代码示例会将表示前面副本集成员的标签列表传递给 ReadPreference.secondary() setter 方法。 然后,代码将读取偏好(read preference)信息传递给 withReadPreference() 方法,以在数据库上设立读取顺序:
TagSet tag1 = new TagSet(new Tag("dc", "ny")); TagSet tag2 = new TagSet(new Tag("dc", "sf")); TagSet tag3 = new TagSet(); ReadPreference readPref= ReadPreference.secondary(Arrays.asList(tag1, tag2, tag3)); MongoDatabase database = mongoClient.getDatabase("test_database") .withReadPreference(readPref);
负载均衡
连接到分片集群或副本集时, Java驱动程序使用负载均衡来处理读取和写入请求。负载均衡允许驱动程序将这些请求分发到多台服务器,从而避免任何一台服务器不堪重负,确保最佳性能。
连接到分片集群时, Java驱动程序会计算网络往返时间最短的 mongos 实例,从而确定最近的mongos实例。然后,驱动程序通过将此 mongos 的平均往返时间与 localThresholdMS 值相加来确定延迟窗口。驱动程序在延迟窗口内的最多两个随机mongos实例之间对请求进行负载均衡。对于每个请求,驱动程序会通过确定其 operationCount 值来选择具有较低操作负载的服务器。
连接到副本集时,Java 驱动程序首先根据您的读取偏好选择副本集成员。然后,驱动程序按照上一段所述的相同流程进行操作。计算延迟时间窗口后,驱动程序会随机选择最多两个该窗口内的副本集成员,并选择具有较低 operationCount 值的成员来接收请求。
提示
LocalThreshold
Java驱动程序使用本地阈值来计算服务器选择的延迟窗口。此值确定有资格接收读取和写入请求的服务器。
默认情况下,驱动程序仅使用mongos实例或副本集成员,其网络探测(ping)时间与最近服务器的偏差在 15 毫秒以内。要在延迟较高的服务器之间分配读取操作,请在 MongoClientSettings实例中设立localThreshold 选项,或在连接 URI 中设置 localThresholdMS 选项。
注意
从单个mongos实例中选择副本集成员时, Java驱动程序会忽略 localThresholdMS 选项。在这种情况下,请使用 localThreshold 命令行选项。
以下示例连接到副本集并指定 35 毫秒的本地阈值。选择 MongoClientSettings 或 Connection URI标签页,查看每种方法的相应代码:
MongoClient client = MongoClients.create(MongoClientSettings.builder() .applyConnectionString(new ConnectionString("mongodb://localhost:27017/")) .applyToClusterSettings(builder -> builder.localThreshold(35, TimeUnit.MILLISECONDS)) .build());
String connectionString = "mongodb://localhost:27017/?replicaSet=repl0&localThresholdMS=35"; MongoClient client = MongoClients.create(connectionString);
在前面的示例中, Java驱动程序在最近节点的网络探测(ping)时间的 35 毫秒内在匹配节点之间分配读取。
API 文档
要进一步了解本指南所讨论的任何方法或类型,请参阅以下 API 文档: