ES - 基本概念

* ES集群會在生產(chǎn)環(huán)境被長期實踐, 一些重要概念, 包括應(yīng)用和優(yōu)化調(diào)試方法值得記錄分享

* 所以, 會有關(guān)于ES的一系列分享, 先從基礎(chǔ)開始, 成體系了后再加目錄

ES:?

Written in Java, based on Lucene
Realtime analytics & Full Text Search Engine
Distributed, Easy to scale,?High availability
Multi tenant architecture (多租戶)
Document oriented(Json)
Schema Free
Restful API, Json over HTTP
Open Source
Easy to Configure

倒排:

Apache Lucene將所有信息寫到一個稱為倒排索引(inverted index)的結(jié)構(gòu)中。不同于關(guān)系型數(shù)據(jù)庫中表的處理方式,倒排索引建立索引中詞和文檔之間的映射葱跋。你可以把倒排索引看成這樣一種數(shù)據(jù)結(jié)構(gòu),其中的數(shù)據(jù)是面向詞而不是面向文檔的。來看一個簡單的例子撬讽。我們有一些文檔,只有它們的標(biāo)題字段需要被索引,它們看起來如下所示:
Elasticsearch Server 1.0 (document 1);
Mastering Elasticsearch (document 2);
Apache Solr 4 Cookbook (document 3)。

那么,簡化版的索引可以看成是這樣的:

每一個詞指向包含它的文檔編號。這樣就可以執(zhí)行一種非常高效且快速的搜索,比如基于詞的查詢往核。此外,每個詞有一個計數(shù),告訴Lucene該詞出現(xiàn)的頻率。

分析:

分析的工作, 由分詞器完成, [字符映射器] --> 分詞器(tokenizer) -----(標(biāo)記流, token stream)----> 標(biāo)記過濾器(token filter)?

token filter通常做的事情, lowercase filter, synonyms filter(同義), multiole language stemming filter(詞干)

過濾器是一個接一個處理的犁苏。所以我們通過使用多個過濾器,幾乎可以達(dá)到無限的分析可能性. 這里應(yīng)該記住的是, 索引應(yīng)該和查詢詞匹配. 如果它們不匹配,Lucene 不會返回所需文檔. 比如, 你在建立索引時使用了詞干提取和小寫, 那你應(yīng)該保證查詢中的詞也必須是詞干和小寫, 否則你的查詢不會返回任何結(jié)果.

評分:

文檔和查詢的匹配程度用公式計算的結(jié)果. Lucene默認(rèn)使用TF/IDF(詞頻/逆向文檔頻率)評分, 這是一種計算文檔在上下文中相關(guān)度的算法. ?


_id & _type & _all & _source & _index :

每個文檔存儲在一個索引中并有一個Elasticsearch自動生成的唯一標(biāo)識符和文檔類型. 文檔需要有對應(yīng)文檔類型的唯一標(biāo)識符, 這意味著在一個索引中, 兩個不同類型的文檔可以有相同的唯一標(biāo)識符.?

_id可以直接在mapping里指定用哪個字段值填充, 這個很有幫助, 有利于數(shù)據(jù)重寫和更新. _type字段也是必須的, 默認(rèn)情況下編入索引, 但不會被分析和存儲

_source可以通過includes或者excludes來指定存儲哪些字段.

_index, 用來確定文檔源自那個索引, 在使用別名時很重要. 默認(rèn)未啟用.

Elasticsearch使用文檔的唯一標(biāo)識符來計算文檔應(yīng)該被放到哪個分片中.?

從這部分的原理可以看出路由的重要性.

分片和副本:

副本的數(shù)量可以線上在集群中實時調(diào)整, 不過分片的數(shù)量一旦創(chuàng)建好, 更改分片的數(shù)量就只能另外創(chuàng)建一個新的索引重新索引數(shù)據(jù).

索引的創(chuàng)建, 在復(fù)雜系統(tǒng)往往需要控制索引的創(chuàng)建規(guī)則, 不可隨意創(chuàng)建, 通過auto_create_index的true, false和模式控制

action.auto_create_index: -ainemo*, +ai*, -* (ainemo不可以, ai開頭的可以, 不可以隨意創(chuàng)建)

模式的順序很重要, ES按順序檢查, 一旦條件成立, 則后面的無效, 所以是程序語言中順序"或" 的關(guān)系

幾個比較重要的屬性(field properties):

index: analyzed, no, not_analyzed. analyzed表示字段分析后編入索引, no表示無法搜索改字段. 字符串的話還有一個not_analyzed, 表示字符串不做上面提到的分析進入索引 (這個很重要, 在使用聚合分析的時候很有效果)

omit_norms:?true, false硬萍。對于經(jīng)過分析的字符串字段,默認(rèn)值為false,而對于未經(jīng)分析但已編入索引的字符串字段,默認(rèn)值設(shè)置為true。當(dāng)屬性為true時,它會禁用Lucene對該字段的加權(quán)基準(zhǔn)計算(norms calculation),這樣就無法使用索引期間的加權(quán),從而可以為只用于過濾器中的字段節(jié)省內(nèi)存(在計算所述文件的得分時不會被考慮在內(nèi))

boost: 文檔的加權(quán)值, 表示這個文檔中的字段的重要性, 默認(rèn)為1, 分值越高越重要. 匹配計算結(jié)果的時候很重要.

include_in_all: 是否包含在_all中, 不包含的話可以減少索引, 但不被全文檢索

通常通過字段冗余實現(xiàn)不同的業(yè)務(wù), 比如一個字段用于搜索,一個字段用于排序或一個經(jīng)語言分析器分析,一個只基于空白字符來分析.?

"name": {
? ? ? ? "type": "string",
? ? ? ? "fields": {
? ? ? ? ? ? "raw": { "type" : "string", "index": "not_analyzed" }
? ? ? ? ?}
}

上述定義將創(chuàng)建兩個字段:我們將第一個字段稱為name,第二個稱為name.raw. 當(dāng)然, 你不必在索引的過程中指定兩個獨立字段, 指定一個name字段就足夠了. Elasticsearch會處理余下的工作,將該字段的數(shù)值復(fù)制到多字段定義的所有字段围详。

相似度模型(TODO):

BM25, 基于概率模型, 簡短文本文檔表現(xiàn)較好;
隨機性偏差模型, 基于具有相同名稱的概率模型, 處理自然語言文本時表現(xiàn)好;
信息基礎(chǔ)模型, 類似與隨機性偏差.


段合并 (Segment Merging): [TODO: update it according to mastering elasticsearch]

Segment mergingis the process during which the underlying Lucene library takes several segments and creates a new segment based on the information found in them. The resulting segment has all the documents stored in the original segments except the ones that were marked for deletion. After the merge operation, the source segments are deleted from the disk. Because segment merging is rather costly in terms of CPU and I/O usage, it is crucial to appropriately control when and how often this process is invoked.

路由 (route):

默認(rèn)情況下, Elasticsearch會在所有索引的分片中均勻地分配文檔. 為了獲得文檔, Elasticsearch必須查詢所有分片并合并結(jié)果. 然而, 如果你可以把數(shù)據(jù)按照一定的依據(jù)來劃分, 就可以使用一個強大的文檔和查詢分布控制機制: 路由. 簡而言之, 它允許選擇用于索引和搜索數(shù)據(jù)的分片.

先看兩個圖, 索引和搜索

左邊是索引, 右邊是查詢. 通常來說, ES會查詢所有的節(jié)點來得到標(biāo)識符和匹配文檔的得分. 緊接著通過一個內(nèi)部請求, 發(fā)送到相關(guān)分片, 最后獲取所需文檔. 顯然效率很低, 所以一個重要的優(yōu)化就是路由, 路由可以控制文檔和查詢轉(zhuǎn)發(fā)的目的分片∑庸裕現(xiàn)在,你可能已經(jīng)猜到了,可以在索引和查詢時都指定路由值。實際上, 如果使用路由, 那么檢索和查詢階段都必須使用路由. 使用路由值之后, 查詢的請求就只會發(fā)送到單個分片上.?

實現(xiàn)來說, 可以使用相同的路由參數(shù) (路由值)來實現(xiàn):

curl -XPUT "/_id?routing=12" [索引]; curl -XGET "/_search?routing=12" [查詢]

通常的實現(xiàn)不會通過每個請求添加路由值的, 一般性做法是在類型定義時添加路由字段 (會比使用路由參數(shù)的方法慢, 因為需要額外的解析) [post是type]:


搜索:

查詢過程, 默認(rèn)分成兩個階段, Scatter (發(fā)散) 階段 和 Gather (收集) 階段

發(fā)散階段會查詢所有的shards, 得到document identifier 和文檔得分. 會等待所有查詢結(jié)束, 匯總數(shù)據(jù), 排序. 然后再通過一個內(nèi)部請求, 到相應(yīng)的shard獲得最終數(shù)據(jù), 稱為收集階段. 這個是默認(rèn)的流程, 如果我們不做任何的優(yōu)化和配置. 如何改變:
1 通過搜索類型search_type: query_then_fetch, query_and_fetch, dfs_query_and_fetch, count, scan
2 通過搜索執(zhí)行偏好preference: _primary, _primary_first, _local, _only_node:id, _shards
? ? ? ? ? 通過_search_shards可以看查詢?nèi)绾螆?zhí)行


基本查詢:

這塊的記錄其實主要是讓大家了解下ES的幾種常用查詢方式和搜索的基本原理, 簡單看看就好, 需要詳細(xì)了解的還是看官方文檔:?ES DOC

- Term query:
"term": {"title": "crime"}, term查詢是未經(jīng)分析的, 所以是完全匹配.
"terms" : {"tags": ["novel", "books"], "minimun_match": 1}, 匹配多個詞條, 可控制匹配度
- Match query:
和term的區(qū)別是, match查詢是需要分析器介入的, 比如默認(rèn)的
"match": {"title": "nemo and office"}, 會匹配所有titile含有nemo, and或office詞條的文檔,
? ? ? ? ? ? operator: or, and. 控制匹配詞條的關(guān)系, 默認(rèn)是or
? ? ? ? ? ? fuzziness: 模糊查詢的相似度
"multi_match": 多字段查詢, 結(jié)果默認(rèn)通過布爾查詢(還有最大分查詢), 結(jié)合評分高低間的平衡來計算結(jié)果
? ? ? ? "multi_match": {"query": "nemo office", "fields": ["title", "otitle"]}
"match_phrase": 類似于布爾查詢, 不過是使用分析后的文本構(gòu)建的查詢
? ? ? ? ?slop: 1, 詞條間的未知詞條數(shù)量, 所以 "nemo office" 和 "nemo and office"是匹配的
- query_string: 這個很好, 支持全部的Lucene查詢語法, 會使用一個查詢解析器構(gòu)建成實際的查詢
"query_string" : {?"query" : "title:nemo^10 +title:office -otitle:xylink +author:(+junjian +dory)",
"default_field" : "title"}
// title中包含crime并且重要程度為10, 并且希望包含office, otitle不包含xylink, 而且需要author字段包含junjian和dory詞條, ps: 還有個simple_query_string, 解析錯誤不會拋異常, 丟棄無效部分.
- 模糊查詢:
"fuzzy": {"title": "offi"}, 基于編輯距離(ED)來匹配文檔
- 通配符查詢:?
"wildcard": {"title": "off?ce"},?
查詢還有很多, 參看文檔就好.

過濾器:

post_filter, filtered, filter

過濾器類型: range, exists, missing, script
當(dāng)然, 之前講的查詢都可以封裝到過濾器中, 區(qū)別是通過過濾器返回的文檔得分都是1.0

應(yīng)該盡可能使用過濾器助赞。過濾器不影響評分,而得分計算讓搜索變得復(fù)雜,而且需要CPU資源寒砖。另一方面,過濾是一種相對簡單的操作。由于過濾應(yīng)用在整個索引的內(nèi)容上,過濾的結(jié)果獨立于找到的文檔,也獨立于文檔之間的關(guān)系嫉拐。過濾器很容易被緩存,從而進一步提高過濾查詢的整體性能

關(guān)于搜索最后,?補充一個api, 就是驗證_validate, 因為復(fù)雜的查詢經(jīng)歷了什么我們不是特別的好控制, 而且部分查詢出錯, _search依舊可以返回貌似正確的結(jié)果. 使用方法是把_search 換成 _validate, 返回結(jié)果類似于:

{
"valid": false,
"_shards": { "total": 1,??"successful": 1,?"failed": 0 }
}

想要了解出錯的具體問題, 加一個explain參數(shù) (通常還需要加一個--data-binary參數(shù), 以保留換行符, 方便定位問題), 就會知道哪些地方寫錯了.

另外, 關(guān)于查詢重寫, 數(shù)據(jù)排序以及高亮的原理, 可以看看官方文檔.


查詢性能分析:

假設(shè)在elasticsearch.yml文件中設(shè)置了以下的日志配置:

index.search.slowlog.threshold.query.warn: 10s

index.search.slowlog.threshold.query.info: 5s

index.search.slowlog.threshold.query.debug: 2s

index.search.slowlog.threshold.query.trace: 1s

并且在logging.yml配置文件中設(shè)置了以下日志級別:logger:

index.search.slowlog: TRACE, index_search_slow_log_file

注意, index.search.slowlog.threshold.query.trace屬性設(shè)置成1s, 而日志級別index.search.slowlog屬性設(shè)置成TRACE. 這意味著每當(dāng)一個查詢執(zhí)行時間查過1秒(在分片上,不是總時間)時, 它將被記錄到慢查詢?nèi)罩疚募?日志文件由logging.yml配置文件中的index_search_slow_log_file節(jié)點指定). 例如, 慢查詢?nèi)罩疚募锌赡苷业较旅娴臈l目:

[2013-01-24 13:33:05,518][TRACE][index.search.slowlog.query] [Local test] [library][1] took[1400.7ms], took_millis[1400], search_type[QUERY_THEN_FETCH], total_shards[32], source[{"query":{"match_all":{}}}], extra_source[]

可以看到, 前面的日志行包含查詢時間, 搜索類型和搜索源本身,它顯示了執(zhí)行的查詢. 當(dāng)然,你的配置文件中可能有不同的值,但慢查詢?nèi)罩究梢允且粋€很有價值的源,從中可以找到執(zhí)行時間過長的哩都、可能需要定義預(yù)熱的查詢,它們可能是父子查詢,需要獲取一些標(biāo)識符來提高性能,或者你第一次使用了一些費時的過濾器.

到這里, 我覺得已經(jīng)把ES關(guān)鍵的一些實用信息都分享到了, 如有遺漏歡迎討論.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市婉徘,隨后出現(xiàn)的幾起案子漠嵌,更是在濱河造成了極大的恐慌,老刑警劉巖盖呼,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件儒鹿,死亡現(xiàn)場離奇詭異,居然都是意外死亡几晤,警方通過查閱死者的電腦和手機约炎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蟹瘾,“玉大人圾浅,你說我怎么就攤上這事『镀樱” “怎么了狸捕?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長众雷。 經(jīng)常有香客問我灸拍,道長,這世上最難降的妖魔是什么砾省? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任鸡岗,我火速辦了婚禮,結(jié)果婚禮上编兄,老公的妹妹穿的比我還像新娘轩性。我一直安慰自己,他們只是感情好翻诉,可當(dāng)我...
    茶點故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布炮姨。 她就那樣靜靜地躺著捌刮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪舒岸。 梳的紋絲不亂的頭發(fā)上绅作,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天,我揣著相機與錄音蛾派,去河邊找鬼俄认。 笑死,一個胖子當(dāng)著我的面吹牛洪乍,可吹牛的內(nèi)容都是我干的眯杏。 我是一名探鬼主播,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼壳澳,長吁一口氣:“原來是場噩夢啊……” “哼岂贩!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起巷波,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤萎津,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后抹镊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锉屈,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年垮耳,在試婚紗的時候發(fā)現(xiàn)自己被綠了颈渊。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡终佛,死狀恐怖俊嗽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情查蓉,我是刑警寧澤乌询,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布榜贴,位于F島的核電站豌研,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏唬党。R本人自食惡果不足惜鹃共,卻給世界環(huán)境...
    茶點故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望驶拱。 院中可真熱鬧霜浴,春花似錦、人聲如沸蓝纲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至永丝,卻和暖如春锹漱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背慕嚷。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工哥牍, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人喝检。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓嗅辣,卻偏偏與公主長得像,于是被迫代替她去往敵國和親挠说。 傳聞我的和親對象是個殘疾皇子澡谭,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,509評論 2 348

推薦閱讀更多精彩內(nèi)容

  • Solr&ElasticSearch原理及應(yīng)用 一、綜述 搜索 http://baike.baidu.com/it...
    樓外樓V閱讀 7,262評論 1 17
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理损俭,服務(wù)發(fā)現(xiàn)译暂,斷路器,智...
    卡卡羅2017閱讀 134,633評論 18 139
  • 這里主要記錄一下集群使用用碰到過的要點, 以及對性能優(yōu)化比較有意義的知識點. 會逐漸完善拆解 內(nèi)存: 首先應(yīng)該記住...
    君劍閱讀 676評論 0 0
  • 你知道嗎撩炊,加菲貓里有一段話外永,有一天,加菲貓走丟了拧咳,被賣給了一家寵物店伯顶。他怕喬恩找不到他而著急,他非常痛苦骆膝。一天祭衩,喬...
    RY麥布閱讀 165評論 0 0
  • 打卡記事。 今天應(yīng)好友要求每周四替她向所在單位領(lǐng)導(dǎo)推薦一本書并寫下感悟阅签,至于推薦何書明天會集體介...
    神賜Doreen閱讀 97評論 0 0