NO IMAGE

ES 5 新增功能

效能有關

1. Lucene 6.x 的支援

最重要的特性就是 Dimensional Point Fields,多維浮點欄位,ES裡面相關的欄位如date, numeric,ip 和 Geospatial 都將大大提升效能。

磁碟空間少一半;索引時間少一半;查詢效能提升25%;IPV6也支援了。

為什麼快?底層使用的是Block k-d trees,核心思想是將數字型別編碼成定長的位元組陣列,對定長的位元組陣列內容進行編碼排序,然後來構建二叉樹,然後依次遞迴構建,目前底層支援8個維度和最多每個維度16個位元組,基本滿足大部分場景。

索引小了之後,merge的時間也相應的減少了。
相應的Java堆記憶體佔用只原來的一半。

索引效能方面的其他優化。
ES5.0在Internal engine級別移除了用於避免同一文件併發更新的競爭鎖,帶來15%-20%的效能提升 #18060。

另一個和aggregation的改進也是非常大,Instant Aggregations。
Elasticsearch已經在Shard層面提供了Aggregation快取,如果你的資料沒有變化,ES能夠直接返回上次的快取結果,

但是有一個場景比較特殊,就是 date histogram,大家kibana上面的條件是不是經常設定的相對時間,如:from:now-30d to:now,now是一個變數在變,所以query條件一直在變,快取也就是沒有利用起來。
經過一年時間大量的重構,現在可以做到對查詢做到靈活的重寫:

首先,now關鍵字最終會被重寫成具體的值;
其次,每個shard會根據自己的資料的範圍來重寫查詢為 match_all或者是match_none查詢,所以現在的查詢能夠被有效的快取,並且只有個別資料有變化的Shard才需要重新計算,大大提升查詢速度

和Scroll相關的
新增了一個:Sliced Scroll型別
資料量很大,用Scroll遍歷資料那確實是接受不了,現在Scroll介面可以併發來進行資料遍歷了。
每個Scroll請求,可以分成多個Slice請求,可以理解為切片,各Slice獨立並行,利用Scroll重建或者遍歷要快很多倍。
這裡寫圖片描述
可以看到兩個scroll請求,id分別是0和1,max是最大可支援的並行任務,可以各自獨立進行資料的遍歷獲取。

查詢優化
新增Profile API https://www.elastic.co/guide/en/elasticsearch/reference/master/search-profile.html
要調優當然需要先監控啦,elasticsearch在很多層面都提供了stats方便你來監控調優,但是還不夠,其實很多情況下查詢速度慢很大一部分原因是糟糕的查詢引起的,玩過SQL的人都知道,資料庫服務的執行計劃(execution plan)非常有用,可以看到那些查詢走沒走索引和執行時間,用來調優,elasticsearch現在提供了Profile API來進行查詢的優化,只需要在查詢的時候開啟profile:true就可以了,一個查詢執行過程中的每個元件的效能消耗都能收集到。

各子查詢耗時多少,佔比多少,一目瞭然。
同時支援search和aggregation的profile。

深度分頁
老大難的問題,因為需要全域性排序(number_of_shards * (from size)),所以需要消耗大量記憶體。

無限制 —–> from size<1w —–> scroll

scroll問題:

  • 沒有順序,直接從底層segment進行遍歷讀取
  • 非實時,中間修改不可見

新的 Search After 機制,其實和scroll類似,也是遊標的機制,它的原理是對文件按照多個欄位進行排序,然後利用上一個結果的最後一個文件作為起始值,拿size個文件,一般我們建議使用_uid這個欄位,它的值是唯一的id。

索引與分片管理相關
新增Shrink API
https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-shrink-index.html#_shrinking_an_index

將分片數進行收縮成它的因數,如之前你是15個分片,你可以收縮成5個或者3個又或者1個,那麼我們就可以想象成這樣一種場景,在寫入壓力非常大的收集階段,設定足夠多的索引,充分利用shard的並行寫能力,索引寫完之後收縮成更少的shard,提高查詢效能。
這裡寫圖片描述
有人肯定會問慢不慢?非常快! Shrink的過程會藉助作業系統的Hardlink進行索引檔案的連結,這個操作是非常快的,毫秒級Shrink就可收縮完成,當然windows不支援hard link,需要拷貝檔案,可能就會很慢了。

新增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
這裡寫圖片描述
首先建立一個logs-0001的索引,它有一個別名是logs_write,然後我們給這個logs_write建立了一個rollover規則,即這個索引文件不超過1000個或者最多儲存7天的資料,超過會自動切換別名到logs-0002,你也可以設定索引的setting、mapping等引數,剩下的es會自動幫你處理。

新增:Reindex
藉助Reindex可以很方便的非同步進行重建,並且支援跨叢集間的資料遷移。
如按天建立的索引可以定期重建合併到以月為單位的索引裡面去。
當然索引裡面要啟用_source。

建過程中,還能對資料就行加工:
這裡寫圖片描述

跟Java開發者最相關的:RestClient

相比之前的TransportClient,版本依賴繫結,叢集升級麻煩,不支援跨Java版本的呼叫等問題,新的基於HTTP協議的客戶端對Elasticsearch的依賴解耦,沒有jar包衝突,提供了叢集節點自動發現、日誌處理、節點請求失敗自動進行請求輪詢,充分發揮Elasticsearch的高可用能力,並且效能不相上下。 #19055。

新增Wait for refresh功能

相當於是提供了文件級別的Refresh:
https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-refresh.html
之前提供了索引層面的_refresh介面,但是這個介面工作在索引層面,我們不建議頻繁去呼叫,如果你有需要修改了某個文件,需要客戶端實時可見怎麼辦?

在 5.0中,Index、Bulk、Delete、Update這些資料新增和修改的介面能夠在單個文件層面進行refresh控制了,有兩種方案可選,一種是建立一個很小的段,然後進行重新整理保證可見和消耗一定的開銷,另外一種是請求等待es的定期refresh之後再返回。
這裡寫圖片描述

新增:Ingest Node

https://www.elastic.co/guide/en/elasticsearch/reference/master/ingest.html
之前如果需要對資料進行加工,都是在索引之前進行處理,比如logstash可以對日誌進行結構化和轉換,現在直接在es就可以處理了,目前es提供了一些常用的諸如convert、grok之類的處理器,在使用的時候,先定義一個pipeline管道,裡面設定文件的加工邏輯,在建索引的時候指定pipeline名稱,那麼這個索引就會按照預先定義好的pipeline來處理了;
這裡寫圖片描述
首先建立了一個名為my-pipeline-id的處理管道,然後接下來的索引操作就可以直接使用這個管道來對foo欄位進行操作了,上面的例子是設定foo欄位為bar值。
原始欄位message被拆分成了更加結構化的物件了。

指令碼方面的改變

新增Painless Scripting

Groove指令碼開啟之後,如果被人誤用可能帶來的漏洞,為什麼呢,主要是這些外部的指令碼引擎太過於強大,什麼都能做,用不好或者設定不當就會引起安全風險,基於安全和效能方面,我們自己開發了一個新的指令碼引擎,名字就叫Painless,顧名思義,簡單安全,無痛使用,和Groove的沙盒機制不一樣,Painless使用白名單來限制函式與欄位的訪問,針對es的場景來進行優化,只做es資料的操作,更加輕量級,速度要快好幾倍,並且支援Java靜態型別,語法保持Groove類似,還支援Java的lambda表示式。

基礎架構方面的變化

新增:Task Manager

任務排程管理機制,用來做離線任務的管理,比如長時間執行的reindex和update_by_query等都是執行在TaskManager機制之上的,並且任務是可管理的,你可以隨時cancel掉,並且任務狀態持久化,支援故障恢復;

新增:Depreated logging

呼叫的介面如果已經是廢棄的介面,就會記錄下日誌

新增: Cluster allocation explain API

不知道是什麼原因,只能嘗試手動路由或者重啟節點,但是不一定能解決。
目前為什麼不能正常分配的原因,方便你去解決。

資料結構這塊,新增: half_float 型別

https://www.elastic.co/guide/en/elasticsearch/reference/master/number.html
只使用 16 位 足夠滿足大部分儲存監控數值型別的場景,支援範圍:2負24次方 到 65504,但是隻佔用float一半的儲存空間。

Aggregation新增: Matrix Stats Aggregation #18300

金融領域非常有用的,可計算多個向量元素協方差矩陣、相關係數矩陣等等

為索引寫操作新增順序號 #10708

es是在primary上寫完然後同步寫副本,這些請求都是併發的,雖然可以通過version來控制衝突,但是沒法保證其他副本的操作順序,通過寫的時候產生順序號,並且在本地也寫入checkpoint來記錄操作點,

在副本恢復的時候也可以知道當前副本的資料位置,而只需要從指定的資料開始恢復就行了,而不是像以前的粗暴的做完整的檔案同步,另外這些順序號也是持久化的,重啟後也可以快速恢復副本資訊,想想以前的大量無用拷貝吧和來回倒騰資料吧。

其他方面的改進

mapping

引入新的欄位型別Text/Keyword 來替換 String
keyword型別的資料只能完全匹配,適合那些不需要分詞的資料,對過濾、聚合非常友好,
text當然就是全文檢索需要分詞的欄位型別了。
另外string型別暫時還在的,6.0會移除。

Index Settings 的改進

配置驗證更加嚴格和保證原子性,如果其中一項失敗,那個整個都會更新請求都會失敗,不會一半成功一半失敗。下面主要說兩點:

設定可以重設會預設值,只需要設定為 null即可
獲取設定介面新增引數?include_defaults,可以直接返回所有設定和預設值

叢集處理的改進: Deleted Index Tombstones(墓碑)

在以前的es版本中,如果你的舊節點包含了部分索引資料,但是這個索引可能後面都已經刪掉了,你啟動這個節點之後,會把索引重新加到叢集中,是不是覺得有點陰魂不散,現在es5.0會在叢集狀態資訊裡面保留500個刪除的索引資訊,所以如果發現這個索引是已經刪除過的就會自動清理,不會再重複加進來了。

文件物件的改進: 欄位名重新支援英文句號,再2.0的時候移除過dot在欄位名中的支援,現在問題解決了,又重新支援了。

es會認為下面兩個文件的內容一樣:
這裡寫圖片描述

其他改進

Cluster state的修改現在會和所有節點進行ack確認。
Shard的一個副本如果失敗了,Primary標記失敗的時候會和Master節點確認完畢再返回。
使用UUID來作為索引的物理的路徑名,有很多好處,避免命名的衝突。
_timestamp 和 _ttl已經移除,需要在Ingest或者程式端處理。
ES可直接用HDFS來進行備份還原(Snapshot/Restore )了 #15191。
Delete-by-query和Update-by-query重新回到core,以前是外掛,現在可以直接使用了,也是構建在Reindex機制之上。
HTTP請求預設支援壓縮,當然http呼叫端需要在header資訊裡面傳對應的支援資訊。
建立索引不會再讓叢集變紅了,不會因為這個卡死叢集了。

預設使用BM25評分演算法,效果更佳,之前是TF/IDF。
快照Snapshots新增UUID解決衝突 #18156。
限制索引請求大小,避免大量併發請求壓垮ES #16011。
限制單個請求的shards數量,預設1000個 #17396。

移除 site plugins,就是說head、bigdesk都不能直接裝es裡面了,不過可以部署獨立站點(反正都是靜態檔案)或開發kibana外掛 #16038。

允許現有parent型別新增child型別 #17956。

支援分號(;)來分割url引數,與符號(&)一樣 #18175。

Q:ik外掛有沒有計劃支援同義詞,專有名詞熱更新?對於詞庫更新比較頻繁的應用場景,只能採取全部重新建立索引的方式嗎?
A:同義詞有單獨的filter,可以和ik結合一起使用的,關於熱更新這個確實是需要重建,詞庫變化之後,分詞產生的term不一樣了,不重建的話,倒排很可能匹配不上,查詢會失敗。

Q:老師,你好,我有個問題想諮詢一下,我們原來的商品基本資料,商品評價資料,收藏量這些都在mysql裡,但我們現在想上es,我們想把商品的基本資料放es,收藏、評價這些實時資料,還是放mysql,但做排序功能的時候,會參考一個商品的收藏量,評價量,這時候在還涉及資料分頁的情況下,怎麼結合es和mysql的資料進行排序呢?
A:這個問題得具體看業務場景,如果更新頻繁,但是還在es承受能力範圍和業務響應指標內,可以直接放es裡面,在es裡面做排序,如果太大,建議放外部儲存,外部儲存和es的結合方式又有很多種,收藏評價是否真的需要那麼實時?另外es的評分機制是可以擴充套件的,在評分階段使用自定義外掛讀取外部資料來源,進行混合打分也是可行的。

Q:請問用於計算unique count的演算法有變化嗎?
A:有的,elasticsearch裡面叫cardinality。這裡有篇文章:https://www.elastic.co/blog/count-elasticsearch

Q:請問es中的如何做到按某個欄位去重?具體問題是這樣的,我們有一個文章索引,其中有2億資料量,每次搜尋的結果總是存在大量重複的title,我們希望在查詢時能根據title進行去重。也就是Field Collapsing特性,官方有一個通過terms aggregation進行去重的方案,但效果不是很理想,仍然會有很多重複,我們希望哪怕是按title嚴格相等來去重也可以接受。 另外我們有一個通過simhash來去重的思路,就是計算title的simhash,一併存入索引,在搜尋階段通過simhash計算相似性,但這需要全量重新計算,資料量太大。所以還是希望能在不動現有索引的情況下,通過某種技巧,實現這個功能。
A:直接去重,這個目前沒有比較好的方案,不過很多變通的做法,首先你的場景需要確認,title重複是不是不允許的,如果是,那麼建索引的時候就可以hash掉作為主鍵,這樣就不會有重複的了,如果你覺得原始資料也要,那麼索引階段產生一個獨立的去除title的索引,來做join,當然還是要看你業務的場景具體研究。