全文搜索存儲引擎 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
      [root@es_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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章