有一个复制的 mongodb(mongodb-1 - 主数据库,mongodb-2 - 辅助数据库,mongodb-3 - 辅助数据库)。 该应用程序通过 spring-boot-starter-data-mongodb 运行。
服务:
public class FooBarService {
private FooBarRepository repository;
public FooBar method1() {
return repository.someQuery();
}
public FooBar method2() {
return repository.someQuery();
}
}
存储库:
public interface FooBarRepository extends MongoRepository<FooBar, String> {
FooBar someQuery();
}
我的问题是,让 method1 从 mongo 副本集中的主要参与者读取,method2 从 mongo 副本集中的次要参与者读取有多好?
想找到某种方法在服务级别管理此问题(类似于@Transactional,但选择一个mongo副本集成员)。
您能告诉我这方面有什么解决方案吗?
@Meta
注释如果您想继续使用存储库接口,您可以使用
@Meta
注释来注释查询方法定义,该注释允许您传递标志以指示从辅助 mongodb 成员读取。
public interface FooBarRepository extends MongoRepository<FooBar, String> {
@Query("{}")
@Meta(flags = Meta.CursorOption.SECONDARY_READS)
FooBar someQuery();
}
但是您无法从服务级别控制该标志。您必须创建 2 种查询方法:一种带有标志,一种不带有标志。就像
someQueryFromSecondary()
和 someQueryFromPrimary()
。
MongoTemplate
另一种选择是直接使用
MongoTemplate
并在 Query
上设置标志。
public void someQuery(boolean readFromSecondary) {
var query = Query.query(Criteria.where("someKey").is("1"));
if (readFromSecondary) {
query.allowSecondaryReads();
}
return mongoTemplate.findOne(query, FooBar.class);
}
无论您选择哪种解决方案:请注意,从次要成员读取可能会导致检索过时的数据。 考虑查看 mongodb 文档。
这已经有所改变。 如果您使用 Spring 的 Repo 接口,则只需使用 @ReadPreference 即可。 像这样:
public interface SearchRepository extends MongoRepository<SearchItem, String>
{
@ReadPreference("secondaryPreferred")
public Optional<SearchItem> findById(String id);
如果你使用Spring的MongoOperations,你可以这样做。
AggregationOptions aggOps = AggregationOptions.builder().readPreference(
com.mongodb.ReadPreference.secondaryPreferred()).build();
Aggregation agg = Aggregation.newAggregation(match, buildRuntimeProjection()).
withOptions(aggOps);
如果您希望代码中的所有读取都使用特定的读取首选项,您只需将其附加到您的 url 字符串即可。 即“readPreference=secondaryPreferred”。 即您的 applications.properties 文件中类似于以下内容。
spring.data.mongodb.uri=mongodb://localhost:27017,localhost:27018,.../dbName?authSource=admin&readPreference=secondaryPreferred