我正在通过实施一个集群来试验spring数据elasticsearch,该集群将托管多租户索引,每个租户一个索引。
我能够为每个需要的索引动态创建和设置设置,比如
public class SpringDataES {
@Autowired
private ElasticsearchTemplate es;
@Autowired
private TenantIndexNamingService tenantIndexNamingService;
private void createIndex(String indexName) {
Settings indexSettings = Settings.builder()
.put("number_of_shards", 1)
.build();
CreateIndexRequest indexRequest = new CreateIndexRequest(indexName, indexSettings);
es.getClient().admin().indices().create(indexRequest).actionGet();
es.refresh(indexName);
}
private void preapareIndex(String indexName){
if (!es.indexExists(indexName)) {
createIndex(indexName);
}
updateMappings(indexName);
}
模型就是这样创建的
@Document(indexName = "#{tenantIndexNamingService.getIndexName()}", type = "movies")
public class Movie {
@Id
@JsonIgnore
private String id;
private String movieTitle;
@CompletionField(maxInputLength = 100)
private Completion movieTitleSuggest;
private String director;
private Date releaseDate;
其中索引名称通过SpEl动态传递
#{tenantIndexNamingService.getIndexName()}
由
提供@Service
public class TenantIndexNamingService {
private static final String INDEX_PREFIX = "test_index_";
private String indexName = INDEX_PREFIX;
public TenantIndexNamingService() {
}
public String getIndexName() {
return indexName;
}
public void setIndexName(int tenantId) {
this.indexName = INDEX_PREFIX + tenantId;
}
public void setIndexName(String indexName) {
this.indexName = indexName;
}
}
因此,每当我必须执行CRUD操作时,首先我指向正确的索引,然后执行所需的操作
tenantIndexNamingService.setIndexName(tenantId);
movieService.save(new Movie("Dead Poets Society", getCompletion("Dead Poets Society"), "Peter Weir", new Date()));
我的假设是以下动态索引分配在多线程Web应用程序中无法正常工作:
@Document(indexName = "#{tenantIndexNamingService.getIndexName()}"
这是因为TenantIndexNamingService是单例。
所以我的问题是如何以线程保存的方式实现正确的行为?
答案 0 :(得分:1)
我可能采用类似于以下为Cassandra提出的方法:
您可以在此处查看相关的GitHub存储库:
现在,由于Elastic在定义Document的方式上存在差异,因此您应该主要关注定义请求范围的bean,该bean将封装您的tenant-id并将其绑定到您的传入请求。