创建索引需要创建索引并且更新集群index matedata,这一过程在MetaDataCreateIndexService的createIndex方法中完成。这里会提交一个高优先级,AckedClusterStateUpdateTask类型的task。索引创建需要即时得到反馈,异常这个task需要返回,会超时,而且这个任务的优先级也非常高。下面具体看一下它的execute方法,这个方法会在master执行任务时调用,这个方法非常长,主要完成以下三个功能:更新合并request,template中的mapping和setting,调用indiceService创建索引,对创建后的索引添加mapping。这一系列功能完成后,合并完成后生成新的matedata,并更新集群状态,完成了索引的创建。具体的调用方法参考上一篇。代码如下所示:

  1. @Override
  2. public ClusterState execute(ClusterState currentState) throws Exception {
  3. boolean indexCreated = false;
  4. String removalReason = null;
  5. try {
                //检查request的合法性,1.5版本主要检查index名字是否合法,如不能含有某些字符,另外就是集群节点版本
  6. validate(request, currentState);
  7. for (Alias alias : request.aliases()) {//检查别称是否合法
  8. aliasValidator.validateAlias(alias, request.index(), currentState.metaData());
  9. }
  10.  
  11. // 查找索引模板
  12. List<IndexTemplateMetaData> templates = findTemplates(request, currentState, indexTemplateFilter);
  13. Map<String, Custom> customs = Maps.newHashMap();
  14. // add the request mapping
  15. Map<String, Map<String, Object>> mappings = Maps.newHashMap();
  16. Map<String, AliasMetaData> templatesAliases = Maps.newHashMap();
  17. List<String> templateNames = Lists.newArrayList();
                //取出request中的mapping配置,虽然mapping可以后面添加,多数情况创建索引的时候还是会附带着mapping,在request中mapping是一个map
  18. for (Map.Entry<String, String> entry : request.mappings().entrySet()) {
  19. mappings.put(entry.getKey(), parseMapping(entry.getValue()));
  20. }
  21.             //一些预设如warm等
  22. for (Map.Entry<String, Custom> entry : request.customs().entrySet()) {
  23. customs.put(entry.getKey(), entry.getValue());
  24. }
  25. // 将找到的template和request中的mapping合并
  26. for (IndexTemplateMetaData template : templates) {
  27. templateNames.add(template.getName());
  28. for (ObjectObjectCursor<String, CompressedString> cursor : template.mappings()) {
  29. if (mappings.containsKey(cursor.key)) {
  30. XContentHelper.mergeDefaults(mappings.get(cursor.key), parseMapping(cursor.value.string()));
  31. } else {
  32. mappings.put(cursor.key, parseMapping(cursor.value.string()));
  33. }
  34. }
  35. // 合并custom
  36. for (ObjectObjectCursor<String, Custom> cursor : template.customs()) {
  37. String type = cursor.key;
  38. IndexMetaData.Custom custom = cursor.value;
  39. IndexMetaData.Custom existing = customs.get(type);
  40. if (existing == null) {
  41. customs.put(type, custom);
  42. } else {
  43. IndexMetaData.Custom merged = IndexMetaData.lookupFactorySafe(type).merge(existing, custom);
  44. customs.put(type, merged);
  45. }
  46. }
  47. //处理合并别名
  48. for (ObjectObjectCursor<String, AliasMetaData> cursor : template.aliases()) {
  49. AliasMetaData aliasMetaData = cursor.value;
  50. //if an alias with same name came with the create index request itself,
  51. // ignore this one taken from the index template
  52. if (request.aliases().contains(new Alias(aliasMetaData.alias()))) {
  53. continue;
  54. }
  55. //if an alias with same name was already processed, ignore this one
  56. if (templatesAliases.containsKey(cursor.key)) {
  57. continue;
  58. }
  59.  
  60. //Allow templatesAliases to be templated by replacing a token with the name of the index that we are applying it to
  61. if (aliasMetaData.alias().contains("{index}")) {
  62. String templatedAlias = aliasMetaData.alias().replace("{index}", request.index());
  63. aliasMetaData = AliasMetaData.newAliasMetaData(aliasMetaData, templatedAlias);
  64. }
  65.  
  66. aliasValidator.validateAliasMetaData(aliasMetaData, request.index(), currentState.metaData());
  67. templatesAliases.put(aliasMetaData.alias(), aliasMetaData);
  68. }
  69. }
  70.  
  71. // 合并完template和request,现在开始处理配置基本的mapping,合并逻辑跟之前相同,只是mapping来源不同
  72. File mappingsDir = new File(environment.configFile(), "mappings");
  73. if (mappingsDir.isDirectory()) {
  74. // first index level
  75. File indexMappingsDir = new File(mappingsDir, request.index());
  76. if (indexMappingsDir.isDirectory()) {
  77. addMappings(mappings, indexMappingsDir);
  78. }
  79.  
  80. // second is the _default mapping
  81. File defaultMappingsDir = new File(mappingsDir, "_default");
  82. if (defaultMappingsDir.isDirectory()) {
  83. addMappings(mappings, defaultMappingsDir);
  84. }
  85. }
  86.             //处理index的配置(setting)
  87. ImmutableSettings.Builder indexSettingsBuilder = settingsBuilder();
  88. //加入模板中的setting
  89. for (int i = templates.size() - 1; i >= 0; i--) {
  90. indexSettingsBuilder.put(templates.get(i).settings());
  91. }
  92. // 加入request中的mapping,request中设置会覆盖模板中的设置
  93. indexSettingsBuilder.put(request.settings());
                //处理shard,shard数量不能小于1,因此这里需要特殊处理,如果没有则要使用默认值
  94. if (request.index().equals(ScriptService.SCRIPT_INDEX)) {
  95. indexSettingsBuilder.put(SETTING_NUMBER_OF_SHARDS, settings.getAsInt(SETTING_NUMBER_OF_SHARDS, 1));
  96. } else {
  97. if (indexSettingsBuilder.get(SETTING_NUMBER_OF_SHARDS) == null) {
  98. if (request.index().equals(riverIndexName)) {
  99. indexSettingsBuilder.put(SETTING_NUMBER_OF_SHARDS, settings.getAsInt(SETTING_NUMBER_OF_SHARDS, 1));
  100. } else {
  101. indexSettingsBuilder.put(SETTING_NUMBER_OF_SHARDS, settings.getAsInt(SETTING_NUMBER_OF_SHARDS, 5));
  102. }
  103. }
  104. }
  105. if (request.index().equals(ScriptService.SCRIPT_INDEX)) {
  106. indexSettingsBuilder.put(SETTING_NUMBER_OF_REPLICAS, settings.getAsInt(SETTING_NUMBER_OF_REPLICAS, 0));
  107. indexSettingsBuilder.put(SETTING_AUTO_EXPAND_REPLICAS, "0-all");
  108. }
  109. else {
  110. if (indexSettingsBuilder.get(SETTING_NUMBER_OF_REPLICAS) == null) {
  111. if (request.index().equals(riverIndexName)) {
  112. indexSettingsBuilder.put(SETTING_NUMBER_OF_REPLICAS, settings.getAsInt(SETTING_NUMBER_OF_REPLICAS, 1));
  113. } else {
  114. indexSettingsBuilder.put(SETTING_NUMBER_OF_REPLICAS, settings.getAsInt(SETTING_NUMBER_OF_REPLICAS, 1));
  115. }
  116. }
  117. }
  118.             //处理副本
  119. if (settings.get(SETTING_AUTO_EXPAND_REPLICAS) != null && indexSettingsBuilder.get(SETTING_AUTO_EXPAND_REPLICAS) == null) {
  120. indexSettingsBuilder.put(SETTING_AUTO_EXPAND_REPLICAS, settings.get(SETTING_AUTO_EXPAND_REPLICAS));
  121. }
  122.  
  123. if (indexSettingsBuilder.get(SETTING_VERSION_CREATED) == null) {
  124. DiscoveryNodes nodes = currentState.nodes();
  125. final Version createdVersion = Version.smallest(version, nodes.smallestNonClientNodeVersion());
  126. indexSettingsBuilder.put(SETTING_VERSION_CREATED, createdVersion);
  127. }
  128.  
  129. if (indexSettingsBuilder.get(SETTING_CREATION_DATE) == null) {
  130. indexSettingsBuilder.put(SETTING_CREATION_DATE, System.currentTimeMillis());
  131. }
  132.  
  133. indexSettingsBuilder.put(SETTING_UUID, Strings.randomBase64UUID());
  134.             //创建setting
  135. Settings actualIndexSettings = indexSettingsBuilder.build();
                // 通过indiceservice创建索引
  136. indicesService.createIndex(request.index(), actualIndexSettings, clusterService.localNode().id());
  137. indexCreated = true;
  138. //如果创建成功这里就可以获取到对应的indexservice,否则会抛出异常
  139. IndexService indexService = indicesService.indexServiceSafe(request.index());
                //获取mappingService试图放置mapping
  140. MapperService mapperService = indexService.mapperService();
  141. // 为索引添加mapping,首先是默认mapping
  142. if (mappings.containsKey(MapperService.DEFAULT_MAPPING)) {
  143. try {
  144. mapperService.merge(MapperService.DEFAULT_MAPPING, new CompressedString(XContentFactory.jsonBuilder().map(mappings.get(MapperService.DEFAULT_MAPPING)).string()), false);
  145. } catch (Exception e) {
  146. removalReason = "failed on parsing default mapping on index creation";
  147. throw new MapperParsingException("mapping [" + MapperService.DEFAULT_MAPPING + "]", e);
  148. }
  149. }
  150. for (Map.Entry<String, Map<String, Object>> entry : mappings.entrySet()) {
  151. if (entry.getKey().equals(MapperService.DEFAULT_MAPPING)) {
  152. continue;
  153. }
  154. try {
  155. // apply the default here, its the first time we parse it
  156. mapperService.merge(entry.getKey(), new CompressedString(XContentFactory.jsonBuilder().map(entry.getValue()).string()), true);
  157. } catch (Exception e) {
  158. removalReason = "failed on parsing mappings on index creation";
  159. throw new MapperParsingException("mapping [" + entry.getKey() + "]", e);
  160. }
  161. }
  162.             //添加request中的别称
  163. IndexQueryParserService indexQueryParserService = indexService.queryParserService();
  164. for (Alias alias : request.aliases()) {
  165. if (Strings.hasLength(alias.filter())) {
  166. aliasValidator.validateAliasFilter(alias.name(), alias.filter(), indexQueryParserService);
  167. }
  168. }
  169. for (AliasMetaData aliasMetaData : templatesAliases.values()) {
  170. if (aliasMetaData.filter() != null) {
  171. aliasValidator.validateAliasFilter(aliasMetaData.alias(), aliasMetaData.filter().uncompressed(), indexQueryParserService);
  172. }
  173. }
  174.  
  175. // 以下更新Index的matedata,
  176. Map<String, MappingMetaData> mappingsMetaData = Maps.newHashMap();
  177. for (DocumentMapper mapper : mapperService.docMappers(true)) {
  178. MappingMetaData mappingMd = new MappingMetaData(mapper);
  179. mappingsMetaData.put(mapper.type(), mappingMd);
  180. }
  181.  
  182. final IndexMetaData.Builder indexMetaDataBuilder = IndexMetaData.builder(request.index()).settings(actualIndexSettings);
  183. for (MappingMetaData mappingMd : mappingsMetaData.values()) {
  184. indexMetaDataBuilder.putMapping(mappingMd);
  185. }
  186.  
  187. for (AliasMetaData aliasMetaData : templatesAliases.values()) {
  188. indexMetaDataBuilder.putAlias(aliasMetaData);
  189. }
  190. for (Alias alias : request.aliases()) {
  191. AliasMetaData aliasMetaData = AliasMetaData.builder(alias.name()).filter(alias.filter())
  192. .indexRouting(alias.indexRouting()).searchRouting(alias.searchRouting()).build();
  193. indexMetaDataBuilder.putAlias(aliasMetaData);
  194. }
  195.  
  196. for (Map.Entry<String, Custom> customEntry : customs.entrySet()) {
  197. indexMetaDataBuilder.putCustom(customEntry.getKey(), customEntry.getValue());
  198. }
  199.  
  200. indexMetaDataBuilder.state(request.state());
  201.             //matedata更新完毕,build新的matedata
  202. final IndexMetaData indexMetaData;
  203. try {
  204. indexMetaData = indexMetaDataBuilder.build();
  205. } catch (Exception e) {
  206. removalReason = "failed to build index metadata";
  207. throw e;
  208. }
  209.  
  210. indexService.indicesLifecycle().beforeIndexAddedToCluster(new Index(request.index()),
  211. indexMetaData.settings());
  212.             //更新集群的matedata,将新build的indexmatadata加入到metadata中
  213. MetaData newMetaData = MetaData.builder(currentState.metaData())
  214. .put(indexMetaData, false)
  215. .build();
  216.  
  217. logger.info("[{}] creating index, cause [{}], templates {}, shards [{}]/[{}], mappings {}", request.index(), request.cause(), templateNames, indexMetaData.numberOfShards(), indexMetaData.numberOfReplicas(), mappings.keySet());
  218.             //阻塞集群,更新matadata
  219. ClusterBlocks.Builder blocks = ClusterBlocks.builder().blocks(currentState.blocks());
  220. if (!request.blocks().isEmpty()) {
  221. for (ClusterBlock block : request.blocks()) {
  222. blocks.addIndexBlock(request.index(), block);
  223. }
  224. }
  225. if (request.state() == State.CLOSE) {
  226. blocks.addIndexBlock(request.index(), MetaDataIndexStateService.INDEX_CLOSED_BLOCK);
  227. }
  228.  
  229. ClusterState updatedState = ClusterState.builder(currentState).blocks(blocks).metaData(newMetaData).build();
  230.  
  231. if (request.state() == State.OPEN) {
  232. RoutingTable.Builder routingTableBuilder = RoutingTable.builder(updatedState.routingTable())
  233. .addAsNew(updatedState.metaData().index(request.index()));
  234. RoutingAllocation.Result routingResult = allocationService.reroute(ClusterState.builder(updatedState).routingTable(routingTableBuilder).build());
  235. updatedState = ClusterState.builder(updatedState).routingResult(routingResult).build();
  236. }
  237. removalReason = "cleaning up after validating index on master";
  238. return updatedState;
  239. } finally {
  240. if (indexCreated) {
  241. // Index was already partially created - need to clean up
  242. indicesService.removeIndex(request.index(), removalReason != null ? removalReason : "failed to create index");
  243. }
  244. }
  245. }
  246. });
  247. }

以上就是创建index的create方法,方法中主要进行了两个动作:合并更新index的matadata和创建index。更新合并matadata的过程都在上面的代码中体现了。创建索引是调用indiceSerivice构建一个guice的injector,这个injector包含了Index的所有功能(如分词,相似度等)。同时会将其存储到indiceService中,以一个map的格式存储Map<String, Tuple<IndexService, Injector>> indices。运行中的集群每次对某个索引的操作都首先从indice中获取对应的IndexService。这一部分代码如下所示:

  1. public synchronized IndexService createIndex(String sIndexName, @IndexSettings Settings settings, String localNodeId) throws ElasticsearchException {
  2. if (!lifecycle.started()) {
  3. throw new ElasticsearchIllegalStateException("Can't create an index [" + sIndexName + "], node is closed");
  4. }
  5. Index index = new Index(sIndexName);
        //检测index是否已经存在
  6. if (indices.containsKey(index.name())) {
  7. throw new IndexAlreadyExistsException(index);
  8. }
  9.  
  10. indicesLifecycle.beforeIndexCreated(index, settings);
  11. logger.debug("creating Index [{}], shards [{}]/[{}]", sIndexName, settings.get(SETTING_NUMBER_OF_SHARDS), settings.get(SETTING_NUMBER_OF_REPLICAS));
  12. Settings indexSettings = settingsBuilder()
  13. .put(this.settings)
  14. .put(settings)
  15. .classLoader(settings.getClassLoader())
  16. .build();
  17.     //构建index对应的injector
  18. ModulesBuilder modules = new ModulesBuilder();
  19. modules.add(new IndexNameModule(index));
  20. modules.add(new LocalNodeIdModule(localNodeId));
  21. modules.add(new IndexSettingsModule(index, indexSettings));
  22. modules.add(new IndexPluginsModule(indexSettings, pluginsService));
  23. modules.add(new IndexStoreModule(indexSettings));
  24. modules.add(new IndexEngineModule(indexSettings));
  25. modules.add(new AnalysisModule(indexSettings, indicesAnalysisService));
  26. modules.add(new SimilarityModule(indexSettings));
  27. modules.add(new IndexCacheModule(indexSettings));
  28. modules.add(new IndexFieldDataModule(indexSettings));
  29. modules.add(new CodecModule(indexSettings));
  30. modules.add(new MapperServiceModule());
  31. modules.add(new IndexQueryParserModule(indexSettings));
  32. modules.add(new IndexAliasesServiceModule());
  33. modules.add(new IndexGatewayModule(indexSettings, injector.getInstance(Gateway.class)));
  34. modules.add(new IndexModule(indexSettings));
  35. Injector indexInjector;
  36. try {
  37. indexInjector = modules.createChildInjector(injector);
  38. } catch (CreationException e) {
  39. throw new IndexCreationException(index, Injectors.getFirstErrorFailure(e));
  40. } catch (Throwable e) {
  41. throw new IndexCreationException(index, e);
  42. }
  43. IndexService indexService = indexInjector.getInstance(IndexService.class);
  44. indicesLifecycle.afterIndexCreated(indexService);
  45.      //将Indexservice和IndexInjector加入到indice map中
  46. indices = newMapBuilder(indices).put(index.name(), new Tuple<>(indexService, indexInjector)).immutableMap();
  47.  
  48. return indexService;
  49. }

以上方法就是具体创建索引的过程,它是在master上操作的,同时它是同步方法。这样才能保证集群的Index创建一致性,因此这也会导致之前所说的大量创建创建索引时候的速度瓶颈。但是创建大量索引的动作是不常见的,需要尽量避免。创建一个索引对于一个集群来说就是开启对于该索引的各种操作,因此这里通过guice将索引的各个功能模块注入,并获得index操作的接口类Indexservice。如果这个方法执行成功,则可以合并template及request中的mapping,并且向刚创建的索引添加合并后的mapping,最后构建新的matadata,并将集群新的matadata发送给各个节点完成索引创建。

总结:索引创建的过程包括三步:更新集群matadata,调用indiceService中创建索引,向新创建的索引中放置(合并到Index对应的mappingService中)mapping。这三步都在以上的两个方法中。完成这三步,集群中就保存了新索引的信息,同时索引配置和mapping放置也完成。索引就可以正常使用。

elasticsearch index 之 create index(二)的更多相关文章

  1. elasticsearch index 之 create index(-)

    从本篇开始,就进入了Index的核心代码部分.这里首先分析一下索引的创建过程.elasticsearch中的索引是多个分片的集合,它只是逻辑上的索引,并不具备实际的索引功能,所有对数据的操作最终还是由 ...

  2. Kibana 创建索引 POST 403 (forbidden) on create index

    一.问题描述: Kibana创建索引:kibana > management > index patterns > create index pattern 索引名称: mercha ...

  3. FOREIGN KEY 外键约束; UNIQUE和PRIMARY KEY 主键约束、CREATE INDEX建立索引的使用

    1)foreign key 是个约束,意思是说如果你给A字段设置了外键约束,以后你要往A字段插入数据,这个数据一定是要在foreign key 后面跟的那个字段中存在的值.这个的意义就是约束了数据的完 ...

  4. PostgreSQL index types and index bloating

    warehouse_db=# create table item (item_id integer not null,item_name text,item_price numeric,item_da ...

  5. Spark2.2+ES6.4.2(三十二):ES API之index的create/update/delete/open/close(创建index时设置setting,并创建index后根据avro模板动态设置index的mapping)

    要想通过ES API对es的操作,必须获取到TransportClient对象,让后根据TransportClient获取到IndicesAdminClient对象后,方可以根据IndicesAdmi ...

  6. Create Index using NEST .NET

    Hello Guys, I have a doubt about how create index using NEST .NET. I created every fields in my C# m ...

  7. CREATE INDEX - 定义一个新索引

    SYNOPSIS CREATE [ UNIQUE ] INDEX name ON table [ USING method ] ( { column | ( expression ) } [ opcl ...

  8. mysql 添加索引,ALTER TABLE和CREATE INDEX的区别

    nvicat-->mysql表设计-->创建索引. (1)使用ALTER TABLE语句创建索引,其中包括普通索引.UNIQUE索引和PRIMARY KEY索引3种创建索引的格式: PRI ...

  9. 如何使用CREATE INDEX语句对表增加索引?

    创建和删除索引索引的创建可以在CREATE TABLE语句中进行,也可以单独用CREATE INDEX或ALTER TABLE来给表增加索引.删除索引可以利用ALTER TABLE或DROP INDE ...

随机推荐

  1. Android框架-Volley(一)

    1. Volley简介 我们平时在开发Android应用的时候不可避免地都需要用到网络技术,而多数情况下应用程序都会使用HTTP协议来发送和接收网络数据.Android系统中主要提供了两种方式来进行H ...

  2. [ Git ] [ GitHub ] 如何刪除自己github上面的Repository-轉載

    http://www.winwu.cc/2013/03/githubrepository.html

  3. 使用U盘安装win8(win8.1)系统

    下载镜像 下载系统镜像,可以选32位或64位.下完后放到非系统盘(如果需要重新分区的,要先保存到移动硬盘或U盘) 使用U盘制作PE 准备一个4G以上的U盘(备份好U盘里的资料,因为刻录PE需要格式化U ...

  4. 常用模块(hashlib、suprocess、configparser)

    hashlib模块 hash是一种接受不了内容的算法,(3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法),该算 ...

  5. HNU 12961 BitTorrent DP

    题意: 你在网上下载东西,一个文件存储在一段或者多段里面,问怎么选择能在规定的流量内下载最多的文件数量.每段的大小一样. 思路: 习惯了做答案保存在DP数组里的题,做这种答案保存在下标里的题,转不过弯 ...

  6. ARM官方《CMSIS-RTOS教程》之线程Threads

    创建线程Creating Threads 一旦RTOS开始运行,就会有很多系统调用来管理和控制活跃的线程.默认情况下,main()函数自动被创建为第一个可运行的线程.在第一个例子里我们使用main() ...

  7. STM32中断名词

    1.NVIC的优先级概念    占先式优先级 (pre-emption priority):    高占先式优先级的中断事件会打断当前的主程序/中断程序运行— —抢断式优先响应,俗称中断嵌套.    ...

  8. 洛谷 P1293 班级聚会

    P1293 班级聚会 题目描述 毕业25年以后,我们的主人公开始准备同学聚会.打了无数电话后他终于搞到了所有同学的地址.他们有些人仍在本城市,但大多数人分散在其他的城市.不过,他发现一个巧合,所有地址 ...

  9. java关闭资源,自制关闭资源工具类

    在网上看到一篇关于关闭资源的正确方式:http://blog.csdn.net/bornforit/article/details/6896775 该博文中的总结: (1)使用finally块来关闭物 ...

  10. PHP Apache shutdown unexpectedly启动错误解释及解决的方法

    在学PHP的时候,偶然发现XAMPP窗体Apache的启动出现错误,出现下面的错误提示: 9:52:41  [Apache] Attempting to start Apache app... 9:5 ...