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