ES(一): 架構及原理

      Elasticsearch 是一個兼有搜索引擎NoSQL數據庫功能的開源系統,基於Java/Lucene構建,能夠用於全文搜索結構化搜索以及近實時分析。能夠說Lucene是當今最早進,最高效的全功能開源搜索引擎框架。 說明: Lucene:只是一個框架,要充分利用它的功能,須要使用JAVA,而且在程序中集成Lucene,學習成本高,Lucene確實很是複雜。 Elasticsearch 是 面向文檔型數據庫,這意味着它存儲的是整個對象或者 文檔,它不但會存儲它們,還會爲他們創建索引,這樣你就能夠搜索他們了html

目錄:node

  • 應用場景
  • solr VS ES
  • 核心概念
  • ES模塊結構
  • 分片示例

應用場景web


  • 站內搜索:主要和 Solr 競爭,屬於後起之秀
  • NoSQL json文檔數據庫:主要搶佔 Mongo 的市場,它在讀寫性能上優於 Mongo ,同時也支持地理位置查詢,還方便地理位置和文本混合查詢,屬於歪打正着 (對比測試參見:http://blog.quarkslab.com/mongodb-vs-elasticsearch-the-quest-of-the-holy-performances.html
  • 監控:統計以及日誌類時間序的數據的存儲和分析以及可視化,這方面是引領者
  • 國外:Wikipedia使用 ES 提供全文搜索並高亮關鍵字、StackOverflow結合全文搜索與地理位置查詢、Github使用Elasticsearch檢索1300億行的代碼
  • 國內:百度(在casio、雲分析、網盟、預測、文庫、直達號、錢包、風控等業務上都應用了ES,單集羣天天導入30TB+數據,總共天天60TB+)、新浪 (見大數據架構--log,阿里巴巴、騰訊等公司均有對ES的使用
  • 使用比較普遍的平臺ELK(ElasticSearch, Logstash, Kibana)

solr VS ESmongodb


  • Solr是Apache Lucene項目的開源企業搜索平臺。其主要功能包括全文檢索、命中標示、分面搜索、動態聚類、數據庫集成,以及富文本(如Word、PDF)的處理。
  • Solr是高度可擴展的,並提供了分佈式搜索和索引複製。Solr是最流行的企業級搜索引擎,Solr4 還增長了NoSQL支持。
  • Solr是用Java編寫、運行在Servlet容器(如 Apache Tomcat 或Jetty)的一個獨立的全文搜索服務器。 Solr採用了 Lucene Java 搜索庫爲核心的全文索引和搜索,並具備相似REST的HTTP/XML和JSON的API。
  • Solr強大的外部配置功能使得無需進行Java編碼,即可對 其進行調整以適應多種類型的應用程序。Solr有一個插件架構,以支持更多的高級定製
  • Elasticsearch 與 Solr 的比較總結
    1. 兩者安裝都很簡單
    2. Solr 利用 Zookeeper 進行分佈式管理,而 Elasticsearch 自身帶有分佈式協調管理功能
    3. Solr 支持更多格式的數據,而 Elasticsearch 僅支持json文件格式
    4. Solr 官方提供的功能更多,而 Elasticsearch 自己更注重於核心功能,高級功能多有第三方插件提供
    5. Solr 在傳統的搜索應用中表現好於 Elasticsearch,但在處理實時搜索應用時效率明顯低於 Elasticsearch
    6. Solr 是傳統搜索應用的有力解決方案,但 Elasticsearch 更適用於新興的實時搜索應用

核心概念數據庫


  • 集羣(Cluster): 包含一個或多個具備相同 cluster.name 的節點.
    1. 集羣內節點協同工做,共享數據,並共同分擔工做負荷。
    2. 因爲節點是從屬集羣的,集羣會自我重組來均勻地分發數據
    3. cluster Name是很重要的,由於每一個節點只能是羣集的一部分,當該節點被設置爲相同的名稱時,就會自動加入羣集
    4. 集羣中經過選舉產生一個mater節點,它將負責管理集羣範疇的變動,例如建立或刪除索引,添加節點到集羣或從集羣刪除節點。master 節點無需參與文檔層面的變動和搜索,這意味着僅有一個 master 節點並不會因流量增加而成爲瓶頸。任意一個節點均可以成爲 master 節點。咱們例舉的集羣只有一個節點,所以它會扮演 master 節點的角色。
    5. 做爲用戶,咱們能夠訪問包括 master 節點在內的集羣中的任一節點。每一個節點都知道各個文檔的位置,並可以將咱們的請求直接轉發到擁有咱們想要的數據的節點。不管咱們訪問的是哪一個節點,它都會控制從擁有數據的節點收集響應的過程,並返回給客戶端最終的結果。這一切都是由 Elasticsearch 透明管理的
  • 節點(node): 一個節點是一個邏輯上獨立的服務,能夠存儲數據,並參與集羣的索引和搜索功能, 一個節點也有惟一的名字,羣集經過節點名稱進行管理和通訊.
  • 索引(Index): 索引與關係型數據庫實例(Database)至關。索引只是一個 邏輯命名空間,它指向一個或多個分片(shards),內部用Apache Lucene實現索引中數據的讀寫
  • 文檔類型(Type):至關於數據庫中的table概念。每一個文檔在ElasticSearch中都必須設定它的類型。文檔類型使得同一個索引中在存儲結構不一樣文檔時,只須要依據文檔類型就能夠找到對應的參數映射(Mapping)信息,方便文檔的存取
  • 文檔(Document) :至關於數據庫中的row, 是能夠被索引的基本單位。例如,你能夠有一個的客戶文檔,有一個產品文檔,還有一個訂單的文檔。文檔是以JSON格式存儲的。在一個索引中,您能夠存儲多個的文檔。請注意,雖然在一個索引中有多分文檔,但這些文檔的結構是一致的,並在第一次存儲的時候指定, 文檔屬於一種 類型(type),各類各樣的類型存在於一個 索引 中。你也能夠經過類比傳統的關係數據庫獲得一些大體的類似之處:
    關係數據庫       ⇒ 數據庫 ⇒ 表    ⇒ 行    ⇒ 列(Columns)
    Elasticsearch  ⇒ 索引   ⇒ 類型  ⇒ 文檔   ⇒ 字段(Fields)
  • 模擬示意圖如:
  • Mapping: 至關於數據庫中的schema,用來約束字段的類型,不過 Elasticsearch 的 mapping 能夠自動根據數據建立
  • 分片(shard) :是 工做單元(worker unit) 底層的一員,用來分配集羣中的數據,它只負責保存索引中全部數據的一小片。
    1. 分片是一個獨立的Lucene實例,而且它自身也是一個完整的搜索引擎。
    2. 文檔存儲而且被索引在分片中,可是咱們的程序並不會直接與它們通訊。取而代之,它們直接與索引進行通訊的
    3. 分片想象成一個數據的容器數據被存儲在分片中,而後分片又被分配在集羣的節點上。當你的集羣擴展或者縮小時,elasticsearch 會自動的在節點之間遷移分配分片,以便集羣保持均衡
    4. 分片分爲 主分片(primary shard) 以及 從分片(replica shard) 兩種。在你的索引中,每個文檔都屬於一個主分片
    5. 分片只是主分片的一個副本,它用於提供數據的冗餘副本,在硬件故障時提供數據保護,同時服務於搜索和檢索這種只讀請求
    6. 索引中的主分片的數量在索引建立後就固定下來了,可是從分片的數量能夠隨時改變。
    7. 一個索引默認設置了5個主分片,每一個主分片有一個從分片對應

ES模塊結構json


  • 模塊結構圖以下
  • Gateway: 表明ES的持久化存儲方式,包含索引信息,ClusterState(集羣信息),mapping,索引碎片信息,以及transaction log等
    1. 對於分佈式集羣來講,當一個或多個節點down掉了,可以保證咱們的數據不能丟,最通用的解放方案就是對失敗節點的數據進行復制,經過控制複製的份數能夠保證集羣有很高的可用性,複製這個方案的精髓主要是保證操做的時候沒有單點,對一個節點的操做會同步到其餘的複製節點上去。
    2. ES一個索引會拆分紅多個碎片每一個碎片能夠擁有一個或多個副本(建立索引的時候能夠配置),這裏有個例子,每一個索引分紅3個碎片,每一個碎片有2個副本,以下:
      $ curl -XPUT http://localhost:9200/twitter/ -d ' index : number_of_shards : 3 number_of_replicas : 2
    3. 每一個操做會自動路由主碎片所在的節點,在上面執行操做,而且同步到其餘複製節點,經過使用「non blocking IO」模式全部複製的操做都是並行執行的,也就是說若是你的節點的副本越多,你網絡上的流量消耗也會越大。複製節點一樣接受來自外面的讀操做,意義就是你的複製節點越多,你的索引的可用性就越強,對搜索的可伸縮行就更好,可以承載更多的操做服務器

    4. 第一次啓動的時候,它會去持久化設備讀取集羣的狀態信息(建立的索引,配置等)而後執行應用它們(建立索引,建立mapping映射等),每一次shard節點第一次實例化加入複製組,它都會從長持久化存儲裏面恢復它的狀態信息
  • Lucence Directory:  是lucene的框架服務發現以及選主 ZenDiscovery: 用來實現節點自動發現,還有Master節點選取,假如Master出現故障,其它的這個節點會自動選舉,產生一個新的Master
    1. 它是Lucene存儲的一個抽象,由此派生了兩個類:FSDirectory和RAMDirectory,用於控制索引文件的存儲位置。使用FSDirectory類,就是存儲到硬盤;使用RAMDirectory類,則是存儲到內存
    2. 一個Directory對象是一份文件的清單。文件可能只在被建立的時候寫一次。一旦文件被建立,它將只被讀取或者刪除。在讀取的時候進行寫入操做是容許的
  • Discovery
    1. 節點啓動後先ping(這裏的ping是 Elasticsearch 的一個RPC命令。若是 discovery.zen.ping.unicast.hosts 有設置,則ping設置中的host,不然嘗試ping localhost 的幾個端口, Elasticsearch 支持同一個主機啓動多個節點)
    2. Ping的response會包含該節點的基本信息以及該節點認爲的master節點
    3. 選舉開始,先從各節點認爲的master中選,規則很簡單,按照id的字典序排序,取第一個
    4. 若是各節點都沒有認爲的master,則從全部節點中選擇,規則同上。這裏有個限制條件就是 discovery.zen.minimum_master_nodes,若是節點數達不到最小值的限制,則循環上述過程,直到節點數足夠能夠開始選舉
    5. 最後選舉結果是確定能選舉出一個master,若是隻有一個local節點那就選出的是本身
    6. 若是當前節點是master,則開始等待節點數達到 minimum_master_nodes,而後提供服務, 若是當前節點不是master,則嘗試加入master.
    7. ES支持任意數目的集羣(1-N),因此不能像 Zookeeper/Etcd 那樣限制節點必須是奇數,也就沒法用投票的機制來選主,而是經過一個規則,只要全部的節點都遵循一樣的規則,獲得的信息都是對等的,選出來的主節點確定是一致的. 但分佈式系統的問題就出在信息不對等的狀況,這時候很容易出現腦裂(Split-Brain)的問題,大多數解決方案就是設置一個quorum值,要求可用節點必須大於quorum(通常是超過半數節點),才能對外提供服務。而 Elasticsearch 中,這個quorum的配置就是 discovery.zen.minimum_master_nodes
  • memcached
    1. 經過memecached協議來訪問ES的接口,支持二進制和文本兩種協議.經過一個名爲transport-memcached插件提供
    2. Memcached命令會被映射到REST接口,而且會被一樣的REST層處理,memcached命令列表包括:get/set/delete/quit
  • River : 表明es的一個數據源,也是其它存儲方式(如:數據庫)同步數據到es的一個方法。它是以插件方式存在的一個es服務,經過讀取river中的數據並把它索引到es中,官方的river有couchDB的,RabbitMQ的,Twitter的,Wikipedia的,river這個功能將會在後面的文件中重點說到

分片示例網絡


  • 啓用一個既沒有數據,也沒有索引的單一節點, 以下圖
  • 在空的單節點集羣中上建立一個叫作 blogs 的索引,設置3個主分片和一組從分片(每一個主分片有一個從分片對應),代碼以下:
    PUT /blogs { "settings" : { "number_of_shards" : 3, "number_of_replicas" : 1 } }
  •  集羣示例圖以下: (此時集羣健康狀態爲: yellow   三個從分片尚未被分配到節點上)架構

  •    
  • 主分片(primary shards) 啓動而且運行了,這時集羣已經能夠成功的處理任意請求,可是 從分片(replica shards) 沒有徹底被激活。事實上,當前這三個從分片都處於 unassigned(未分配)的狀態,它們還未被分配到節點上。在同一個節點上保存相同的數據副本是沒有必要的,若是這個節點故障了,就等同於全部的數據副本也丟失了
  • 啓動第二個節點,配置第二個節點與第一個節點的 cluster.name 相同(./config/elasticsearch.yml文件中的配置),它就能自動發現並加入到第一個節點的集羣中,以下圖:
  •   
  • cluster-health 的狀態爲 green,這意味着全部的6個分片(三個主分片和三個從分片)都已激活,文檔在主節點和從節點上都能被檢索
  • 隨着應用需求的增加,啓動第三個節點進行橫向擴展,集羣內會自動重組,如圖
  • 在 Node 1 和 Node 2 中分別會有一個分片被移動到 Node 3 上,這樣一來,每一個節點上就都只有兩個分片了。這意味着每一個節點的硬件資源(CPU、RAM、I/O)被更少的分片共享,因此每一個分片就會有更好的性能表現
  • 一共有6個分片(3個主分片和3個從分片),所以最多能夠擴展到6個節點,每一個節點上有一個分片,這樣每一個分片均可以使用到所在節點100%的資源了
  • 主分片的數量在索引建立的時候就已經指定了,實際上,這個數字定義了能存儲到索引中的數據最大量(具體的數量取決於你的數據,硬件的使用狀況)。例如,讀請求——搜索或者文檔恢復就能夠由主分片或者從分片來執行,因此當你擁有更多份數據的時候,你就擁有了更大的吞吐量
  • 從分片的數量能夠在運行的集羣中動態的調整,這樣咱們就能夠根據實際需求擴展或者縮小規模。接下來,咱們來增長一下從分片組的數量:
    PUT /blogs/_settings { "number_of_replicas" : 2 }
  •  如今 blogs 的索引總共有9個分片:3個主分片和6個從分片, 又會變成一個節點一個分片的狀態了,最終獲得了三倍搜索性能的三節點集羣app

  • 說明:僅僅是在一樣數量的節點上增長從分片的數量是根本不能提升性能的,由於每一個分片都有訪問系統資源的權限。你須要升級硬件配置以提升吞吐量。
  • 嘗試一下,把第一個節點殺掉,咱們的集羣就會以下圖所示:
  • 被殺掉的節點是主節點,主分片 1 和 2 在咱們殺掉 Node 1 後就丟失了,咱們的索引在丟失主節點的時候是不能正常工做的。若是咱們在這個時候檢查集羣健康狀態,將會顯示 red:存在不可用的主節點
  • 而爲了集羣的正常工做必須須要一個主節點,因此首先進行的進程就是從各節點中選擇了一個新的主節點:Node 2
  • 新的主節點所完成的第一件事情就是將這些在 Node 2 和 Node 3 上的從分片提高爲主分片,而後集羣的健康狀態就變回至 yellow。這個提高的進程是瞬間完成了,就好像按了一下開關
  • 若是再次殺掉 Node 2 的時候,咱們的程序依舊能夠在沒有丟失任何數據的狀況下運行,由於 Node 3 中依舊擁有每一個分片的備份
  • 若是咱們重啓 Node 1,集羣就可以從新分配丟失的從分片,這樣結果就會與三節點兩從集羣一致。若是 Node 1 依舊還有舊節點的內容,系統會嘗試從新利用他們,並只會複製在故障期間的變動數據
相關文章
相關標籤/搜索