Elasticsearch之elasticsearch5.x 新特性

 

  其实,elasticsearch5.x 和 elasticsearch2.x 并不区别很大。html

  是由于,ELK里以前版本各类很混乱,直接升级到5.0了。git

  其实,elasticsearch5.x 按理来讲是elasticsearch3.x,只是为了跟随ELK总体版本的统一。github

 

 

 

 

 

       

 

 

下面给你们介绍一下 5.0 版里面的一些新的特性和改进算法

  5.0? 天啦噜,你是否是以为版本跳的太快了。数据库

  好吧,先来讲说背后的缘由吧。windows

        

  相信你们都据说 ELK 吧,是 Elasticsearch 、 Logstash 、 Kibana 三个产品的首字母缩写,如今 Elastic 又新增了一个新的开源项目成员: Beats。数组

          

 

   有人建议之后这么叫: ELKB 缓存

 

  为了将来更好的扩展性:) ELKBS?ELKBSU?.....安全

  因此咱们打算将产品线命名为 ElasticStack数据结构

  同时因为如今的版本比较混乱,每一个产品的版本号都不同, Elasticsearch和Logstash目前是2.3.4;Kibana是4.5.3;Beats是1.2.3;

        

 

 

 

  版本号太乱了有没有,什么版本的 ES 用什么版本的 Kibana ?有没有兼容性问题?

  因此咱们打算将这些的产品版本号也统一一下,即 v5.0 ,为何是 5.0 ,由于 Kibana 都 4.x 了,下个版本就只能是 5.0 了,其余产品就跟着跳跃一把,第一个 5.0 正式版将在今年的秋季发布,目前最新的测试版本是: 5.0 Alpha 4。

          

  目前各团队正在紧张的开发测试中,天天都有新的功能和改进,本次分享主要介绍一下 Elasticsearch 的主要变化。

 

 

 

 

Elasticsearch5.0新增功能

  首先来看看 5.0 里面都引入了哪些新的功能吧。

一、首先看看跟性能有关的

  1.1 第一个就是Lucene 6.x 的支持。

  Elasticsearch5.0率先集成了Lucene6版本,其中最重要的特性就是 Dimensional Point Fields,多维浮点字段,ES里面相关的字段如date, numeric,ip 和 Geospatial 都将大大提高性能。

  这么说吧,磁盘空间少一半;索引时间少一半;查询性能提高25%;IPV6也支持了。

  为何快,底层使用的是Block k-d trees,核心思想是将数字类型编码成定长的字节数组,对定长的字节数组内容进行编码排序,而后来构建二叉树,而后依次递归构建,目前底层支持8个维度和最多每一个维度16个字节,基本知足大部分场景。

  说了这么多,看图比较直接。

             

  图中从 2015 /10/32  total bytes 飙升是由于 es 启用了 docvalues ,咱们关注红线,最近的引入新的数据结构以后,红色的索引大小只有原来的一半大小。

  索引小了以后, merge 的时间也响应的减小了,看下图:

            

 

   相应的 Java 堆内存占用只原来的一半:

           

 

  1.2  再看看 索引的性能 ,也是飙升:

           

  固然 Lucene6 里面还有不少优化和改进,这里没有一一列举。

 

 

  1.3  咱们再看看索引性能方面的其余优化。

  ES5.0在Internal engine级别移除了用于避免同一文档并发更新的竞争锁,带来15%-20%的性能提高 #18060 。

          

    以上截图来自 ES 的每日持续性能监控: https://benchmarks.elastic.co/index.html

 

  1.4 另外一个 和 aggregation 的改进也是很是大, Instant Aggregations。

  Elasticsearch已经在Shard层面提供了Aggregation缓存,若是你的数据没有变化,ES可以直接返回上次的缓存结果,可是有一个场景比较特殊,就是 date histogram,你们kibana上面的条件是否是常常设置的相对时间,如:from:now-30d to:now,好吧,now是一个变量,每时每刻都在变,因此query条件一直在变,缓存也就是没有利用起来。

  通过一年时间大量的重构,如今能够作到对查询作到灵活的重写:

    首先,`now`关键字最终会被重写成具体的值;

    其次  每一个shard会根据本身的数据的范围来重写查询为 `match_all`或者是`match_none`查询,因此如今的查询可以被有效的缓存,而且只有个别数据有变化的Shard才须要从新计算,大大提高查询速度。

 

 

  1.5   另外再看看和Scroll相关的吧。

  如今新增了一个:Sliced Scroll类型

  用过Scroll接口吧,很慢?若是你数据量很大,用Scroll遍历数据那确实是接受不了,如今Scroll接口能够并发来进行数据遍历了。

  每一个Scroll请求,能够分红多个Slice请求,能够理解为切片,各Slice独立并行,利用Scroll重建或者遍历要快不少倍。

  看看这个demo

              

  能够看到两个 scroll 请求, id 分别是 0 和 1 , max 是最大可支持的并行任务,能够各自独立进行数据的遍历获取。

 

 

 

 

二、咱们再看看es在查询优化这块作的工做

  2.1 新增了一个Profile API。

#https://www.elastic.co/guide/en/elasticsearch/reference/master/search-profile.html#_usage_3

  都说要致富先修路,要调优固然须要先监控啦,elasticsearch在不少层面都提供了stats方便你来监控调优,可是还不够,其实不少状况下查询速度慢很大一部分缘由是糟糕的查询引发的,玩过SQL的人都知道,数据库服务的执行计划(execution plan)很是有用,能够看到那些查询走没走索引和执行时间,用来调优,elasticsearch如今提供了Profile API来进行查询的优化,只须要在查询的时候开启profile:true就能够了,一个查询执行过程当中的每一个组件的性能消耗都能收集到。

            

 

  那个子查询耗时多少,占比多少,一目了然。

  同时支持search和aggregation的profile。

  还有一个和翻页相关的问题,就是深度分页 ,是个老大难的问题,由于须要全局排序( number_of_shards * (from + size) ),因此须要消耗大量内存,之前的 es 没有限制,有些同窗翻到几千页发现 es 直接内存溢出挂了,后面 elasticsearch 加上了限制, from+size 不能超过 1w 条,而且若是须要深度翻页,建议使用 scroll 来作。

  可是 scroll 有几个问题,第一个是没有顺序,直接从底层 segment 进行遍历读取,第二个实时性无法保证, scroll 操做有状态, es 会维持 scroll 请求的上下文一段时间,超时后才释放,另外你在 scroll 过程当中对索引数据进行了修改了,这个时候 scroll接口是拿不到的,灵活性较差, 如今有一个新的 Search After 机制,其实和 scroll 相似,也是游标的机制,它的原理是对文档按照多个字段进行排序,而后利用上一个结果的最后一个文档做为起始值,拿 size 个文档,通常咱们建议使用 _uid 这个字段,它的值是惟一的 id 。

#(Search After

https://github.com/elastic/elasticsearch/blob/148f9af5857f287666aead37f249f204a870ab39/docs/reference/search/request/search-after.asciidoc )

  来看一个Search After 的demo 吧,比较直观的理解一下:

              

 

  上面的 demo , search_after 后面带的两个参数,就是 sort 的两个结果。

  根据你的排序条件来的,三个排序条件,就传三个参数。

 

 

三、再看看跟索引与分片管理相关的新功能吧。

  3.1 新增了一个 Shrink  API

#https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-shrink-index.html#_shrinking_an_index

  相信你们都知道elasticsearch索引的shard数是固定的,设置好了以后不能修改,若是发现shard太多或者太少的问题,以前若是要设置Elasticsearch的分片数,只能在建立索引的时候设置好,而且数据进来了以后就不能进行修改,若是要修改,只能重建索引。

  如今有了Shrink接口,它可将分片数进行收缩成它的因数,如以前你是15个分片,你能够收缩成5个或者3个又或者1个,那么咱们就能够想象成这样一种场景,在写入压力很是大的收集阶段,设置足够多的索引,充分利用shard的并行写能力,索引写完以后收缩成更少的shard,提升查询性能。

  这里是一个API调用的例子

        

  上面的例子对 my_source_index 伸缩成一个分片的 my_targe_index, 使用了最佳压缩。

  有人确定会问慢不慢?很是快! Shrink的过程会借助操做系统的Hardlink进行索引文件的连接,这个操做是很是快的,毫秒级Shrink就可收缩完成,固然windows不支持hard link,须要拷贝文件,可能就会很慢了。

 

 

  再来看另一个比较有意思的新特性,除了有意思,固然还很强大。

  3.2 新增了一个Rollover API。

https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-rollover-index.html#indices-rollover-index

  前面说的这种场景对于日志类的数据很是有用,通常咱们按天来对索引进行分割(数据量更大还能进一步拆分),咱们之前是在程序里设置一个自动生成索引的模板,你们用过logstash应该就记得有这么一个模板logstash-[YYYY-MM-DD]这样的模板,如今es5.0里面提供了一个更加简单的方式:Rollover API

  API调用方式以下:

              

 

 

  从上面能够看到,首先建立一个 logs-0001 的索引,它有一个别名是 logs_write, 而后咱们给这个 logs_write 建立了一个 rollover 规则,即这个索引文档不超过 1000 个或者最多保存 7 天的数据,超过会自动切换别名到 logs-0002, 你也能够设置索引的 setting 、 mapping 等参数 , 剩下的 es 会自动帮你处理。这个特性对于存放日志数据的场景是极为友好的。

 

 

  3.3  新增:Reindex。

  另外关于索引数据,你们以前常常重建,数据源在各类场景,重建起来非常头痛,那就不得不说说如今新加的Reindex接口了,Reindex能够直接在Elasticsearch集群里面对数据进行重建,若是你的mapping由于修改而须要重建,又或者索引设置修改须要重建的时候,借助Reindex能够很方便的异步进行重建,而且支持跨集群间的数据迁移。

  好比按天建立的索引能够按期重建合并到以月为单位的索引里面去。

  固然索引里面要启用_source。

  来看看这个demo吧,重建过程当中,还能对数据就行加工。

            

 

 

  3.4  再看看跟Java开发者最相关的吧,就是 RestClient了

  5.0里面提供了第一个Java原生的REST客户端SDK,相比以前的TransportClient,版本依赖绑定,集群升级麻烦,不支持跨Java版本的调用等问题,新的基于HTTP协议的客户端对Elasticsearch的依赖解耦,没有jar包冲突,提供了集群节点自动发现、日志处理、节点请求失败自动进行请求轮询,充分发挥Elasticsearch的高可用能力,而且性能不相上下。 #19055 。

 

  

 

四、而后咱们再看看其余的特性吧:

  4.1 新增了一个 Wait for refresh 功能。

  简单来讲至关因而提供了文档级别的Refresh: https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-refresh.html。

  索引操做新增refresh参数,你们知道elasticsearch能够设置refresh时间来保证数据的实时性,refresh时间过于频繁会形成很大的开销,过小会形成数据的延时,以前提供了索引层面的_refresh接口,可是这个接口工做在索引层面,咱们不建议频繁去调用,若是你有须要修改了某个文档,须要客户端实时可见怎么办?

  在 5.0中,Index、Bulk、Delete、Update这些数据新增和修改的接口可以在单个文档层面进行refresh控制了,有两种方案可选,一种是建立一个很小的段,而后进行刷新保证可见和消耗必定的开销,另一种是请求等待es的按期refresh以后再返回。

  调用例子:

 

          

 

 

 

 

  4.2 # 新增: Ingest Node #

  #https://www.elastic.co/guide/en/elasticsearch/reference/master/ingest.html#

  再一个比较重要的特性就是IngestNode了,你们以前若是须要对数据进行加工,都是在索引以前进行处理,好比logstash能够对日志进行结构化和转换,如今直接在es就能够处理了,目前es提供了一些经常使用的诸如convert、grok之类的处理器,在使用的时候,先定义一个pipeline管道,里面设置文档的加工逻辑,在建索引的时候指定pipeline名称,那么这个索引就会按照预先定义好的pipeline来处理了;

  Demo again:

            

 

 

  上图首先建立了一个名为my-pipeline-id的处理管道,而后接下来的索引操做就能够直接使用这个管道来对foo字段进行操做了,上面的例子是设置foo字段为bar值。

  上面的还不太酷,咱们再来看另一个例子,如今有这么一条原始的日志,内容以下:

{

"message": "55.3.244.1 GET /index.html 15824 0.043”

}

  google以后得知其Grok的pattern以下:)

%{IP:client} %{WORD:method} %{URIPATHPARAM:request} %{NUMBER:bytes} %{NUMBER:duration}

  那么咱们使用Ingest就能够这么定义一个pipeline:

             

  那么经过咱们的 pipeline 处理以后的文档长什么样呢,咱们获取这个文档的内容看看:

          

 

 

  很明显,原始字段 message 被拆分红了更加结构化的对象了。

  

 

 

五、再看看脚本方面的改变

  5.1  #新增Painless Scripting#

  还记得Groove脚本的漏洞吧,Groove脚本开启以后,若是被人误用可能带来的漏洞,为何呢,主要是这些外部的脚本引擎太过于强大,什么都能作,用很差或者设置不当就会引发安全风险,基于安全和性能方面,咱们本身开发了一个新的脚本引擎,名字就叫Painless,顾名思义,简单安全,无痛使用,和Groove的沙盒机制不同,Painless使用白名单来限制函数与字段的访问,针对es的场景来进行优化,只作es数据的操做,更加轻量级,速度要快好几倍,而且支持Java静态类型,语法保持Groove相似,还支持Java的lambda表达式。

  咱们对比一下性能,看下图

          

 

 

 

  Groovy 是弱弱的绿色的那根。

  再看看如何使用:

def first = input.doc.first_name.0;

def last  = input.doc.last_name.0;

return first + " " + last;

  是否是和以前的写法差很少

  或者还能够是强类型(10倍速度于上面的动态类型)

String first = (String)((List)((Map)input.get("doc")).get("first_name")).get(0);

String last  = (String)((List)((Map)input.get("doc")).get("last_name")).get(0);

return first + " " + last;

  脚本能够在不少地方使用,好比搜索自定义评分;更新时对字段进行加工等

  如:

          

 

 

 

 

 六、再来看看基础架构方面的变化

  6.1 新增:Task Manager

  这个是5.0 引入任务调度管理机制,用来作 离线任务的管理,好比长时间运行的reindex和update_by_query等都是运行在TaskManager机制之上的,而且任务是可管理的,你能够随时cancel掉,而且任务状态持久化,支持故障恢复;

  6.2 还新增一个: Depreated logging

  你们在用ES的时候,其实有些接口可能以及打上了Depreated标签,即废弃了,在未来的某个版本中就会移除,你当前能用是由于通常废弃的接口都不会当即移除,给足够的时间迁移,可是也是须要知道哪些不能用了,要改应用代码了,因此如今有了Depreated日志,当打开这个日志以后,你调用的接口若是已是废弃的接口,就会记录下日志,那么接下来的事情你就知道你应该怎么作了。

  6.3 新增 : Cluster allocation explain API

  『谁能给我一个shard不能分配的理由』,如今有了,你们若是以前遇到过度片不能正常分配的问题,可是不知道是什么缘由,只能尝试手动路由或者重启节点,可是不必定能解决,其实里面有不少缘由,如今提供的这个explain接口就是告诉你目前为何不能正常分配的缘由,方便你去解决。

  6.4 另外在数据结构这块,新增 : half_float 类型

https://www.elastic.co/guide/en/elasticsearch/reference/master/number.html

  只使用 16 位 足够知足大部分存储监控数值类型的场景,支持范围:2负24次方 到 65504,可是只占用float一半的存储空间。

  6.5 Aggregation 新增 : Matrix Stats Aggregation # 18300

金融领域很是有用的,可计算多个向量元素协方差矩阵、相关系数矩阵等等

  6.6 另一个重要的特性:为索引写操做添加顺序号 # 10708

  你们知道es是在primary上写完而后同步写副本,这些请求都是并发的,虽然能够经过version来控制冲突,

  可是无法保证其余副本的操做顺序,经过写的时候产生顺序号,而且在本地也写入checkpoint来记录操做点,

  这样在副本恢复的时候也能够知道当前副本的数据位置,而只须要从指定的数据开始恢复就好了,而不是像之前的粗暴的作完整的文件同步 ,另外这些顺序号也是持久化的,重启后也能够快速恢复副本信息,想一想之前的大量无用拷贝吧和来回倒腾数据吧。

 

 

七、Elasticsearch5.0其余方面的改进

  7.1 咱们再看看 mapping 这块的改进 吧。

    引入新的字段类型 Text/Keyword 来替换  String

  之前的string类型被分红Text和Keyword两种类型,keyword类型的数据只能彻底匹配,适合那些不须要分词的数据,

  对过滤、聚合很是友好,text固然就是全文检索须要分词的字段类型了。将类型分开的好处就是使用起来更加简单清晰,之前须要设置analyzer和index,而且有不少都是自定义的分词器,从名称根本看不出来到底分词没有,用起来很麻烦。

  另外string类型暂时还在的,6.0会移除。

  7.2 还有关于 Index Settings 的改进

  Elasticsearch的配置实在太多,在之前的版本间,还移除过不少无用的配置,常常弄错有没有?

  如今,配置验证更加严格和保证原子性,若是其中一项失败,那个整个都会更新请求都会失败,不会一半成功一半失败。下面主要说两点:

    1.设置能够重设会默认值,只须要设置为 `null`便可

    2.获取设置接口新增参数`?include_defaults`,能够直接返回全部设置和默认值

  7.3 集群处理的改进 : Deleted Index Tombstones

  在之前的es版本中,若是你的旧节点包含了部分索引数据,可是这个索引可能后面都已经删掉了,你启动这个节点以后,会把索引从新加到集群中,是否是以为有点阴魂不散,如今es5.0会在集群状态信息里面保留500个删除的索引信息,因此若是发现这个索引是已经删除过的就会自动清理,不会再重复加进来了。

  文档对象的改进 : 字段名从新支持英文句号,再 2.0 的时候移除过 dot 在字段名中的支持,如今问题解决了,又从新支持了。

  es会认为下面两个文档的内容同样:

             

 

 

   7.4 还有其余的一些改进

  Cluster state 的修改如今会和全部节点进行 ack 确认。

  Shard 的一个副本若是失败了, Primary 标记失败的时候会和 Master 节点确认完毕再返回。

  使用 UUID 来做为索引的物理的路径名,有不少好处,避免命名的冲突。

  _timestamp 和 _ttl 已经移除,须要在 Ingest 或者程序端处理。

  ES 可直接用 HDFS 来进行备份还原( Snapshot/Restore )了 #15191 

  Delete-by-query 和 Update-by-query 从新回到 core ,之前是插件,如今能够直接使用了,也是构建在 Reindex 机制之上。(es1.x版本是直接支持,在es2.x中提取为插件,5.x继续回归直接支持)

  HTTP 请求默认支持压缩,固然 http 调用端须要在 header 信息里面传对应的支持信息。

  建立索引不会再让集群变红了,不会由于这个卡死集群了。

  默认使用 BM25 评分算法,效果更佳,以前是 TF/IDF。

  快照 Snapshots 添加 UUID 解决冲突 #18156 

  限制索引请求大小,避免大量并发请求压垮 ES #16011

  限制单个请求的 shards 数量,默认 1000 个 #17396

  移除 site plugins ,就是说 head 、 bigdesk 都不能直接装 es 里面了,不过能够部署独立站点(反正都是静态文件)或开发 kibana 插件 #16038 

  容许现有 parent 类型新增 child 类型 #17956

  这个功能对于使用parent-child特性的人应该很是有用。

  支持分号(;)来分割 url 参数,与符号( & )同样 #18175 

  好比下面这个例子:

curl http://localhost:9200/_cluster/health?level=indices;pretty=true

  好吧,貌似不少,其实上面说的还只是众多特性和改进的一部分, es5.0 作了很是很是多工做,原本还打算讲讲 bug 修复的,可是太多了,时间有限, 一些重要的 bug在 2.x 都已经第一时间解决了。

 

 

 

 

 

八、你们能够查看下面的连接了解更多更详细的更新日志

https://www.elastic.co/guide/en/elasticsearch/reference/master/release-notes-5.0.0-alpha1-2x.html

https://www.elastic.co/guide/en/elasticsearch/reference/master/release-notes-5.0.0-alpha1.html

https://www.elastic.co/guide/en/elasticsearch/reference/master/release-notes-5.0.0-alpha2.html

https://www.elastic.co/guide/en/elasticsearch/reference/master/release-notes-5.0.0-alpha3.html

https://www.elastic.co/guide/en/elasticsearch/reference/master/release-notes-5.0.0-alpha4.html

 

下载体验最新的版本 : https://www.elastic.co/v5

升级向导:https://github.com/elastic/elasticsearch-migration/blob/2.x/README.asciidoc

相关文章
相关标签/搜索