基于集合的多租户 Spring 数据 MongoDB
Collection based multitenancy with Spring Data MongoDB
我们的 Spring Boot 1.3.3 应用程序使用 Spring 数据 MongoDB 1.8.4.
在 MongoDB(2.6 或 3.2)上保留数据
我们需要支持多租户。我们选择使用 "collection based" 多租户,即每个租户都有自己的集合。例如,对于 Article 实体,集合是“{tenantName}_articles”。
Oliver Gierke 亲切地解释了 Making spring-data-mongodb multi-tenant 中的一个实现,例如:
@Document(collectionName = "#{tenantProvider.getTenantId()}_articles")
这在纸面上非常好,但似乎不适用于现实生活中的应用程序,因为我发现了两个问题,一个是主要问题:
问题 1(我可以接受):在应用程序启动时 Spring 引导使数据库为具有自定义索引(例如 @索引属性)。但是在启动时,没有 "current tenant" 所以 Spring 数据会创建不相关的集合,例如“_articles”。我们如何防止这种情况?
问题 2(这里是主要问题):在运行时创建和使用多租户集合(例如“{tenantName}_articles”)没有自定义索引(除了“_id”上的默认 MongoDB 索引)。我怀疑 Spring 在运行时忽略了索引,因为它认为它已经在启动时完成了工作。这是一个主要的性能问题。我们该如何解决这个问题?
感谢您的宝贵时间。
找到了为给定租户重新创建索引的方法:
String tenantName = ...;
MongoMappingContext mappingContext = (MongoMappingContext) mongoTemplate.getConverter().getMappingContext();
MongoPersistentEntityIndexResolver resolver = new MongoPersistentEntityIndexResolver(mappingContext);
for (BasicMongoPersistentEntity entity : mappingContext.getPersistentEntities()) {
if (entity.findAnnotation(Document.class) == null) {
// Keep only collection roots
continue;
}
String collectionName = entity.getCollection();
if (!collectionName.startsWith(tenantName)) {
// Keep only dynamic entities
continue;
}
IndexOperations indexOperations = mongoTemplate.indexOps(collectionName);
for (MongoPersistentEntityIndexResolver.IndexDefinitionHolder holder : resolver.resolveIndexForEntity(entity)) {
indexOperations.ensureIndex(holder.getIndexDefinition());
}
}
我花了一些时间才弄明白这一点。希望这会有所帮助。欢迎改进。
我们的 Spring Boot 1.3.3 应用程序使用 Spring 数据 MongoDB 1.8.4.
在 MongoDB(2.6 或 3.2)上保留数据我们需要支持多租户。我们选择使用 "collection based" 多租户,即每个租户都有自己的集合。例如,对于 Article 实体,集合是“{tenantName}_articles”。
Oliver Gierke 亲切地解释了 Making spring-data-mongodb multi-tenant 中的一个实现,例如:
@Document(collectionName = "#{tenantProvider.getTenantId()}_articles")
这在纸面上非常好,但似乎不适用于现实生活中的应用程序,因为我发现了两个问题,一个是主要问题:
问题 1(我可以接受):在应用程序启动时 Spring 引导使数据库为具有自定义索引(例如 @索引属性)。但是在启动时,没有 "current tenant" 所以 Spring 数据会创建不相关的集合,例如“_articles”。我们如何防止这种情况?
问题 2(这里是主要问题):在运行时创建和使用多租户集合(例如“{tenantName}_articles”)没有自定义索引(除了“_id”上的默认 MongoDB 索引)。我怀疑 Spring 在运行时忽略了索引,因为它认为它已经在启动时完成了工作。这是一个主要的性能问题。我们该如何解决这个问题?
感谢您的宝贵时间。
找到了为给定租户重新创建索引的方法:
String tenantName = ...;
MongoMappingContext mappingContext = (MongoMappingContext) mongoTemplate.getConverter().getMappingContext();
MongoPersistentEntityIndexResolver resolver = new MongoPersistentEntityIndexResolver(mappingContext);
for (BasicMongoPersistentEntity entity : mappingContext.getPersistentEntities()) {
if (entity.findAnnotation(Document.class) == null) {
// Keep only collection roots
continue;
}
String collectionName = entity.getCollection();
if (!collectionName.startsWith(tenantName)) {
// Keep only dynamic entities
continue;
}
IndexOperations indexOperations = mongoTemplate.indexOps(collectionName);
for (MongoPersistentEntityIndexResolver.IndexDefinitionHolder holder : resolver.resolveIndexForEntity(entity)) {
indexOperations.ensureIndex(holder.getIndexDefinition());
}
}
我花了一些时间才弄明白这一点。希望这会有所帮助。欢迎改进。