[toc] 發表日期:2019年9月18日 什麼是ElasticSearch ElasticSearch是一個集 數據存儲 、 數據搜索 和 數據分析 為一體的系統。它是分散式的,所以能利用分散式來提高其處理能力,具有高可用性和高伸縮性。如果你需要一個能夠提供高性能的搜索服務的系統,那麼它或許是一個 ...
目錄
發表日期:2019年9月18日
什麼是ElasticSearch
ElasticSearch是一個集數據存儲、數據搜索和數據分析為一體的系統。它是分散式的,所以能利用分散式來提高其處理能力,具有高可用性和高伸縮性。如果你需要一個能夠提供高性能的搜索服務的系統,那麼它或許是一個好的選擇。
- 數據存儲:是指它能夠以JSON格式來存儲數據。如果你不在意數據的搜索,你甚至可以像類似使用mongodb那樣來單純把它作為一個數據存儲系統使用。
- 數據搜索:是指它能夠對JSON格式的數據進行全文檢索等搜索。
- 數據分析:是指它能夠利用一些演算法來對JSON文檔數據進行分析,比如得出某個月的商品銷售增長量。
核心能力
ElasticSearch是一個搜索系統,搜索就是從數據集合中搜索出我們想要的數據,例如從大量的商品數據中搜索出我們想要的某類商品。
現在提一個需求,例如我有一個“文章”的表,我想搜索文章表中欄位content中包含有'java'的數據。
如果你不使用ES,那麼從開發角度來說,平常我們都是使用關係型資料庫系統來存儲數據,然後使用類似select name,age,address from student where name like '%李%'
的語句通過模糊匹配來搜索符合指定條件的數據的。(對應到上面的需求應該是select name,author,content from article where content like '%java%'
)但其實上面這種基於模糊匹配的搜索方式的效率是比較低的,因為資料庫系統的搜索通常是逐一掃描的,也就是從頭到尾的來嘗試匹配,某個欄位的數據越多,可能需要嘗試匹配的次數就會越多(試想一下從4000字的文章中從上到下只為找到一個字),這種查找就好像最低級的遍歷查找(當然並不是真的就是傻傻的遍歷了,各個資料庫系統都會採用各種演算法來優化)。
而ElasticSearch由於其內部建立了每個詞的索引表,當搜索某個詞時,可以根據這個詞從索引表中找到匹配的記錄,所以效率比較高(就好像記錄了某個詞的坐標,有了坐標,就能根據坐標非常快地找到那個詞)。
(這裡舉個類似的慄子:相信大家都用過字典,那麼普通的資料庫搜索就好像從第一頁到最後一頁找一個詞,而ElasticSearch根據這個詞的部首結構從“部首-字的對應表”中直接查找到那個字的頁數,這個效率直接就是天差地別了!)另外,資料庫的搜索是根據指定詞直接查找的,它是很笨的!它不能查找到某些意義上“類似”的結果,比如我搜索“mother”,但如果某個記錄中包含“mom”這個詞,那這條記錄也應該被展示出來,而資料庫的普通搜索做不到。
而這個操作ElasticSearch就可以做到,由於它內部有分詞器,在建立索引的過程中,分詞器可以把數據中的某些詞都認為是指定的某一個詞(比如把mother,mom通通都使用mom作為索引詞),再用這個詞來建立索引,然後在進行搜索的時候,將輸入的詞也進行同樣的轉化,再根據這個詞從索引表中查找到符合的記錄結果,這樣就可以把那些意義相近的結果也搜索出來。所以說,ElasticSearch解決了普通全文搜索的搜索效率低下和搜索不智能的問題。
ES的搜索核心
介紹兩個搜索方法:順序掃描查找、全文搜索
上面有說到資料庫的搜索和ElasticSearch的搜索。
常見的關係型資料庫的針對某個欄位中的數據的搜索是順序掃描查找,從頭到尾去嘗試匹配,也就是所謂的遍歷查找,當然演算法可能沒有那麼低級。(現在一些資料庫系統也在嘗試優化全文搜索功能。)而ElasticSearch的搜索是全文搜索,而什麼是全文搜索?
全文搜索可以根據一定方式把非結構化的數據對應到一種結構化的標識,從而可以通過標識來檢索到指定的非結構化的數據記錄。
這句話可能有點難以理解,舉個例子理解,比如有一大堆食物你需要去認識,食物本身可以被認作是非結構化的數據,因為他們都是獨特的,但如果我們利用他們的顏色來劃分的話就可以初步地將他們進行結構化劃分,這個就是一種簡單的將數據結構化的手段。在ElasticSearch中,這個把非結構化的數據對應到一種結構化的標識的方式就是倒排索引,下麵介紹倒排索引來理解這個概念。在ElasticSearch中,處理這些非結構化的數據的方式就是建立倒排索引(Inverted Index)。
什麼是倒排索引呢?
倒排索引把數據進行了拆分(比如某個欄位的數據為hello world,那麼就會被拆分成hello和world),我們使用這些拆分的詞來作為索引詞來建立索引表,在以hello為索引詞的記錄中,有對hello world
的指向,world也是如此。
當然,這裡的拆分並不是真實的拆分,原始的數據依然存儲在elasticsearch中,我們另外創建了一個索引文件來存儲。下麵是一個使用倒排索引搜索的示例
1.首先,假設我們有一個欄位的數據是"I thank my mother",當我們把這個數據存儲到ElasticSearch中,ElasticSearch內部使用分詞器進行處理數據,分詞器用於將非結構化數據中的詞進行拆分和轉換,於是把"I thank my mother"拆解成了"I"、"thank"、"my"、"mother"。
2.當把數據拆分出來後(拆分成的數據單位我們稱為“詞”),就會把這些詞建立索引,ElasticSearch內部有一個索引表,用於建立詞與數據的對應,結構類似如下(真實格式還會有詞的頻率、數據長度等信息),索引表存儲了詞和詞所在記錄的ID集合,所以可以通過某個詞來快速搜索出相關的記錄,比如搜索"I",那麼會返回1和2,然後可以快速根據ID來獲取對應的數據。【請註意,下圖只是方便理解,並不是真實的格式】
3.然後我們搜索的時候,分詞器也先把我們輸入的內容處理(為了與索引表的詞統一),然後再從索引表中查找,返回對應的數據記錄集合。
例如我輸入mother,mother會先轉成mom,然後從索引表中找到mom,返回包含mom的記錄的ID,然後根據ID獲取對應數據,也就是“I like my mom”
搜索引擎選擇
Lucene也是一種搜索引擎,為什麼不直接使用Lucene?
ElasticSearch實際上底層使用的就是Lucene,雖然Lucene也有很多功能,但Lucene的使用難度較大(也正是使用難度高所以ElasticSearch才對Lucene進行封裝),而且ElasticSearc的高級功能也很強大,ES支持了多樣的數據分析。除了基本的功能,集群能力也是一個問題,Lucene一開始沒有考慮集群,所以對於存儲在不同伺服器上的大量數據的交互比較麻煩,而ElasticeSearch一開始就是集群思想的,數據存儲以一個ElasticSearch節點為單位,多個節點的數據可以交流。
由於底層是Lucene,所以,對於一些elasticsearch底層的東西,有時候你完全可以參照Lucene,比如索引詞文件的存儲等。為什麼不是Solr?
Solr也是一個知名的搜索引擎,它與ElasticSearch各有好處,Solr適用於一些非實時搜索系統(新增的數據不要求馬上查出來的),而ElasticSearch適用於一些實時搜索要求較高的系統(電商平臺等要求新商品馬上可查的系統)。因為Solr在建立索引時,搜索效率下降,實時索引搜索效率不高,而ElasticSearch建立索引的速度較快。ElasticSearch有一個非常顯著的特性"NRT":NRT全稱Near Real Time,近實時,意思是你插入的數據幾乎可以“馬上”就可以被搜索出來。這也是為什麼它能使用在實時更新要求高的場景的原因。
搜索的處理
上面提了詞的拆分,這裡提一些關於底層的搜索處理的內容。介紹一下ElasticSearch另一個協助搜索的關鍵組件--分詞器。ElasticSearch的全文搜索離不開分詞器的幫助。
分詞器通常由分解器tokenizer和詞元過濾器token filter組成。
分詞器對數據的分詞處理:為了提高索引的效率,ElasticSearch會數據進行處理,處理方式主要有字元過濾、詞轉換、詞拆分
字元過濾:過濾一些特殊字元,例如&
、||
、html標簽,因為這些詞通常搜索意義不大。詞轉換:把一些意義相同的詞統一轉成一個詞,(同詞義轉換)比如mom,mother統一轉成mom;(大小寫轉換)he,He統一歸為He;還處理一些詞意義不大的詞(停用詞清除),比如英文的“the”,“to”,這些詞使用頻率很高,但沒有具體意義。
詞拆分:進行數據的拆分,拆分成詞,比如把
good morning,mom
拆分成good
,morining
,mom
。另外,詞拆分並不完全是按照數據的最小單位分解的,某一些分詞器會把一些詞進行組合,因為一些詞的組合起來才有索引的意義,比如中文的一些詞通常要組合起來才有意義,比如“大”和“家”要組成“大家”才有比較具體的意義,這是為了確保索引詞的最小單位是有意義的(比如英文mom的最小單位是m,o,m,內部的分詞器要能夠區分出mom整個是有意義的才可以確保是採用mom作為索引,而不是採用m和o,也正是因為這個問題,所以英文分詞器不能用於中文分詞器)。【分詞器有很多個,預設的分詞器是不能適當對中文數據分詞的,它只能把一個個數據按最小的單位拆分,因為英文分詞器不能分清楚怎麼把詞拆分才有意義,由於配置分詞器是一個較為靠後的知識點,所以前期將以英文數據為測試數據。】分詞文件的存儲:
分詞文件一般包括三種文件:詞典文件,頻率文件,位置文件。
詞典文件保存了關鍵詞(索引詞),還保留了指向頻率文件和位置文件的指針。
頻率文件記錄了詞出現的頻率。
位置文件記錄了這些詞出現在哪些數據中。
補充:
- 資料庫不是被替代,而是被補充。有時候會將數據同時存儲到資料庫和ElasticSearch中,在單個查看的時候可以從資料庫中查詢,在搜索的時候從ElasticSearch中查詢;也有的項目由於數據比較簡單完全使用elasticsearch來存儲數據。
- ElasticSearch是分散式的,但我們是不需要對其集群進行部署的,它自動進行了集群部署和節點發現等功能,我們只需進行很少的配置就能管理集群。在比較靠後的內容才會講到如何深入管理集群。
小節總結:
- 1.本小節簡單講述了ElasticSearch是什麼
- 2.傳統搜索的不足
- 3.使用ElasticSearch搜索的好處
- 4.全文搜索和倒排索引
- 5.與其他搜索引擎的比較
- 6.ElasticSearch對於索引詞的處理(這個內容是提前講的內容,是為了幫助瞭解倒排索引如何建立索引)
基本學習環境搭建
如何操作ElasticSearch
首先要說的是,ElasticSearch是一款軟體,有點類似MySQL,我們要操作它的時候,也要給它發送它能識別的命令,而ElasticSearch是面向restful(不知道restful的自查吧)的,所以我們發送的命令是有點類似發送http請求的。
mysql是3306埠,而elasticsearch支持9200和9300埠操作,其中9200面向http,9300面向tcp。9200能夠使用普通的http請求來操作elasticsearch,9300需要連接elasticsearch之後再執行命令。
- 對於9200,因為面向http,所以我們可以使用postman發http請求來操作elasticsearch。
- 對於9300,因為面向tcp,我們通常使用一些elasticsearch管理工具(如kibana)進行連接elasticsearch之後再執行命令。(類似navicat之於mysql)
下載、安裝和運行(Based Windows)
我們首先來搭建好學習環境,主要是ElasticSearch和Kibana。【請註意,Elasticsearch依賴Java環境】
【Kibana是可選的,下麵會介紹一下基於postman的對ElasticSearch操作。】,Kibana是一款對ElasticSearch進行管理的軟體,我們可以在Kibana上執行ElasticSearch的命令。
下載:
- ElasticSearch下載:ElasticSearch下載【這裡以6.2的為例】
- Kibana下載:Kibana下載 【兩個下載都是同一個位置,這裡下載以6.2的為例】【Kibana的版本儘量與ElasticSearch的一致,有些版本會連接錯誤】
安裝:
- 兩個軟體都是不需要安裝的,下載後,直接解壓即可。
運行:
- 對於ElasticSearch,可以直接在
elasticsearch-6.2.0\bin
中運行elasticsearch.bat
,當提示“started”時,表示運行成功。 - 對於Kibana,可以直接在
kibana-6.2.0-windows-x86_64\bin
中運行kibana.bat
,當提示“Server running at http://localhost:5601”時,表示運行成功。【要先運行ElasticSearch再運行Kibana,因為它要與ElasticSearch進行連接】
如何操作ES
ElasticSearch預設的TCP服務埠是9300,Kibana的服務埠是5601,當我們啟動了Kibana之後,它會預設幫我們連接上9300,所以我們可以從http://localhost:5601
中進入Kibana的管理界面來管理ElasticSearch。
如果你是第一次使用,那麼ElasticSearch會自動創建一個名為elasticsearch
的集群,Kibana會在這個節點中初始化一個index
我們在Kibana的DevTools中執行一些命令來看一下ElasticSearch。【從http://localhost:5601
中進入】
在輸入命令GET /_cat/health?v
後,點擊該行右側的執行按鈕。【GET /_cat/health?v
是查看集群的健康狀態的命令】
然後就可以在右側的結果視窗中查看命令執行結果。
【你現在大概都是看不懂命令的意義和結果的意義的了,不過你應該知道哪裡輸入命令和哪裡看執行結果了】
基於postman操作
postman是一個用來發請求的軟體,可以使用restful風格的請求來操作elasticsearch。
比如上面的查看集群的命令:GET /_cat/health?v
轉成基於restful的是:http://localhost:9200/_cat/health?v
即IP:9200+命令
,其中9200是用於接收restful請求的es監聽埠。
補充:
上面的第一次使用並沒有涉及到具體的知識,只是讓你熟悉一下如何使用Kibana來操作ElasticSearch。下麵講到具體知識點才會具體使用。
小節總結
- 1.講了ES如何提供服務:9200,9300
- 2.講瞭如何下載、安裝、運行ElasticSearch和Kibana
- 3.講述瞭如何在Kibana中操作ElasticSearch
- 4.講述瞭如何在postman中操作ElasticSearch
需要瞭解的概念
分散式模型相關
- 集群Cluster:所謂集群,就是多個服務節點的集合,集群意味著這些節點是能夠相互交流的,不然無法進行數據交互。集群的預設名稱是"elasticsearch",多個提供服務的節點會根據集群名來自動加入集群。
- 節點Node:節點是集群的一部分,是集群的最小單元,是可以提供服務的節點。
- 分片shard:分片位於節點上,分片是elasticsearch數據存儲的單元,elasticsearch中的數據會存儲在分片中。分片可以存儲在任意一個節點上。分片分為主分片Primary Shard和副本分片Replica Shard。
- 主分片Primary Shard:當存儲一個文檔document的時候,會先存儲到主分片中,然後再複製到其他的副本分片Replica Shard中。
- 副本分片Replica Shard:副本分片是主分片的複製(備份)。預設情況下,主分片有一個副本分片,主分片不能修改,但副本分片可以後續再增加。
- 為了保證數據的不丟失,通常來說Replica Shard不能與其對應的Primary Shard處於同一個節點中。【因為萬一這個節點損壞了,那麼存儲在這個節點上的原數據(primary shard)和備份數據(replica shard)就全部丟失了】
- 當主分片掛掉的時候,會選擇一個副本分片作為主分片。
- 查詢可以在主分片或副本分片上進行查詢,這樣可以提供查詢效率。【但數據的修改只發生在主分片上。】
- 一個Primary Shard可以有多個Replica Shard,預設創建是1個。
數據存儲相關
數據存儲在shard中,shard中的數據是以文檔document為單位的。document存儲在index和type劃分的邏輯空間中。document以json為格式,每一個key-value中key可以稱為域Field。
- 索引Index:索引是存儲具有相同結構的document的集合,意義上有點類似關係型資料庫中的資料庫,用於存儲一系列數據,比如可以說“商品”索引,一般都是個大類,小邏輯劃分由Type處理。
- 類型Type:類型是索引的邏輯分區,意義有點類似關係型資料庫中的數據表。用來劃分索引下不同子類型的數據,比如商品(索引)可以有電子產品(類型),藥品(類型)。在同一個分類下的數據一般都具有同種特征,用來定義數據的欄位的數量一般也是相同的。每一個document都有一個type和一個id,在存儲文檔的時候需要指定索引、類型和ID。
- 文檔Document:類似於關係型資料庫中的記錄,是ElasticSearch的數據存儲的基本單位,格式與JSON相同。例如:
{
"book_id": 1,
"book_name": "Java Core ",
"book_desc": "A good book, you know!",
"category_id": "1",
"category_name": "Computer"
}
- 域Field:類似於關係型資料庫中的欄位。
- elasticsearch是面向restful的,下麵是restful請求與elasticsearch操作的對應:
請求方法 | 對應操作 | 說明 |
---|---|---|
GET | 讀取 | 獲取數據 |
POST | 新增 | 新增數據 |
PUT | 修改 | 修改數據或增加數據 |
DELETE | 刪除 | 刪除數據 |
- 索引用來存儲數據,分片也是用來存儲數據,它們是怎麼對應的?一個索引存儲在多個分片上,預設情況下,一個索引有五個主分片,五個副本分片。主分片的數量一旦定下來就不能再修改,但副本分片的數量還可以修改。
小節總結
- 講了一下ElasticSearch的集群概念,節點是集群的基礎服務單位,節點可以提供數據讀寫服務,數據按分片來存儲,主分片是主要數據,可以讀取和修改數據,副本分片不支持修改數據。
- 主分片和副本分片的互斥性(為了保證數據不同時丟失)
- elasticsearch的數據的邏輯存儲結構(索引->類型->文檔)。索引是數據的大分類,類型是數據的小分類。
- 文檔的格式
- 索引與分片的關係。一個索引存儲在多個分片上
Hello ElasticSearch
前面提了一下index,type,document,說了ElasticSearch的邏輯存儲空間。
下麵以兩個實例:“寫document->讀document”和“寫document->搜索document“來初步演示一下如何存儲數據和獲取數據。
寫->讀
如果我們要向ElasticSearch中寫入一份數據(document),命令的語法應該如下:
PUT /index名稱/type名稱/document的ID
{
document的數據
}
上面的語法的意思就是向一個index的一個type中插入一個document,document用id作為標識,後面我們取document的數據也將以這個id為依據。其中index,type是可以不需要我們預創建的,在我們還不會如何創建index和type的時候,你可以先隨便打個名字(如果ElasticSearch檢測到我們輸入的index和type是不存在的,那麼它就會以預設的規則幫我們創建出來)。
請在kibana的devtool中執行以下命令來存儲一份document:
PUT /douban/book/1
{
"book_id":1,
"book_name":"A Clockwork Orange",
"author":"Anthony Burgess",
"summary":"Fully restored edition of Anthony Burgess' original text of A Clockwork Orange, with a glossary of the teen slang 'Nadsat', explanatory notes, pages from the original typescript, interviews, articles and reviews Edited by Andrew Biswell With a Foreword by Martin Amis 'It is a horrorshow story ...' Fifteen-year-old Alex likes lashings of ultraviolence. He and his gang of friends rob, kill and rape their way through a nightmarish future, until the State puts a stop to his riotous excesses. But what will his re-education mean? A dystopian horror, a black comedy, an exploration of choice, A Clockwork Orange is also a work of exuberant invention which created a new language for its characters. This critical edition restores the text of the novel as Anthony Burgess originally wrote it, and includes a glossary of the teen slang 'Nadsat', explanatory notes, pages from the original typescript, interviews, articles and reviews, shedding light on the enduring fascination of the novel's 'sweet and juicy criminality'. Anthony Burgess was born in Manchester in 1917 and educated at Xaverian College and Manchester University. He spent six years in the British Army before becoming a schoolmaster and colonial education officer in Malaya and Brunei. After the success of his Malayan Trilogy, he became a full-time writer in 1959. His books have been published all over the world, and they include The Complete Enderby, Nothing Like the Sun, Napoleon Symphony, Tremor of Intent, Earthly Powers and A Dead Man in Deptford. Anthony Burgess died in London in 1993. Andrew Biswell is the Professor of Modern Literature at Manchester Metropolitan University and the Director of the International Anthony Burgess Foundation. His publications include a biography, The Real Life of Anthony Burgess, which won the Portico Prize in 2006. He is currently editing the letters and short stories of Anthony Burgess.",
"press":"Penguin Classic",
"publication_date":"2000-02-22"
}
如果要獲取ES中存儲的document,命令的語法應該如下:
GET /index名/type名/id
一樣的,請在kibana中執行下述命令來獲取我們上面存儲的document:
GET /douban/book/1
返回結果:【返回index名稱,type名稱,id,原始文檔等數據】
很明顯地,我們獲取到了我們剛剛存儲進去的數據。
寫->搜索
一樣的,我們寫多一份數據進ES中:
PUT /douban/book/2
{
"book_id":2,
"book_name":"Kubernetes in Action",
"author":"Marko Luksa",
"summary":"Kubernetes in Action teaches you to use Kubernetes to deploy container-based distributed applications. You'll start with an overview of Docker and Kubernetes before building your first Kubernetes cluster. You'll gradually expand your initial application, adding features and deepening your knowledge of Kubernetes architecture and operation. As you navigate this comprehensive guide, you'll explore high-value topics like monitoring, tuning, and scaling.Kubernetes is Greek for \"helmsman,\" your guide through unknown waters. The Kubernetes container orchestration system safely manages the structure and flow of a distributed application, organizing containers and services for maximum efficiency. Kubernetes serves as an operating system for your clusters, eliminating the need to factor the underlying network and server infrastructure into your designs.",
"press":"Manning Publications",
"publish_date":"2017-08-31"
}
下麵將演示搜索的功能,搜索的其中一種語法是:
GET /index名/type名/_search
{
"query":{
"match":{
"欄位Field名稱":"用於搜索的關鍵字"
}
}
}
那麼,根據我們之前存儲的數據,如果我們要查詢summary欄位有Orange的數據的話,命令如下:
GET /douban/book/_search
{
"query": {
"match": {
"summary":"Orange"
}
}
}
返回的結果:
小節總結
- 這小節涉及到了數據的插入,讀取,搜索,但僅僅是一個Hello ElasticSearch的例子,所以沒有講到插入數據應該有的前置知識。理論上,你只需要記得這個流程即可。後面會補充這個流程中沒有提到的內容。
--To Be Continue