這篇博客講到基本概念包括: Index、Type、Document。集羣,節點,分片及副本,倒排索引。
一、Index、Type、Document
1、Index
index
:索引是文檔(Document)的容器,是一類文檔的集合。
索引這個詞在 ElasticSearch 會有三種意思:
1)、索引(名詞)
類比傳統的關係型數據庫領域來說,索引相當於SQL中的一個數據庫(Database)
。索引由其名稱(必須爲全小寫字符)進行標識。
2)、索引(動詞)
保存一個文檔到索引(名詞)的過程
。這非常類似於SQL語句中的 INSERT關鍵詞。如果該文檔已存在時那就相當於數據庫的UPDATE。
3)、倒排索引
關係型數據庫通過增加一個B+樹索引到指定的列上,以便提升數據檢索速度。索引ElasticSearch 使用了一個叫做 倒排索引
的結構來達到相同的目的。
2、Type
Type
可以理解成關係數據庫中Table。
之前的版本中,索引和文檔中間還有個類型的概念,每個索引下可以建立多個類型,文檔存儲時需要指定index和type。從6.0.0開始單個索引中只能有一個類型,
7.0.0以後將將不建議使用,8.0.0 以後完全不支持。
棄用該概念的原因:
我們雖然可以通俗的去理解Index比作 SQL 的 Database,Type比作SQL的Table。但這並不準確,因爲如果在SQL中,Table 之前相互獨立,同名的字段在兩個表中毫無關係。
但是在ES中,同一個Index 下不同的 Type 如果有同名的字段,他們會被 Luecence 當作同一個字段 ,並且他們的定義必須相同。所以我覺得Index現在更像一個表,
而Type字段並沒有多少意義。目前Type已經被Deprecated,在7.0開始,一個索引只能建一個Type爲_doc
3、Document
Document
Index 裏面單條的記錄稱爲Document(文檔)。等同於關係型數據庫表中的行。
我們來看下一個文檔的源數據
_index
文檔所屬索引名稱。
_type
文檔所屬類型名。
_id
Doc的主鍵。在寫入的時候,可以指定該Doc的ID值,如果不指定,則系統自動生成一個唯一的UUID值。
_version
文檔的版本信息。Elasticsearch通過使用version來保證對文檔的變更能以正確的順序執行,避免亂序造成的數據丟失。
_seq_no
嚴格遞增的順序號,每個文檔一個,Shard級別嚴格遞增,保證後寫入的Doc的_seq_no
大於先寫入的Doc的_seq_no。
primary_term
primary_term也和_seq_no
一樣是一個整數,每當Primary Shard發生重新分配時,比如重啓,Primary選舉等,_primary_term會遞增1
found
查詢的ID正確那麼ture, 如果 Id 不正確,就查不到數據,found字段就是false。
_source
文檔的原始JSON數據。
二、集羣,節點,分片及副本
1、集羣
ElasticSearch集羣實際上是一個分佈式系統,它需要具備兩個特性:
1)高可用性
a)服務可用性:允許有節點停止服務;
b)數據可用性:部分節點丟失,不會丟失數據;
2)可擴展性
隨着請求量的不斷提升,數據量的不斷增長,系統可以將數據分佈到其他節點,實現水平擴展;
一個集羣中可以有一個或者多個節點;
集羣健康值
green
:所有主要分片和複製分片都可用yellow
:所有主要分片可用,但不是所有複製分片都可用red
:不是所有的主要分片都可用
當集羣狀態爲 red,它仍然正常提供服務,它會在現有存活分片中執行請求,我們需要儘快修復故障分片,防止查詢數據的丟失;
2、節點(Node)
1)節點是什麼?
a)節點是一個ElasticSearch的實例,其本質就是一個Java進程;
b)一臺機器上可以運行多個ElasticSearch實例,但是建議在生產環境中一臺機器上只運行一個ElasticSearch實例;
Node 是組成集羣的一個單獨的服務器,用於存儲數據並提供集羣的搜索和索引功能。與集羣一樣,節點也有一個唯一名字,默認在節點啓動時會生成一個uuid作爲節點名,
該名字也可以手動指定。單個集羣可以由任意數量的節點組成。如果只啓動了一個節點,則會形成一個單節點的集羣。
3、分片
Primary Shard(主分片)
ES中的shard用來解決節點的容量上限問題,,通過主分片,可以將數據分佈到集羣內的所有節點之上。
它們之間關係
一個節點對應一個ES實例;
一個節點可以有多個index(索引);
一個index可以有多個shard(分片);
一個分片是一個lucene index(此處的index是lucene自己的概念,與ES的index不是一回事);
主分片數是在索引創建時指定,後續不允許修改,除非Reindex
一個索引中的數據保存在多個分片中(默認爲一個),相當於水平分表。一個分片便是一個Lucene 的實例,它本身就是一個完整的搜索引擎。我們的文檔被存儲和索引到分片內,
但是應用程序是直接與索引而不是與分片進行交互。
Replica Shard(副本)
副本有兩個重要作用:
1、服務高可用:由於數據只有一份,如果一個node掛了,那存在上面的數據就都丟了,有了replicas,只要不是存儲這條數據的node全掛了,數據就不會丟。因此分片副本不會與
主分片分配到同一個節點;
2、擴展性能:通過在所有replicas上並行搜索提高搜索性能.由於replicas上的數據是近實時的(near realtime),因此所有replicas都能提供搜索功能,通過設置合理的replicas
數量可以極高的提高搜索吞吐量
分片的設定
對於生產環境中分片的設定,需要提前做好容量規劃,因爲主分片數是在索引創建時預先設定的,後續無法修改。
分片數設置過小
導致後續無法增加節點進行水平擴展。
導致分片的數據量太大,數據在重新分配時耗時;
分片數設置過大
影響搜索結果的相關性打分,影響統計結果的準確性;
單個節點上過多的分片,會導致資源浪費,同時也會影響性能;
三、倒排索引
ES的搜索功能是基於lucene,而lucene搜索的基本原理就是倒敘索引,倒序排序的結果跟分詞的類型有關
。
舉例
1、假設文檔集合包含五個文檔,毎個文檔內容如圖所示,在圖中最左端一欄是每個文檔對應的文擋編號。
如圖(盜圖)
2、首先要用分詞系統將文擋自動切分成單詞序列,記錄下哪些文擋包含這個單詞,在如此處理結束後,我們可以得到最簡單的倒排索引。
3、索引系統還可以記錄除此之外的更多信息,下圖還記載了單詞頻率信息。文檔中的句子被劃分爲一個個term(term 用來表示一個單詞或詞語,取決於使用的分詞方式
),
倒敘索引
中存儲着term,term的出現頻率(tf,term frequency)和出現位置(倒敘索引中的單詞是按順序排列的,這張圖沒有體現出來
),請注意這裏的文檔內容是document
中的一個字段,也就是說每個被索引了的字段都有自己的倒敘索引
一次簡單的搜索流程
假設我們搜索谷歌地圖之父
,搜索流程會是這樣
- 分詞,分詞插件將句子分爲3個term
谷歌
,地圖
,之父
- 將這3個term拿到倒敘索引中去查找(會很高效,比如二分查找),如果匹配到了就拿對應的文檔id,獲得文檔內容
但是,如何確定結果順序?
這裏要引入_score的概念,對於term的匹配,lucene會對其打分,得分越高,排名越靠前.這裏要介紹幾個相關的概念
- TF(term frequency),詞頻,term在當前document中出現的頻率,一個term在當前document中出現5次要比出現1次更相關,打分也會更高
- IDF(inverse doucment frequency),逆向文檔頻率,term在所有document中出現的頻率,這個頻率越高,該term對應的分值越低
- 字段長度歸一值,簡單來說就是字段越短,字段的權重越高, 比如 term `我`在匹配 `我123`和`我123456`時,`我123`的得分會更高.
### 參考
1、Elasticsearch核心技術與實戰---阮一鳴(eBay Pronto平臺技術負責人
我相信,無論今後的道路多麼坎坷,只要抓住今天,遲早會在奮鬥中嚐到人生的甘甜。抓住人生中的一分一秒,勝過虛度中的一月一年!(8)