Overview
在本指南中,您可以学习;了解如何配置写关注(write concern)、读关注(read concern)和读取偏好(read preference)选项,以修改Kotlin Sync驾驶员在副本集上运行写入操作的方式。
读取和写入设置优先级
您可以在以下级别设置写关注、读关注和读取偏好选项:
客户端,为所有操作执行设置默认值,除非被覆盖
事务
Database
Collection
此列表还指示了选项设置的优先级递增顺序。示例,如果为ACID 事务设立读关注(read concern),它将覆盖从客户端继承的读关注(read concern)设置。
写关注、读关注(read concern)和读取偏好(read preference)选项允许您自定义副本集中数据的因果一致性和可用性。 要查看这些选项的完整列表,请参阅MongoDB Server手册中的以下指南:
配置读取和写入操作
您可以通过设置读取偏好(read preference)控制驾驶员如何在副本集节点之间路由读取操作。 您还可以通过设置读关注和写入关注来控制驾驶员如何等待副本集上写入操作的确认。
以下部分介绍如何在各个级别配置这些读取和写入设置。
客户端配置
此示例演示如何通过将 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驾驶员优先选择某些标签,请将标签作为列表传递给读取偏好(read preference)setter 方法。
假设您连接到一个副本集,其中包含托管在美国多个数据中心的节点。 您希望驾驶员优先按以下顺序从从节点(secondary node from replica set)副本集成员读取:
来自 纽约数据中心 的节点,标记为
("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 Sync驾驶员会计算网络往返时间最短的实例,从而确定最近的 mongos
实例。然后,驾驶员通过将此 mongos
的平均往返时间与 localThresholdMS 值 相加来确定延迟窗口。驾驶员在延迟窗口内的最多两个随机 mongos
实例之间对请求进行负载均衡。对于每个请求,驾驶员会通过确定其 operationCount
值来选择具有较低操作负载的服务器。
连接到副本集时, Kotlin Sync驾驶员首先根据您的读取偏好(read preference)副本集成员。然后,驾驶员执行与上一段所述相同的进程。计算延迟窗口后,驾驶员最多选择两个处于该窗口内的随机副本集节点,并选择具有较低 operationCount
值的节点来接收请求。
提示
要学习;了解有关负载均衡的更多信息,请参阅MongoDB Server手册中的分片集群负载均衡器。
LocalThreshold
Kotlin Sync驾驶员使用本地阈值来计算服务器选择的延迟窗口。此值确定有资格接收读取和写入请求的服务器。
默认下,驾驶员仅使用网络探测(ping)时间在最近服务器的 15 毫秒以内的 mongos
实例或副本集成员。要在延迟较高的服务器之间分配读取操作,请在 MongoClientSettings
实例中设立localThreshold
选项,或在连接 URI 中设置 localThresholdMS
选项。
注意
从单个 mongos
实例中选择副本集成员时, Kotlin Sync驾驶员会忽略 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 Sync驾驶员在最近节点的网络探测(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 文档: