O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.

Elasticsearch 簡介

11.847 visualizações

Publicada em

elasticsearch 的介紹,內容簡化於 Elasticseach: The Definitive Guide 中的 Getting Started 章節。除此之外也介紹了三個 elasticseach 的 rails gem

Publicada em: Software
  • Seja o primeiro a comentar

Elasticsearch 簡介

  1. 1. elasticsearch. 分散式 RESTful 全⽂文搜尋資料庫 中央資⼯工三 ⿈黃瑞安 rueiancsie@gmail.com 2015/3/10
  2. 2. 內容 • 本投影⽚片內容簡化於 Elasticsearch:The Definitive Guide 中 Getting Started 章節的: • You know, for search… • life inside a cluster • Distributed Document Store • Mapping and Analysis • Index Management • inside a shard • 除此之外也介紹了三個 elasticsearch 的 rails gem
  3. 3. elasticsearch • 分散式叢集架構,具有⾼高擴充性,可隨時增 加或移除節點,並確保資料正確 • 使⽤用 Apache Lucene 儲存 JSON ⽂文件,提供全 ⽂文搜索功能 • 所有操作均可透過 RESTful API 完成 • 跨平台,JAVA 撰寫⽽而成
  4. 4. 有誰在使⽤用?
  5. 5. Github
  6. 6. ⽤用來做什麼? 記錄 搜尋 分析
  7. 7. 安裝 • 到官網下載 zip,解壓縮後直接運⾏行執⾏行檔即 可,不需要額外設定。 • 除了 elasticsearch 本體,也可以安裝 Marvel 插 件,它提供了 web 圖形化監控介⾯面。
  8. 8. 與關聯資料庫有什麼不⼀一樣?
  9. 9. index, type? Relational DB Databases Tables Rows Columns Elasticsearch Indices Types Documents Fields • Index 的使⽤用⽅方法就相當於關聯式資料庫的 database • Type 的使⽤用⽅方法就相當於關聯式資料庫的 table • ⽂文件的 Field 就相當於關聯式資料庫的 Column
  10. 10. 快速預覽⼀一下如何使⽤用
  11. 11. 如何存⼊入資料? PUT /megacorp/employee/1 { “first_name": "John", "last_name" : "Smith", "age" : 25, "about" : "I am hero", "interests": [ "sports", "music" ] } 1. 創建 megacorp Index 2. 在裡⾯面創建⼀一個 employee type 3. 在裡⾯面建⽴立⼀一個 _id 是 1 的 JSON ⽂文件
  12. 12. 如何取得資料? GET /megacorp/employee/1 or GET /megacorp/employee/_search?q=music or GET /megacorp/_search?q=hero or ……
  13. 13. 回傳了什麼訊息? { …… "took": 4, "hits": { "total": 1, "hits": [ { "_index": "megacorp", "_type": "employee", "_id": "1", "_score": 0.095891505, "_source": { "first_name": "John", …… } } ] } }
  14. 14. 有個官⽅方的教學範例
  15. 15. Employee Directory Tutorial • Enable data to contain multi value tags, numbers, and full text. • Retrieve the full details of any employee. • Allow structured search, such as finding employees over the age of 30. • Allow simple full-text search and more-complex phrase searches. • Return highlighted search snippets from the text in the matching documents. • Enable management to build analytic dashboards over the data. • 詳細請看: http://www.elasticsearch.org/guide/en/elasticsearch/guide/current/ _finding_your_feet.html
  16. 16. ⼀一些基本⽤用語介紹
  17. 17. index, shard ? • 在 elasticsearch 中,index 這個詞不斷被使⽤用,他可能代表 下⾯面幾個意思: • index (名詞) - 類似於關聯式資料庫的 database • index (動詞) - 儲存⽂文件這個動作 • inverted index - ⼀一種適合全⽂文搜索的索引結構 • elasticsearch index 由好幾個 shard 組成,shard 是⼀一個底層 的⼯工作單元,負責實際上的⽂文件的儲存與搜尋
  18. 18. life inside a cluster
  19. 19. life inside a cluster • cluster 由⼀一個或以上具有相同 cluster.name 的 elasticsearch 節點所 組成。當有節點加⼊入或移除時,cluster 會⾃自動平均分配資料。 • cluster 中會⾃自動選出⼀一個主節點負責 cluster 性的變動,例如新 增節點或創建新 Index。 • 主節點可以不參與⽂文件操作或搜尋,因此只有⼀一個主節點不會 導致瓶頸。 • 我們可以發送請求到任⼀一節點,它會清楚在 cluster 中該如何處 理,並回傳給我們最終結果。
  20. 20. cluster 的健康狀態 • GREEN 所有的主要與複製的 shard 都是啟動的。 • YELLOW 所有的主要 shard 都是啟動的,但複製的沒有。 • RED 所有的主要與複製的 shard 都沒有啟動。 GET /_cluster/health
  21. 21. 創建 index PUT /blogs { "settings" : { "number_of_shards" : 3, "number_of_replicas" : 1 } } 創建⼀一個 blogs Index,並設定它有 3 個主要的 shard。 每⼀一個主要的 shard 總共要有⼀一個複製的 shard 在其他機器。
  22. 22. ⼀一個節點的時候 此時 cluster 健康狀態為 ⿈黃⾊色,因為沒有分配複製的 shard 到其他機器。此時 elasticsearch 可以正常運作, 但是資料若遭遇到硬體問題時無法復原。
  23. 23. 加⼊入第⼆二、第三個節點 此時 cluster 健康狀態為 綠⾊色,因所有 shard 都啟動 了。此時其中⼀一個節點遇到硬體問題都不會有影響。
  24. 24. 增加複製的 shard 如此⼀一來,壞掉兩個節點也不影響。 PUT /blogs/_settings { "number_of_replicas" : 2 }
  25. 25. 資料如何分配到 shard? 當有⽂文件要儲存進⼊入 Index 時,elasticsearch 經過上⾯面 的計算後決定要把該⽂文件儲存到哪⼀一個 shard。 routing 為任意的字串,預設為⽂文件上的 _id,可被改 為其他的值。透過改變 routing 可以決定⽂文件要儲存 到哪個 shard。 shard = hash(routing) % number_of_primary_shards
  26. 26. 當新增或刪除⽂文件的時候 1. Node 1 收到新增或刪除的請求。 2. Node 1 算出請求的⽂文件是屬於 Shard 0,因此將請求轉給 Node3。 3. 當 Node 3 完成請求時,會再將請求轉給複製的 shard 所在的 Node 1 與 Node 2,並確定它們也都完成,此請求才算是成功。
  27. 27. 當取得指定⽂文件的時候 1. Node 1 收到新增或刪除的請求。 2. Node 1 算出請求的⽂文件是在 Shard 0,⽽而三台機器都有 Shard 0,以 圖上的案例,它將請求轉給 Node 2。 3. Node 2 將⽂文件回傳給 Node1,再回傳給使⽤用者。
  28. 28. 當更新⽂文件的時候 1. Node 1 收到新增或刪除的請求。 2. Node 1 算出請求的⽂文件是屬於 Shard 0,因此將請求轉給 Node3。 3. Node 3 將⽂文件取出後更新 _source 並嘗試重新索引。此步驟可能重 複 retry_on_conflict 次數。 4. 當 Node 3 完成請求時,會再將新的⽂文件轉給複製的 shard 所在的 Node 1 與 Node 2,並確定它們也都完成,此請求才算是成功。
  29. 29. 它是如何製作搜尋索引?
  30. 30. • 假如有 12 筆 date 是 2014-xx-xx 的⽂文件。但只有⼀一個 ⽂文件的 date 是 2014-09-15。那我們發送以下請求: GET /_search?q=2014 # 12 results GET /_search?q=2014-09-15 # 12 results ! GET /_search?q=date:2014-09-15 # 1 result GET /_search?q=date:2014 # 0 results ! 怎麼結果會這麼奇怪呢?
  31. 31. 跨欄位搜尋 • 當儲存⽂文件時,elasticsearch 預設會另外儲存 ⼀一個 _all 欄位。該欄位預設由所有的欄位串接 ⽽而成,並使⽤用 inverted index 製作索引提供全 ⽂文搜索。例如: { "tweet": "However did I manage before Elasticsearch?", "date": "2014-09-14", "name": "Mary Jones", "user_id": 1 } "However did I manage before Elasticsearch? 2014-09-14 Mary Jones 1" 該⽂文件的 _all 欄位如下
  32. 32. mapping • 當有⽂文件儲存進來 時,elasticsearch 預 設會為該 type ⾃自動 產⽣生 mapping,⽤用 來決定如何製作索 引以提供搜尋。 { "gb": { "mappings": { "tweet": { "properties": { "date": { "type": "date", "format": "dateOptionalTime" }, "name": { "type": "string" }, "tweet": { "type": "string" }, "user_id": { "type": "long" } } } } } }
  33. 33. exact value 與 full text • elasticsearch 把值分成兩類:exact value 與 full text • 當針對 exact value 的欄位搜尋時,使⽤用布林判 斷,例如:Foo != foo • 當針對 full text 的欄位搜尋時,則是計算相關程 度,例如:UK 與 United Kingdom 相關、jumping 與 leap 也相關
  34. 34. inverted Index • elasticsearch ⽤用 inverted index 建⽴立索引,提供 全⽂文搜索。考慮以下兩份⽂文件: • The quick brown fox jumped over the lazy dog • Quick brown foxes leap over lazy dogs in summer
  35. 35. inverted Index • 建⽴立出來的 inverted index 看起來⼤大概像是左邊的表。 • 搜尋 ”quick brown” 的結果 如下表。 Term Doc_1 Doc_2 ------------------------- Quick | | X The | X | brown | X | X dog | X | dogs | | X fox | X | foxes | | X in | | X jumped | X | lazy | X | X leap | | X over | X | X quick | X | summer | | X the | X | ------------------------ Term Doc_1 Doc_2 ------------------------- brown | X | X quick | X | ------------------------ Total | 2 | 1
  36. 36. inverted Index • 此表還可以再優化,例如: • Quick 可以變成 quick • foxes, dogs 可以變成 fox 與 dog • jumped, leap 可以變成 jump • 這種分詞(tokenization)、正規化 (normalization)過程叫做 analysis Term Doc_1 Doc_2 ------------------------- Quick | | X The | X | brown | X | X dog | X | dogs | | X fox | X | foxes | | X in | | X jumped | X | lazy | X | X leap | | X over | X | X quick | X | summer | | X the | X | ------------------------
  37. 37. inverted Index • 優化結果如下 Term Doc_1 Doc_2 ------------------------- Quick | | X The | X | brown | X | X dog | X | dogs | | X fox | X | foxes | | X in | | X jumped | X | lazy | X | X leap | | X over | X | X quick | X | summer | | X the | X | ------------------------ Term Doc_1 Doc_2 ------------------------- brown | X | X dog | X | X fox | X | X in | | X jump | X | X lazy | X | X over | X | X quick | X | X summer | | X the | X | X ------------------------
  38. 38. analysis 與 analyzers Analysis 程序由 analyzer 完成,analyzer 由下⾯面三個功能組成: 1. Character filters ⾸首先,字串先依序經過 character filters 處理過,再進⾏行分詞。例如 可能先將 html 標籤移除,或將 & 轉換為 and。 2. Tokenizer 分詞器就是將字串切為許多有意義的單詞。 3. Token filters 每個單詞再依序經過 token filters 做最後處理。例如可能將 Quick 變成 quick、把 leap 換成 jump。
  39. 39. 中⽂文分詞 • 中⽂文做全⽂文搜索困難的地⽅方在於不好分詞。 • elasticsearch 內建的中⽂文 analyzer 效果有限。 • 建議使⽤用其他中⽂文分詞器,例如 ik 分詞器或 mmseg 分詞器 • https://github.com/medcl/elasticsearch-analysis-ik • https://github.com/medcl/elasticsearch-analysis-mmseg • 或是安裝容易的 Lucene Smart Chinese analysis 模組 • https://github.com/elasticsearch/elasticsearch-analysis-smartcn • 其他可以參考 http://www.sitepoint.com/efficient-chinese-search-elasticsearch/
  40. 40. • 假如有 12 筆 date 是 2014-xx-xx 的⽂文件。但只有⼀一個 ⽂文件的 date 是 2014-09-15。那我們發送以下請求: GET /_search?q=2014 # 12 results GET /_search?q=2014-09-15 # 12 results ! GET /_search?q=date:2014-09-15 # 1 result GET /_search?q=date:2014 # 0 results ! 1. ⽤用 2014 去全⽂文搜尋 _all 欄位 2. 2014-09-15 經過分析後變成使⽤用 2014, 09, 15 去全⽂文搜尋 _all 欄位,由於每份⽂文件都有 2014 所以全部都相關。 3. 針對 date 欄位搜尋 exact value 4. 針對 date 欄位搜尋 exact value,沒有⽂文件的 date 是 2014
  41. 41. 搜尋時要注意資料是分散的
  42. 42. 分散式搜尋 • elasticsearch 將搜尋分成兩個階段,來完成在 分散式系統中的搜尋與排序:query 與 fetch • 排序的其中⼀一個⺫⽬目的是為了分⾴頁,考慮以下 搜尋請求: GET /_search { "from": 90, "size": 10 }
  43. 43. query 階段 1. Node 3 收到搜尋請求後製作⼀一個⼤大⼩小為 from + size = 100 的 priority queue 來排序。 2. Node3將搜尋請求轉給其他每個 shard,此例為 0 號與 1 號。每個 shard 將⾃自⼰己搜尋,並⽤用 priority queue 排序出前 from + size = 100 個結果。 3. 每個 shard 將各⾃自結果的 IDs 與排序值回傳給 Node3 ,Node3 再將這些 結果加⼊入 priority quere 中。
  44. 44. fetch 階段 1. Node 3 將排序完的 IDs 取出需要的部份,即最後 10 筆,再發送 Multi- GET 請求跟⽂文件所在的 shard 取得完整的⽂文件。 2. shard 各⾃自收到請求後,取出⽂文件,若需要的話再經過處理,例如加上 metadata 與⽚片段⾼高亮,再回傳給 Node3。 3. Node3 取得所有結果後再回傳給客⼾戶端。
  45. 45. 在分散式系統中的排序與分⾴頁 • elasticsearch 搜尋結果預設只會回傳 10 個經過 _score 排序的 ⽂文件。 • 我們可以透過 size 與 from 參數,取得其他分⾴頁的結果。例如 GET /_search?size=10&from=10000 • 但是在分散式系統中分⾴頁的成本⾮非常⾼高。預設⼀一個 Index 有 五個 shard,若要取出第1000⾴頁的內容的話,必須從每個 shard 取出前 10010 個⽂文件。再將總共 50050 個結果重新排序 取出 10 個 (10001 - 10010 )。因此若要取出⼤大量資料,不建 議使⽤用排序與分⾴頁的功能。
  46. 46. scan 與 scroll • 設定 search_type=scan,這樣⼀一來 elasticsearch 不會對結果進⾏行排序。 • 設定 scroll=1m,將會對這個搜尋建⽴立快照,並維持⼀一分鐘。根據回傳的 _scroll_id 可以取得下⼀一批的結果。經由 size 參數可以設定⼀一個 shard ⼀一批最多 取多少⽂文件,因此每⼀一批取得的數量最多為 size * number_of_primary_shards • 透過 scan 與 scroll,我們可以批次取得⼤大量的⽂文件,⽽而且不會有分⾴頁成本。若 有需要重新索引整個 index 時,可以使⽤用此⽅方法完成。 GET /old_index/_search?search_type=scan&scroll=1m { "query": { "match_all": {}}, "size": 1000 }
  47. 47. 最佳化 index
  48. 48. index 設定 • 雖然 elasticsearch 在存⼊入⽂文件的時候就會⾃自動創建 index,但使⽤用預設設定可能 不是個好主意。例如: • 主要的 shard 數量不能夠被修改 • ⾃自動 mapping 可能會猜錯 • 使⽤用不符需求的 Analyzer • 這些設定都需要在儲存資料之前設定完成,否則將會需要重新索引整個 index。 • 除了⼿手動設定 index 之外,也可以使⽤用 index template ⾃自動套⽤用設定。 • mapping 的部分則可以設定 dynamic_templates ⾃自動套⽤用。
  49. 49. index 別名與 reindex • 若想要改變已經既有欄位的索引⽅方式,例如 改變 Analyzer。將需要重新索引整個 index, 否則既有的資料與新索引的不⼀一致。 • 利⽤用 Index 別名,可以做到 zero downtime 的 重新索引。
  50. 50. index 別名與 reindex • 應⽤用程式請求的 index 叫做 my_index。實際上 my_index 是個別名,指到的是 my_index_v1。 • 若要重新索引,則創建新的 my_index_v2,並 套⽤用新的設定。再透過 scan 與 scroll 將⽂文件從 my_index_v1 放⼊入 my_index_v2。 • 最後將 my_index 別名導向 my_index_v2 即可。
  51. 51. inside a shard
  52. 52. inside a shard • shard 是⼀一個低階的⼯工作單元,事實上是⼀一個 Lucene 實例,負責⽂文件的儲存與搜尋。 • inverted index 由 shard 創建,並寫⼊入硬碟,⽽而 且建⽴立好的 inverted index 不會被更改。
  53. 53. 不會被修改的 inverted index • inverted index 的不變性帶來了許多好處,如: • 當多個 processes 來讀取時,不需要鎖定 • ⼀一旦被讀⼊入系統的 cache,將會⼀一直留在 cache 中,如此⼀一來便不⽤用再讀取硬碟
  54. 54. 更新 inverted index • Lucene 帶來了 per-segment search 的概念,segment 就是⼀一個 inverted index。既有的 segment 不被改變,因此當有新⽂文件存⼊入 的時候,就建⽴立新的 segment;若更新或刪除⽂文件時,則另外將 舊⽂文件標記於.del檔案。⽽而搜尋時,就依序對各個 segment 搜尋。
  55. 55. 合併 segments • 然⽽而隨著時間經過,segment 數量愈來愈多,搜 尋成本也越⼤大。elasticsearch 會定期將 segment 合併,同時移除掉那些被標記為刪除的⽂文件。
  56. 56. 繼續學習 • 以上內容簡化於 elasticsearch: the definitive guide 的 getting started 章節,並略過搜尋相關內容,如: • searching - the basic tools • full-body search • 繼續學習搜尋相關技巧,請繼續閱讀 search in depth、aggregations 等章節。
  57. 57. Logstash, Kibana, Shield, Marvel, Hadoop • elasticsearch 有需多衍⽣生產品: • logstash - 集中收集系統 log 到 elasticsearch。 • kibana - 分析與視覺化 elasticsearch 中的資料。 • shield - 為 elasticsearch 提供⾝身份認證與傳輸加密。 • Marvel - 圖形化的 elasticsearch 監控介⾯面。 • elasticsearch 也提供 Hadoop 深度 API 整合。
  58. 58. elasticsearch + rails • ⺫⽬目前有許多 gem 可以⽅方便與 rails 整合: • chewy • searchkick • elasticsearch-rails
  59. 59. searchkick • 相當⾼高階的 elasticsearch 整合,已經完成了許多功能: • SQL like query DSL • zero downtime reindex • 根據使⽤用者與搜尋紀錄動態調整搜尋結果 • 地理位置相關搜尋 • ⾃自動完成 • “Did you mean” 建議 • 但是 searchkick ⺫⽬目前以 Model 為單位做成 elasticsearch index,跨 Model 的搜尋還在 Roadmap 中,值得關注。
  60. 60. elasticsearch-rails • elasticsearch 官⽅方的 rails 整合,功能沒有像 searchkick 那麼豐富。elasticsearch index 也是直 接跟 Model 掛勾,要製作跨 Model 搜尋⽐比較 不容易。
  61. 61. Chewy • 沒有 searchkick 那麼多⾼高階應⽤用功能,但是 index 跟 model 是獨⽴立的,要製作跨 model 的搜尋相當容易。 其他特⾊色: • zero downtime reindex • AR-style query DSL • 缺點是⺫⽬目前 Async reindexing 還在 Roadmap 中,需要 靠⾮非官⽅方的 chewy_kiqqer gem。
  62. 62. references • elasticsearch.org • elasticsearch: the definitive guide • elasticsearch: reference • searchkick • elasticsearch-rails • chewy • chewy-kiqqer

×