Collection based multitenancy with Spring Data MongoDB
我们的Spring Boot 1.3.3应用程序使用Spring Data MongoDB 1.8.4将数据持久存储在MongoDB(2.6或3.2)上。
我们需要支持多租户。我们选择使用"基于集合"的多租户,即每个租户都有自己的集合。例如,对于Article实体,集合为" {tenantName} _articles "。
Oliver Gierke用例如:
解释了在使spring-data-mongodb多租户中的实现。
1 | @Document(collectionName ="#{tenantProvider.getTenantId()}_articles") |
这在纸上非常好,但是似乎不适用于现实生活中的应用,因为我发现了两个问题,一个是主要问题:
问题1(我可以忍受):在应用程序启动时,Spring Boot使数据库为具有自定义索引(例如@Indexed属性)的实体建立索引。但是在启动时,没有"当前租户",因此Spring Data创建了不相关的集合,例如" _articles"。我们如何防止这种情况?
问题2(这里是主要问题):在运行时,创建并使用了诸如" {tenantName} _articles "之类的多租户集合,而没有自定义索引(除了" _ id "上的默认MongoDB索引)。我怀疑Spring在运行时会忽略索引,因为它认为它已经在启动时完成了工作。这是一个主要的性能问题。我们该如何解决呢?
谢谢您的时间。
找到一种为给定租户重新创建索引的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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()); } } |
花一些时间来解决这个问题。希望这会有所帮助。欢迎改进。