1. 程式人生 > >全文搜尋儲存引擎 Elasticsearch 一點點

全文搜尋儲存引擎 Elasticsearch 一點點

開始請大家想一個問題,如何統計一個Web站點的有效PV?

針對使用者請求的URL,統計時做模式匹配-------->即使用者真正去開啟一個站點的有效頁面並對每個頁面的入口的訪問做一個統計瀏覽量;


簡要搜尋引擎

搜尋引擎在網際網路上特別多有專業(Startpage,Google,Yahoo,Baidu)等也有非專業開源(北大搜索、任何基於Lucene庫的二次開發搜尋代理引擎)等;
其重點都是用來做海量資料搜尋儲存、分析,並且根據使用者指定的filter來過濾出使用者所需要的資料。而背後所需基礎元件無外乎是 索引鏈、搜尋元件;

索引鏈:
能夠把資料收集進來,儲存下來併為其構建一個索引,即把資料收集起來構建索引;
索引鏈實現獨立步驟:檢索原始內容,根據原始內容建立文件,對文件完成索引構建等;
搜尋元件:


程式的組成部分,主要提供使用者介面(UI)比如 Elasticsearch;


核心 Lucene

  • Lucene是什麼,它能做什麼?
    • Lucene的重點是文件 如果你想操作lucene就得先給它建立“資料庫”,在“資料表”中一行一行插入資料,資料插入成功後你就可以向操作MySQL那樣來實現增刪改查操作了;
    • 如果你想了解它更多資訊可參考官方網,參考IBM站點我覺得你會理解的比較快基礎,初識Lucene;
  • Lucene 文件
    • 文件:lucene裡的文件是索引和搜尋的最原子單位,包含了一個或多個域的容器,由field+value組成;
    • 什麼叫"域":文件包含多個鍵值對,這個鍵值對就叫"域"。而一個文件可包含一個或多個鍵值對,真正搜尋是對value進行搜尋,且無需事先定義任何結構,無全域性模式;
    • 域的分析過程: 建立域時可為域指定多個選項來控制lucene在將文件新增進域索引後對該域可以執行哪些操作,此過程我們稱之為域的分析過程;
    • 域的多個選項: 即索引選項,儲存選項,項量使用選項,可單獨或組合使用;

      域索引選項:索引選項用於通過倒排索引來控制文字是否可被搜尋,如何被索引;
      Index:ANYLYZED:
      分析(切詞)並單獨作為索引項;
      Index.Not_ANYLYZED:
      不分析(不切詞),把整個文件當一個索引項;
      Index.ANYLYZED_NORMS:
      類似於Index:ANALYZED,但不儲存token的Norms(加權基準)資訊;
      Index.Not_ANYLYZED_NORMS:
      類似於Index.Not_ANYLYZED,但不儲存值的Norms(加權基準)資訊;
      Index.No:
      不對此域的值進行索引,因此不能被搜尋;
      域儲存選項:

      是否需要儲存域的真實值,如何被儲存;
      store.YES:儲存真實值,佔用儲存空間並返回真實值;
      store.NO:不儲存真實值,不佔用儲存空間;
      域向量選項:
      域向量選項用於在搜尋期間該文件所有的唯一項都能完全從文件中檢索時使用;
      文件和域的加權操作:
      搜尋時如有多個文件都出現了某個詞,我們認為即哪個文件權值更高哪個就排在前面,預設都無加權值;


在Lucene中搜索

  • 查詢Lucene索引時它返回的是一個有序(根據評分返回)的scoreDOC物件。查詢時lucene會為每個文件計算出分值/score並根據分值進行排序,如果想完成查詢就需要利用自身API來查詢;
  • Lucene 查詢API:
    IndexSearcher:搜尋索引入口
    Query及其子類:查詢及其子類
    QueryParser:查詢分析器
    TopDocs:儲存查詢分值較高的前10
    ScoreDoc:陣列
  • Lucene的多樣化查詢:在IndexSearch類中的search方法搜尋,有多種搜尋方法;
    TermQuery:對索引中的特定項進行搜尋。Term是索引中最小索引片段,每個Term包含了一個域的一個文字值
    TermRangQuery:在索引中的多個特定項中進行搜尋,能搜尋指定的多個域
    NumericRangeQuery;做數值範圍搜尋
    PrefixQuery:用來搜尋以指定字串開頭的項
    BooleanQuery:實現組合搜尋查詢,邏輯有 AND,OR,NOT
    PhraseQuery:根據位置資訊,定位文件
    WildcardQuery:萬用字元查詢
    FuzzyQuery:模糊查詢,根據模演算法計算查詢,levenshtein距離演算法
  • 在Lucene當中每個可被搜尋的文件(元件)就放在索引當中,多個文件組合就叫做索引;
  • 在Lucene當中每個索引就是一個有大量文件組合起來形成的組建,就叫做索引;
  • 在Lucene當中每個索引對應儲存在磁碟上並表現為物理檔案;
  • 在Lucene當中整個可被搜尋文件都儲存在整個索引中,可直接被搜尋;

認識 ES

  • ES是一個基於Lucene實現的開源、分散式、Restful風格的全文字搜尋引擎。實時文件儲存,對每個文件的每個field均是被索引的資料且可都被搜尋;
  • ES也是一個帶實時分析功能的分散式搜尋引擎,能夠擴充套件至數以百計的節點實時處理PB級資料;
  • Git站點,這個站點是官方的關於ES的介紹都在這裡 elastic/elasticsearch
  • ES官方的Doc文件及外掛幫助頁 Elasticsearch Reference

ES 的基本元件:

索引(index):文件容器可理解為索引是具有類似屬性的文件集合,類似於表。切記索引名必須為小寫字母;
型別(type):型別是索引內部的邏輯分割槽,其意義完全取決於使用者需求,一個索引內部可定義一個或多個型別,型別就是其擁有相同的域的文件的預定義,建議一個索引只存一類資料;
文件(document):文件是lucene索引的搜尋原子單位,它包含了一個或多個域。是域的容器;
每個域的組成部分:一個名字,一個或多個值。擁有多個值的域,通常稱為‘多值域’;
對映(mapping):原始內容儲存為文件需要事先分析(如何切詞,哪些可以過濾等)分析完後要定義這個分析,定義這個分析後讓它怎麼去根據這個定義去搜索實現,這個過程就叫對映;
例如:切詞、過濾掉某些詞等。除此之外ES還為對映提供了諸如將域中的內容排序等功能;


ES 的叢集元件:

Cluster:
ES的叢集標識為叢集名稱,預設為elasticsearch。節點就是靠此名字來決定加入到哪個叢集中。一個節點只能屬於一個叢集;
Node:
運行了單個ES例項的主機即為節點。用於儲存資料、參與叢集索引及搜尋操作,節點的標識靠‘節點名’;
Shard:
將索引切割成為的物理儲存元件,但每個shard都是一個獨立且完整的索引;建立索引時ES預設將每個索引分割為5個shard,使用者可自定義,不可更改;
shard兩個型別:
   primary shard和replica(副本),每個主shard都應該有一個副本shard,副本用於資料冗餘及查詢時的負載均衡,使用者可自定義副本動態建立多個replica;


ES 的叢集工作過程:

  • ES啟動時通過多播(預設)或單播方式監聽在TCP/9300埠下去查詢同一叢集中的其它節點,並與之建立通訊;
  • 叢集中的所有節點會選舉一個主節點負責管理整個叢集狀態,以及在叢集範圍內決定各shards的分佈方式;
     (站在使用者角度每個節點均可接收並響應使用者的各類請求,無需區分誰是主節點)
  • 叢集狀態:green、red、yellow
    • 必要時主節點會讀取各節點狀態資訊並啟動修復過程,在此過程中主節點會檢查所有可用shard的主shard並確定主shard是否存在,這時叢集狀態轉換為yellow狀態;
    • 在yellow狀態下各副本shareds均處於未分配模式(只能使用主的),副本不可用,讀請求無法執行,吞吐能力下降;
    • 要做的任務是:檢查主shard是否在,如果在再檢查副本shards是否夠數,如果主shard不在就把某個主shard的副本提升為主shard,副本不夠還要填足,等整個過程,執行完成後再從yellow轉換為green狀態;
    • 主節點每週期性檢查各節點是否線上(類似心跳資訊)並且可用狀態,任意節點不可用修復模式立刻啟動。叢集將進行重新均衡;
    • ES的選舉:在選舉主節點時會自動執行;

ES 的安裝及API:

  • 安裝jdk
    ~]# yum install -y java-1.8.0-openjdk 
    ~]# wget https://download.elastic.co/elasticsearch/elasticsearch/elasticsearch-1.7.2.noarch.rpm
    ~]# yum install -y elasticsearch-1.7.2.noarch.rpm

  • 修改配置檔案
    ~]# cp /etc/elasticsearch/elasticsearch.yml{,.bak}
    ~]# vim /etc/elasticsearch/elasticsearch.yml
    • 預設是一個節點可直接啟動,沒有切片和副本的意義,可設定 index.number_of_shards:1,index.number_of_replicas:0
    • 這裡主要說些用的配置,其它的可自行參考官方文件進行配置
       cluster name: myes 叢集名稱,各node節點就是靠此名字來決定加入哪個叢集中且一個節點只屬一個叢集
       node name:"node1" 自己節點的名字,執行單個ES例項的主機即為節點
       node.master: ture 如果被選舉是否可以是主的
       node.master: false 不參與選舉
       node.data: true 可不可以儲存資料
       index.number_of_shards:5 每一個索引預設的shards數量
       index.number_of_replicas:1 每一個shard的預設的副本
       transport.tcp.port: 9300 參與叢集時選舉的埠
       http.port: 9200 elasticsearch自身工作埠,接受使用者查詢請求埠

  • 啟動ES
    ~]# systemctl daemon-reload
    ~]# systemctl enable elasticsearch.service 
    ~]# systemctl start elasticsearch.service 
    ~]# systemctl status elasticsearch.service
    按照以上方法依次啟動其它兩個節點,即可構成ES叢集(三個節點構成ES的叢集)
    可抓包看報文傳輸狀態  tcpdump -i ens33 -nn -p tcp port 9300
    瀏覽器訪問  http://172.10.10.103:9200/

  • Elasticsearch訪問介面

監聽於 9200/tcp,使用curl命令進行互動,所有的api訪問都是以'下劃線訪問'
curl -X<verb> '<protocol>://host:port/<path>?<query_string>' -d '<body>'
 verb:http協議的請求方法 get,put,delete...
 protocol:http協議 http,https
 query_string:查詢的字串,例如:?pretty表示用易讀的JSON格式輸出
 body:請求的主體資訊


  • 確定叢集工作是否正常,可通過API檢視
    • 四種 Restful 風格的 API:
      (1) 檢查叢集、節點、索引等健康與否和獲取其相應狀態
      (2) 管理叢集、節點、索引及元資料
      (3) 執行CRUD操作(增、刪、查、改)
      (4) 執行高階操作,如:paging,filtering等

  • 給出一些示例供參考
    • 檢視elasticsearch 工作是否正常
      ~]# curl -X get 'http://localhost:9200/?preey'
      {
      "status" : 200,
      "name" : "node3",
      "cluster_name" : "myes",
      "version" : {
      "number" : "1.7.2",
      "build_hash" : "e43676b1385b8125d647f593f7202acbd816e8ec",
      "build_timestamp" : "2015-09-14T09:49:53Z",
      "build_snapshot" : false,
      "lucene_version" : "4.10.4"
      },
      "tagline" : "You Know, for Search"
      }
    • 檢視elasticsearch 叢集工作狀態(需要通過cluster介面查詢),也可使用_cat檢視
      ~]# curl -X get 'http://localhost:9200/_cat/nodes?v'
      host                  ip        heap.percent ram.percent load node.role master name
      localhost.localdomain 127.0.0.1            4          36 0.10 d         *      node3 
      host:表示主機名 
      ip:表示主機ip
      heap.percent:堆記憶體佔用記憶體量
      ram.percent:ram記憶體使用量
      load:平均負載
      node.role:節點的角色(d表示資料節點)
      master:*號表示主節點
      name:表示節點名稱
    • 獲取幫助及其它
      curl -X get 'http://localhost:9200/_cat/nodes?help' 獲取幫助
      curl -X get 'http://localhost:9200/_cat/nodes?h=name,ip,port...' 自定義欄位
      curl -X get 'http://localhost:9200/_cat/nodes' 顯示叢集中節點
      curl -X get 'http://localhost:9200/_cat/nodes?V' 顯示詳細格式


ES 外掛Plugins

外掛可擴充套件ES功能,並且使用者可根據自己需要開發擴充套件功能,比如可新增自定義的對映型別、自定義分析器、本地指令碼、自定義發現方式等;

  • ES 的外掛安裝方式有兩種(網際網路安裝、本地安裝)
    • 本地安裝:
      直接將下載後外掛包(一般zip格式)的檔案解壓出來放置於plugins目錄下即可
      ~]# tar xf marvel-latest.zip && mv mar* /usr/share/elasticsearch/plugins
      也可將下載下來的zip外掛包使用plugin指令碼進行本地安裝
      ~]# /usr/share/elasticsearch/bin/plugin -i marvel -u file:///root/marvel-latest.zip
    • 網際網路安裝:
      ~]# /usr/share/elasticsearch/bin/plugin -i marvel -u ftp://172.16.0.1/pub/elk/plugins/marvel-latest.zip
      ~]# /usr/share/elasticsearch/bin/plugin -i lukas-vlcek/bigdesk
  • 站點程式的訪問可通過_plugin介面訪問
    http://localhost:9200/_plugin/marvel
    curl -x get 'http://localhost:9200/_cat/indicies' 

ES_CRUD操作相關API(增、刪、改、查)

針對資料庫的增、刪、改、查、操作 官方文件路徑 Document APIs

  • 建立文件(PUT):
curl -XPUT 'http://172.10.10.101:9200/students/class1/1?pretty' -d '
{
"first_name": "Jing",
"last_name": "Guo",
"gender": "Male",
"age": 24,
}'
獲取文件的時候,直接給出文件而非關鍵字
curl -XGET 'http://172.10.10.101:9200/students/class1/1?pretty'  
  • 刪除文件(DELETE)
    • curl -XDELETE 'localhost:9200/students/class1/1'
    • curl -XGET 'localhost:9200/students/class1/1?pretty'
    • 刪除索引(不可逆,只能重建)
      curl -XGET 'localhost:9200/_cat/indices?v'
      curl -XDELETE 'localhost:9200/movies'
  • 更新文件(PUT 或 UPDATE)
    • 注意:直接put會覆蓋原有文件,使用update api
    • 做表單提交的方式利用update api修改文件內年齡24改為23
      [[email protected]_node1 ~]# curl -XPOST 'localhost:9200/students/class1/1/_update?pretty' -d '
      {
      "doc": { "age": 23 }
      }'
      curl -XGET 'localhost:9200/students/class1/1?pretty'

查詢資料(Query API)

Query Domain Search Language JSON based language for building complex queries
用於實現諸多型別的查詢操作如:simple term query,phrase,range boolean,fuzzy......

  • ES的查詢操作執行分為多個階段:
     分散階段:把整個查詢操作分散到shards所在的整個節點上去;
     合併階段:將所有shard的返回結果合併起來並返回給查詢者;
  • ES的查詢方式:
    • 目標向ES發起的查詢請求方式有兩種
      (1) Query String 通過Restful request API查詢;
      (2) Filter DSL 通過傳送REST request body 進行查詢;
  • 全量查詢
    • curl -XGET 'localhost:9200/students/_search?pretty'
  • Body方式查詢
    • curl -XGET 'localhost:9200/students/_search?pretty' -d '
  • 多索引多型別查詢
    /_search:所有索引查詢
    /INDEX_NAME/_search 單索引查詢
    /INDEX1,INDEX2/_search 多索引查詢
    /s*,t*/_search:
    /students/class1/_search 單型別
    /students/class1,class2/_search 多型別
  • Mapping和Analysis(對映與分析)

    ES對每一個文件會取得其所有域的所有值,生成一個名為"_all"的域。如果在query_string未指定查詢的域時則在_all域上執行查詢操作;

  • 在一個文件的所有域中搜索
    • GET /_serarch?q='Xianglong'
    • GET /_serarch?q='Xianglong%20Shiba%20Zhang'
  • 在一個文件內指定域的位置做精確搜尋
    • GET /_serarch?q=courses:'Xianglong'
    • GET /_serarch?q=courses:'Xianglong%20Shiba%20Zhang'
    • GET /_search?q=name:'Guo%20Jing'
    • curl -XGET 'localhost:9200/students/_mapping/class1?pretty'
  • 資料型別:string,numbes,boolean,dates
    • 在ES中搜索資料有兩種型別,可理解為
       type:exact:精確搜尋
      精確值:未經加工的原始值,在搜尋時進行精確匹配;
       full-text:全文搜尋
      用於引用文字中資料,判斷文件在多個程式上匹配查詢請求,即評估文件與使用者請求查詢的相關度;
    • note1:為了完成full-text全文搜尋,ES必須首先分析文字,並創建出倒排索引並且索引中將資料正規化;
    • note2:分詞+正規化操作即是分析,分析需要使用分析器來完成 analyzer;
  • ES 內建分析器
    • 分析器的組成三部分:字元過濾器,分詞器,分詞過濾器
    • 分析器可以在建立索引時用到,並且在構建查詢時也會用到
    • 內建1 Standard analyzer:標準分析器(預設),根據unicode標準分析
    • 內建2 Simple analyzer:簡單分析器,根據所有非字元進行分詞
    • 內建3 Whitespace analyzer:空白文字分析器,把空白字元去了每個都是一個單詞
    • 內建4 Languageanalyzer:適用於多種不同語言分析器
    • 注意:在構建建立索引與查詢索引必須使用相同分析器,即構建查詢要麼Standard analyzer,要麼Simple analyzer;

Query DSL

內容和知識點太多,不廢話直接給出官方站點地址 Query DSL
Elasticsearch提供了一個基於JSON的完整Query DSL來定義查詢 (Query dsl,Filter dsl)
Query DSL 在執行full-text查詢時,基於相關度來評判其匹配結果,查詢執行過程複雜且結果不快取
Filter DSL 在執行exact查詢時,基於其結果為yes或no進行評判。速度快,且結果快取

  • 合併filter和query
    • 一般可以把filter用於query上進行過濾,很少把query用在filter上,較麻煩;
      {
      "filterd":{
      query: { "match": { "gender": "Female" } }
      filter: { "term": { "age": 25 } }
      }
      }
  • 查詢語句語法檢查(valid返回true或false)
    GET /INDEX/_validate/query?pretty
    {
    ...
    }
    GET /INDEX/_validate/query?explain&pretty

ES 的另外兩個元件(查詢介面元件)

L:logstash
(日誌收集工具)可實現向產生日誌的伺服器上部署一個agent收集日誌並通過一個統一管道給集中儲存在elasticsearch元件中;
K:kibina
(nodejs開發)非常美觀的搜尋介面,能夠把使用者搜尋的語句傳送給elasticsearch由elasticsearch完成搜尋並且把結果返回;
es+logstash+kibina同屬一個組織elastic


  • Logstash介紹(JRuby研發 JVM)

    • 官方幫助文件站點地址 Doc 文件幫助頁
    • 支援索引構建、日誌收集:整合型框架支援日誌收集、分析、儲存,自有索引元件與elasticsearch不是一個量級,只用日誌收集;
    • 支援多種資料獲取機制:比如通過TCP/UDP協議、檔案、syslog、windows Eventlogs及STDIN等,獲取到資料後支援對資料過濾修改等操作;
  • Logstash工作模式(agent/server)
    • 在每個產生日誌的節點上部署個agent,通常叫運輸器;
    • 各運輸器負責收集日誌並且傳送給server端;
    • 在agent及server兩者之間部署訊息佇列來處理多節點的資料傳送接收請求(redis、msq),一般叫broker一手託兩家;
    • server端負責在佇列中每次取出一條資料,在本地做過濾修改併發送給elasticsearch叢集再發送給logstash叢集;
  • Logstash外掛
    • 知識點太多,還是官方直接看比較妥 Input plugins、Output plugins、Filter plugins、Codec plugins
  • Logstash 安裝

    input {...},filter {...},output {...},codec {...}
    • 匯出環境變數
       vim /etc/profile.d/logstash.sh
       export PATH=/opt/logstash/bin:$PATH
       source /etc/profile.d/logstash.sh
    • 語法檢查
        logstash -f /etc/logstash/conf.d/sample.conf --configtest
    • 啟動:logstash -f /etc/logstash/conf.d/sample.conf
  • logstash工作流程:input | filter | output,無需對資料進行額外處理,filter可省略;
  • es和logstash知識點太多,一定要多看官方文件

Kibina安裝


建議各元件啟動方式

  • elasticsearch 使用systemd啟動
  • logstash 使用指令碼啟動 /etc/rc.d/init.d/logstash
  • Kibana 使用&啟動在後臺執行,日誌可/dev/null