Spring Data MongoDB 教程

WriteConcern 写入策略

如果尚未通过 MongoDB 驱动程序在更高层次(如 com.mongodb.client.MongoClient)上指定写入策略,可以设置 MongoTemplate 用于写操作的 com.mongodb.WriteConcern 属性(写入策略)。如果没有设置 WriteConcern 属性,则默认为 MongoDB 驱动程序的 DB 或 Collection 设置中的写入策略设置。

写入策略

MongoDB 的写入策略有多种方式,写入策略是指 “当客户端发起写入请求后,数据库什么时候给应答”。MongoDB 有三种处理策略:

Unacknowledged

客户端发出请求丢到 socket 的时候就收到响应。这个时候客户端不需要等地服务器的应答,但是的本地的驱动还是尽可能的通知客户端网络的异常,这和客户端操作系统的配置有关。就像现实中邮寄信件一样,丢到信箱就结束了。但是如果信箱坏了,发信人还是能知道的。

Acknowledged

这种方式客户端发送接口会等待服务器给的确认,这种方式一定能确保服务器收到了客户端的请求。并且服务器能够在异常时,响应客户端。

Journaled

Journaled 方式相比 Acknowledged 的方式是要保证服务器端已经写入到硬盘文件了。对于 Acknowledged 的方式有可能服务收到请求数据并响应客户端后的一瞬间宕机了。此时,数据就可能丢失。但是对于 Journaled 方式,服务器保证写入到磁盘后再响应客户端(即使宕机了,也不会导致数据丢失)。

Replica Acknowledged

这个方式和 Acknowledged 是一样的意思,适用于 Replica sets(复制集)模式。Acknowledged 模式下只有一台机器收到了请求就返回了,对于复制集模式有多台机器的情况,可以要求有多台机器收到写入请求后再响应客户端。这种更安全,但是导致了客户端耗时增加,所以要结合自己的场景设置合适的策略。

可以通过下面的方式设置默认的策略,其中:

  • majority 表示多数节点写入成功后才相应客户端,也可以替换成具体的数子,比如 w:2 表示至少写入 2 个节点才返回。

  • wtimeout 表示超时时间。

  • j 表示是否等待写入 journal 日志之后应答客户端。true 表示等待写入日志,false 表示不等待写入日志。写入 journal 日志需要开启 journal 功能,用于在意外重启,宕机等情形下可以通过 journal 来进行数据恢复,写入 journal 操作必须等待直到下次提交日志时完成写入,为降低延迟,MongoDB 可以通过增加 commit journal 的频率来加快 journal 写入。

cfg = rs.conf()
cfg.settings.getLastErrorDefaults = { w: "majority", wtimeout: 5000 }
rs.reconfig(cfg)

也可以通过客户端来指定具体的策略,如下:

//  至少要写入两个节点,超时时间是5s
db.products.insert(
  { item: "envelopes", qty : 100, type: "Clasp" },
  { writeConcern: { w: 2, wtimeout: 5000 } }
)

示例

通过 @Configuration 类设置 MongoTemplate 的 WriteConcern 写入策略,如下:

package com.hxstrive.springdata.mongodb.config;

import com.mongodb.WriteConcern;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.WriteResultChecking;

/**
* 配置实例化 MongoTemplate
* @author hxstrive.com 2022/12/23
*/
@Configuration
public class AppConfig {

   @Bean
   public MongoClient mongoClient() {
       // 创建连接到本地的 MongoClient 对象
       return MongoClients.create("mongodb://localhost:27017");
   }

   @Bean
   public MongoTemplate mongoTemplate(MongoClient mongoClient) {
       // 创建链接到本地 test 数据库的 MongoTemplate 实例
       MongoTemplate mongoTemplate = new MongoTemplate(mongoClient, "test");

       // 设置 WriteResultChecking 检查策略
       mongoTemplate.setWriteResultChecking(WriteResultChecking.EXCEPTION);

       // 设置 WriteConcern 写入策略
       mongoTemplate.setWriteConcern(WriteConcern.ACKNOWLEDGED);

       return mongoTemplate;
   }

}
说说我的看法
全部评论(
没有评论
关于
本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,请来信告知:hxstrive@outlook.com
公众号