elasticstack系列之十六&elasticsearch5.xindex/create和update源码分析

星火燎原智勇 星火燎原智勇     2022-09-22     433

关键词:

开篇

  在ElasticSearch 系列十四中提到的问题即 ElasticStack系列之十四 & ElasticSearch5.x bulk update 中重复 id 性能骤降,继续这个问题再继续查看更加多的源代码,看看底层在执行 index、create 和 update 操作到底有什么不同,有什么可以使得我们使用性能更加好的。

准备

  使用 Intellij IDEA 来阅读 ElasticSearch 源码,操作相对来说比较简单。具体操作步骤如下:

1. 下载 ElasticSearch 源码

git clone https://github.com/elastic/elasticsearch.git 

2. 下载安装 gradle,确保版本在 3.3 及以上,我电脑是 macOS,自动下载最新版本为:4.2.1

brew update && brew install gradle

  在 mac 上按照上面的命令执行完毕之后它会自动安装到 /usr/local/bin/gradle , 源文件目录我到现在都没有找到,最后一怒之下直接下载对应最新版本的 zip 包,放到指定目录自己执行安装

  首先,先download最新版本的gradle,网址:http://www.gradle.org/get-started
  然后将下载下来的zip包放在你要安装的路径上,我安装在 /usr/myname/
  然后打开电脑上的.bash_profile文件,输入以下命令:

  export GRADLE_HOME=/Users/myname/gradle-4.2.1
  export PATH=$PATH:$GRADLE_HOME/bin

  然后执行命令:source ~/.bash_profile 使刚才配置生效。

3. 进入到 ElasticSearch 源码目录,在该目录下执行以下命令准备导入 IntelliJ IDEA 需要的文件

gradle idea

  以上命令执行完毕之后,打开 IntelliJ IDEA 工具它会自己进行编译,需要你配置对应的 gradle home 目录,即上面指定的 /Usrs/myname/gradle-4.2.1 ,配置完毕之后项目就算导入成功了。

  注意:

  1. 运行这个命令需要下载很多东西,有时候可能因为某一个包卡住,不要紧张,退出重新运行该命令,多尝试几次就好了。

  2. 各个版本代码上有一定的差别,但是核心代码整体是不会有大改动的,我查看的源码版本为当前最新版本:5.6.3

Index/Create 源码分析

  es index 和 create 最终都会调用 org/elasticsearch/index/engine/InternalEngine.java 中下面的方法:

  public IndexResult index(Index index) throws IOException

  注意这里的 index 中包含有要写入的 doc, 简单画下该方法的执行流程图,代码这里就不贴了

  

  请结合上面的流程图来看相应的代码,整个逻辑应该还是很清晰的,接下来我们看 planIndexingAsPrimary 的逻辑。

  private IndexingStrategy planIndexingAsPrimary(Index index) throws IOException

  这个方法最终返回一个 IndexingStrategy,即一个索引的策略,总共有如下几个策略:

  • optimizedAppendOnly
  • skipDueToVersionConflict
  • processNormally
  • overrideExistingAsIfNotThere
  • skipAsStale

  不同的策略对应了不同的处理逻辑,前面3个是常用的,我们来看下流程图。

   

  这里的第一步判断:是否是自定义 doc id? 这一步就是 es 对于日志类非自定义 doc id 的优化,感兴趣的可以自己去看下代码,简单讲就是在非自定义 id 的情况下,直接将文档 add ,否则需要 update,而 update 比 add 成本高很多。
  而第二个判断:检查版本号是否冲突? 涉及到是如何根据 文档版本号(doc version) 来确认文档可写入,代码都在 index.versionType().isVersionConflictForWrites 方法里,逻辑也比较简单,不展开讲了,感兴趣的自己去看吧。

  上面的流程图也比较清晰地列出了策略选择的逻辑,除去 optimizedAppendOnly 策略,其他都需要根据待写入文档的版本号来做出决策。接下来我们就看下获取文档版本号的方法。

  private VersionValue resolveDocVersion(final Operation op) throws IOException

 该方法逻辑比较简单,主要分为2步:

  1. 尝试从 versionMap 中读取待写入文档的 version,也即从内存中读取。versionMap 会暂存还没有 commit 到磁盘的文档版本信息。
  2. 如果第 1 步中没有读到,则从 index 中读取,也即从文件中读取。

  看到这里,开篇问题便有了答案。es 在 index 或者 create 的时候并不会 get 整个文档,而是只会获取文档的版本号做对比,而这个开销不会很大。

 Update 源码分析

  es update 的核心代码在 org/elasticsearch/action/update/UpdateHelper.java 中,具体方法如下:

public Result prepare(UpdateRequest request, IndexShard indexShard, LongSupplier nowInMillis) {
        final GetResult getResult = indexShard.getService().get(request.type(), request.id(),
                new String[]{RoutingFieldMapper.NAME, ParentFieldMapper.NAME},
                true, request.version(), request.versionType(), FetchSourceContext.FETCH_SOURCE);
        return prepare(indexShard.shardId(), request, getResult, nowInMillis);
}

 代码逻辑很清晰,分两步走:

  1. 获取待更新文档的数据
  2. 执行更新文档的操作

  第 1 步最终会调用 InternalEngine 中的 get 方法,如下:

  public GetResult get(Get get, Function<String, Searcher> searcherFactory, LongConsumer onRefresh) throws EngineExceptio

  update 操作需要先获取原始文档的原因也很简单,因为这里是允许用户做部分更新的,而 es 底层每次更新时要求必须是完整的文档(因为 lucene 的更新实际是删除老文档,新增新文档),如果不拿到原始数据的话,就不能组装出更新后的完整文档了。

  因此,比较看重效率的业务,最好还是不要用 update 这种操作,直接用上面的 index 会更好一些。

总结

  本文通过源码分析的方式解决了开篇提到的问题,答案简单总结在下面。

  es 在 index 和 create 操作的时候,如果没有自定义 doc id,那么会使用 append 优化模式,否则会获取待写入文档的版本号(doc version),进行版本检查后再决定是否写入 lucene。所以这里不会去做一个 get 操作,即获取完整的文档信息。

 

elasticstack系列之十三&联想补全策略

业务需求  1.实现搜索引擎前缀搜索功能(中文,拼音前缀查询及简拼前缀查询功能)  2.实现摘要全文检索功能,及标题加权处理功能(按照标题权值高内容权值相对低的权值分配规则,按照索引的相关性进行排序,列出前20条... 查看详情

elasticstack系列之十七&大文本搜索性能提升方案

1.什么是大文本?具体是什么?  首先需要理解,ElasticSearch建立索引完成全文检索的前提是将待检索的信息导入到ElasticSearch中。而有的信息对应的正文内容会非常的打,可能达到1MB~3MB左右字节,这个内容就认为是大文本,一... 查看详情

elasticstack系列之十五&querycache引起性能问题思考

问题描述  一个线上集群,执行的QueryDSL都是一样的,只是参数不同。统计数据显示98%~99%的查询相应速度都很快,只需要4~6ms,但是有1%左右的查询响应时间在100ms~200ms之间。集群硬件配置较高,使用的是SSD硬盘,系统可用内存... 查看详情

elasticstack系列之十九&bulk时index和create的区别

区别:  两篇文章id都一样的情况下,index是将第二篇文章覆盖第一篇;create是在第二篇插入的时候抛出一个已经存在的异常解释:  在批量请求的时候最好使用create方式进行导入。假如你批量导入一个大小为500MB的文件,中... 查看详情

elasticstack系列之十四&elasticsearch5.xbulkupdate中重复id性能骤降

  目前在绝对多数公司在使用ElasticSearch将其当做数据库使用,将多个数据库中的数据同步到ElasticSearch索引是非常常见的应用场景。那么自然而然就会涉及到数据频繁的新增和更新,而官方的文档并没有对update的底层机制做特... 查看详情

系列文章--opencv入门教程

 《OpenCV3编程入门》内容简介&勘误&配套源代码下载【OpenCV入门教程之十八】OpenCV仿射变换&SURF特征点描述合辑【OpenCV入门教程之十七】OpenCV重映射&SURF特征点检测合辑【OpenCV入门教程之十六】OpenCV角点检测之Harris... 查看详情

chrome插件(扩展)开发资料

...com/liuxianan/p/chrome-plugin-develop.html Chrome浏览器扩展开发系列2015年Chrome浏览器扩展开发系列之十九:扩展开发示例 Chrome浏览器扩展开发系列之十八:扩展的软件国际化chrome.i18nAPI Chrome浏览器扩展开发系列之十七:扩展中... 查看详情

部署packbeat--elasticstack之十

1.简介packbeat是一个开源的实时网络抓包与分析框架,内置了很多常见的协议捕获及解析,如HTTP、MySQL、Redis等。在实际使用中,通常和Elasticsearch以及kibana联合使用,用于数据搜索和分析以及数据展示。目前Packebeat支持的协议如... 查看详情

部署heartbeat--elasticstack之十一

 Heartbeat能够通过ICMP、TCP和HTTP进行ping检测,同时也支持TLS、认证和代理。可以借助简易的DNS解析,监控负载均衡服务器背后的所有主机。下载地址:https://www.elastic.co/cn/downloads/beats/heartbeat#安装Heartbeat#yuminstall-yheartbeat-7.2.0-x86_64.r... 查看详情

opencv教程

...》内容简介&勘误&配套源代码下载【OpenCV入门教程之十八】OpenCV仿射变换&SURF特征点描述合辑【OpenCV入门教程之十七】OpenCV重映射&SURF特征点检测合辑【OpenCV入门教程之十六】OpenCV角点检测之Harris角点检测【OpenCV入门... 查看详情

opencv入门教程之十六opencv角点检测之harris角点检测(代码片段)

本系列文章由@浅墨_毛星云 出品,转载请注明出处。  文章链接: http://blog.csdn.net/poem_qianmo/article/details/29356187作者:毛星云(浅墨)  微博:http://weibo.com/u/1723155442知乎:http://www 查看详情

qt基础之十六:qtconcurrent和qthreadpool

目录一.QtConcurrent1.在单独的线程中运行函数2.获取函数的返回值3.使用成员函数4.使用Lambda表达式 查看详情

qt基础之十六:qtconcurrent和qthreadpool

目录一.QtConcurrent1.在单独的线程中运行函数2.获取函数的返回值3.使用成员函数4.使用Lambda表达式 查看详情

java经典编程题50道之十六

输出九九乘法表。publicclassExample16{   publicstaticvoidmain(String[]args){      table(9);   }   publicstaticvoidtable(intn){ &n 查看详情

px4模块设计之十六:hardfault模块(代码片段)

PX4模块设计之十六:Hardfault模块1.Hardfault模块初始化2.Hardfault模块主程序3.Hardfault命令3.1hardfault_check_status3.2hardfault_rearm3.3genfault3.4hardfault_commit3.5hardfault_increment_reboot4.BBSRAM设备5.总结6.参考资料1.Ha 查看详情

opencv新手教程之十七opencv重映射&amp;surf特征点检測合辑

本系列文章由@浅墨_毛星云 出品。转载请注明出处。   文章链接: http://blog.csdn.net/poem_qianmo/article/details/30974513 作者:毛星云(浅墨)   微博:http://weibo.com/u/1723155442 知乎:http://www.zhihu.com/pe 查看详情

chrome浏览器扩展开发系列之十四

Chrome浏览器扩展开发系列之十四:本地消息机制Nativemessaging时间:2015-10-0816:17:59     阅读:1361     评论:0     收藏:0     &nbs 查看详情

实时音频编解码之十六opus解码(代码片段)

本文谢绝任何形式转载,谢谢。第五章Opus解码理论上而言,编码的逆过程就是解码,如果理解了第四章编码的内容,这里叙述解码过程显得有所多余,但是笔者在理解Opus编码原理的时候,发现编解码交叉... 查看详情