個人專題目錄
概述
1. 什么是搜索?
百度:我們比如說想找尋任何的信息的時候,就會上百度去搜索一下,比如說找一部自己喜歡的電影,或者說找一本喜歡的書,或者找一條感興趣的新聞(提到搜索的第一印象)。百度 != 搜索
1)互聯網的搜索:電商網站,招聘網站,新聞網站,各種app
2)IT系統的搜索:OA軟件,辦公自動化軟件,會議管理,日程管理,項目管理。
搜索,就是在任何場景下,找尋你想要的信息,這個時候,會輸入一段你要搜索的關鍵字,然后就期望找到這個關鍵字相關的有些信息
2. 如果用數據庫做搜索會怎么樣?
用數據庫來實現搜索,是不太靠譜的。通常來說,性能會很差的。
3. 什么是全文檢索和Lucene?
1)全文檢索,倒排索引
全文檢索是指計算機索引程序通過掃描文章中的每一個詞,對每一個詞建立一個索引,指明該詞在文章中出現的次數和位置,當用戶查詢時,檢索程序就根據事先建立的索引進行查找,并將查找的結果反饋給用戶的檢索方式。這個過程類似于通過字典中的檢索字表查字的過程。全文搜索搜索引擎數據庫中的數據。
2)lucene,就是一個jar包,里面包含了封裝好的各種建立倒排索引,以及進行搜索的代碼,包括各種算法。我們就用java開發的時候,引入lucene jar,然后基于lucene的api進行去進行開發就可以了。
4. 什么是Elasticsearch?
Elasticsearch是一個高度可擴展性的、開源的、全文本搜索和分析引擎。它讓你能夠快速地存儲、搜索和分析大量的數據,接近實時操作。它通常被用作底層引擎/技術,用來驅動那些"需要支持復雜的搜索功能的"應用程序。
Elasticsearch,基于lucene,隱藏復雜性,提供簡單易用的restful api接口、java api接口(還有其他語言的api接口)。
關于elasticsearch的一個傳說,有一個程序員失業了,陪著自己老婆去英國倫敦學習廚師課程。程序員在失業期間想給老婆寫一個菜譜搜索引擎,覺得lucene實在太復雜了,就開發了一個封裝了lucene的開源項目,compass。后來程序員找到了工作,是做分布式的高性能項目的,覺得compass不夠,就寫了elasticsearch,讓lucene變成分布式的系統。
Elasticsearch是一個實時分布式搜索和分析引擎。它用于全文搜索、結構化搜索、分析。
全文檢索:將非結構化數據中的一部分信息提取出來,重新組織,使其變得有一定結構,然后對此有一定結構的數據進行搜索,從而達到搜索相對較快的目的。
結構化檢索:我想搜索商品分類為日化用品的商品都有哪些,select * from products where category_id='日化用品'
數據分析:電商網站,最近7天牙膏這種商品銷量排名前10的商家有哪些;新聞網站,最近1個月訪問量排名前3的新聞版塊是哪些
5. Elasticsearch的適用場景
維基百科,類似百度百科,牙膏,牙膏的維基百科,全文檢索,高亮,搜索推薦。
The Guardian(國外新聞網站),類似搜狐新聞,用戶行為日志(點擊,瀏覽,收藏,評論)+ 社交網絡數據(對某某新聞的相關看法),數據分析,給到每篇新聞文章的作者,讓他知道他的文章的公眾反饋(好,壞,熱門,垃圾,鄙視,崇拜)。
Stack Overflow(國外的程序異常討論論壇),IT問題,程序的報錯,提交上去,有人會跟你討論和回答,全文檢索,搜索相關問題和答案,程序報錯了,就會將報錯信息粘貼到里面去,搜索有沒有對應的答案
GitHub(開源代碼管理),搜索上千億行代碼。
國內:站內搜索(電商,招聘,門戶,等等),IT系統搜索(OA,CRM,ERP,等等),數據分析(ES熱門的一個使用場景)。
6. Elasticsearch的特點
可以作為一個大型分布式集群(數百臺服務器)技術,處理PB級數據,服務大公司;也可以運行在單機上,服務小公司
Elasticsearch不是什么新技術,主要是將全文檢索、數據分析以及分布式技術,合并在了一起,才形成了獨一無二的ES;lucene(全文檢索),商用的數據分析軟件(也是有的),分布式數據庫(mycat)
對用戶而言,是開箱即用的,非常簡單,作為中小型的應用,直接3分鐘部署一下ES,就可以作為生產環境的系統來使用了,數據量不大,操作不是太復雜
數據庫的功能面對很多領域是不夠用的(事務,還有各種聯機事務型的操作);特殊的功能,比如全文檢索,同義詞處理,相關度排名,復雜數據分析,海量數據的近實時處理;Elasticsearch作為傳統數據庫的一個補充,提供了數據庫所不能提供的很多功能
7. Elasticsearch的核心概念
近實時 NRT(Near Realtime)
近實時,兩個意思,從寫入數據到數據可以被搜索到有一個小延遲(大概1秒);基于es執行搜索和分析可以達到秒級。
Cluster(集群)
集群包含多個節點,每個節點屬于哪個集群是通過一個配置(集群名稱,默認是elasticsearch)來決定的,對于中小型應用來說,剛開始一個集群就一個節點很正常。集群由一個唯一名字來標識,默認情況下,該名字為 "elasticsearch"。集群名字是很重要的,因為節點只能通過集群名字來加入該集群從而成為它的一部分.
Elasticsearch集群由一或多個節點組成,其中有一個主節點,這個主節點是可以通過選舉產生的,主從節點是對于集群內部來說的。Elasticsearch的一個概念就是去中心化,字面上理解就是無中心節點,這是對于集群外部來說的,因為從外部看Elasticsearch集群,在邏輯上是個整體,你與集群中的任何一個節點通信和與整個Elasticsearch集群通信是等價的。也就是說,主節點的存在不會產生單點安全隱患、并發訪問瓶頸等問題。
Node(節點)
集群中的一個節點,節點也有一個名稱(默認是隨機分配的),節點名稱很重要(在執行運維管理操作的時候),默認節點會去加入一個名稱為“elasticsearch”的集群,如果直接啟動一堆節點,那么它們會自動組成一個elasticsearch集群,當然一個節點也可以組成一個elasticsearch集群。
Shards & Replicas
一個索引可能會存儲大量的數據,最終超過單個節點的硬件容量。比如,某個索引有10億個文檔,占用 1TB 的磁盤空間,這樣的話,單個節點的磁盤可能就裝不下,此外,由單個節點來處理所有搜索請求可能會很慢。
要想解決這個問題,Elasticsearch允許你將索引切割成多塊,這些數據塊叫做shards。當你創建一個索引時,你可以定義將shards數量定義為任何值。每個shard自身是一個功能完整的、獨立的"index",可以被存儲在集群中的任何節點之上。
數據切割很重要,主要有兩個原因:
- 允許你水平地 切割/擴展 你的內容容量。
- 允許你跨越多個shards(它們可以位于多個節點之上)執行分發和并行處理,這樣就提高了性能/吞吐量。
shard是如何分布的,其中的文檔是如何被匯聚回搜索請求的,完全由Elasticsearch管理,對于用戶而言是透明的。
在一個網絡/云環境中,任何時候都可能出現故障,故障轉移機制是非常重要的,也是強烈推薦的,用于防備某個shard/node由于什么原因而離線或消失。因此,Elasticsearch允許你將index的 shards拷貝成多份,叫做replica shards,或者簡稱 replicas。
復制之所以很重要,主要有兩個原因:
- 它提供了高可用性,以防某個 shard/node 發生故障。因此,請一定要注意,某個replica shard永遠不要和它所拷貝的original/primary shard位于相同的節點上。
- 它允許你擴展你的搜索容量/吞吐量,因為搜索操作可以在所有replicas上并行執行。
總結一下,每個索引都可以被分割成多個shards。一個索引可以被復制零次(也即時沒有復制品)或多次。一旦某個索引被復制過了,它就擁有primary shards (原來的、被復制的shards) 以及 replica shards (primary shards的復制品)。 你可以在創建索引時,為之定義shards 和 replicas的數量。在索引被創建好之后,你可以在任何時候,動態地修改replicas的數量,但是,你不能修改 shards的數量。
默認情況下,Elasticsearch中的每個索引都會被指定5個primary shards以及1個replica,這意味著,在你的集群中,你需要至少兩個節點,你的索引具有5個primary shards以及另外5個replica shards (index的一份完整的復制品),每個索引總該有10個切片(shards)。
Index(索引-數據庫)
索引包含一堆有相似結構的文檔數據,比如可以有一個客戶索引,商品分類索引,訂單索引,索引有一個名稱。一個index包含很多document,一個index就代表了一類類似的或者相同的document。比如說建立一個product index,商品索引,里面可能就存放了所有的商品數據,所有的商品document。
索引創建規則:
僅限小寫字母
不能包含\、/、 *、?、"、<、>、|、#以及空格符等特殊符號
從7.0版本開始不再包含冒號
不能以-、_或+開頭
不能超過255個字節(注意它是字節,因此多字節字符將計入255個限制)
Type(類型-表)
每個索引里都可以有一個或多個type,type是index中的一個邏輯數據分類,一個type下的document,都有相同的field,比如博客系統,有一個索引,可以定義用戶數據type,博客數據type,評論數據type。
一種
type 就像一類表。如用戶表、角色表等。在 Elasticsearch7.X 默認 type 為 _doc
- ES 5.x 中一個 index 可以有多種 type 。
- ES 6.x 中一個 index 只能有一種 type 。
- ES 7.x 以后,將逐步移除 type 這個概念,現在的操作已經不再使用,默認 _doc
商品index,里面存放了所有的商品數據,商品document
但是商品分很多種類,每個種類的document的field可能不太一樣,比如說電器商品,可能還包含一些諸如售后時間范圍這樣的特殊field;生鮮商品,還包含一些諸如生鮮保質期之類的特殊field
type,日化商品type,電器商品type,生鮮商品type
日化商品type:product_id,product_name,product_desc,category_id,category_name
電器商品type:product_id,product_name,product_desc,category_id,category_name,service_period
生鮮商品type:product_id,product_name,product_desc,category_id,category_name,eat_period
每一個type里面,都會包含一堆document
{
"product_id": "1",
"product_name": "長虹電視機",
"product_desc": "4k高清",
"category_id": "3",
"category_name": "電器",
"service_period": "1年"
}
{
"product_id": "2",
"product_name": "基圍蝦",
"product_desc": "純天然,冰島產",
"category_id": "4",
"category_name": "生鮮",
"eat_period": "7天"
}
Document(文檔-行)
文檔是es中的最小數據單元,一個document可以是一條客戶數據,一條商品分類數據,一條訂單數據,通常用JSON數據結構表示,每個index下的type中,都可以去存儲多個document。
Field(字段-列)
Field是Elasticsearch的最小單位。一個document里面有多個field,每個field就是一個數據字段。
product document
{
"product_id": "1",
"product_name": "高露潔牙膏",
"product_desc": "高效美白",
"category_id": "2",
"category_name": "日化用品"
}
mapping(映射-約束)
數據如何存放到索引對象上,需要有一個映射配置,包括:數據類型、是否存儲、是否分詞等。
這樣就創建了一個名為blog的Index。Type不用單獨創建,在創建Mapping 時指定就可以。Mapping用來定義Document中每個字段的類型,即所使用的 analyzer、是否索引等屬性,非常關鍵等。創建Mapping 的代碼示例如下:
client.indices.putMapping({
index : 'blog',
type : 'article',
body : {
article: {
properties: {
id: {
type: 'string',
analyzer: 'ik',
store: 'yes',
},
title: {
type: 'string',
analyzer: 'ik',
store: 'no',
},
content: {
type: 'string',
analyzer: 'ik',
store: 'yes',
}
}
}
}
});
elasticsearch與數據庫的類比
關系型數據庫(比如Mysql) | 非關系型數據庫(Elasticsearch) |
---|---|
數據庫Database | 索引Index |
表Table | 類型Type |
數據行Row | 文檔Document |
數據列Column | 字段Field |
約束 Schema | 映射Mapping |
8. 分片的大小和數量怎么設定?
注1:小的分片會造成小的分段,從而會增加開銷。我們的目的是將平均分片大小控制在幾 GB 到幾十 GB 之間。對于基于時間的數據的使用場景來說,通常將分片大小控制在 20GB 到 40GB 之間。
注2:由于每個分片的開銷取決于分段的數量和大小,因此通過 forcemerge 操作強制將較小的分段合并為較大的分段,這樣可以減少開銷并提高查詢性能。 理想情況下,一旦不再向索引寫入數據,就應該這樣做。 請注意,這是一項比較耗費性能和開銷的操作,因此應該在非高峰時段執行。
注3:我們可以在節點上保留的分片數量與可用的堆內存成正比,但 Elasticsearch 沒有強制的固定限制。 一個好的經驗法則是確保每個節點的分片數量低于每GB堆內存配置20到25個分片。 因此,具有30GB堆內存的節點應該具有最多600-750個分片,但是低于該限制可以使其保持更好。 這通常有助于集群保持健康。
注4:如果擔心數據的快速增長, 建議根據這條限制: ElasticSearch推薦的最大JVM堆空間是 30~32G, 把分片最大容量限制為 30GB, 然后再對分片數量做合理估算。例如, 如果的數據能達到 200GB, 則最多分配7到8個分片。
9. ES存入數據和搜索數據機制
索引對象(blog):存儲數據的表結構 ,任何搜索數據,存放在索引對象上 。
映射(mapping):數據如何存放到索引對象上,需要有一個映射配置, 包括:數據類型、是否存儲、是否分詞等。
文檔(document):一條數據記錄,存在索引對象上
文檔類型(type):一個索引對象,存放多種類型數據,數據用文檔類型進行標識
10. 分布式特性
- es支持集群模式,是一個分布式系統,其好處主要有兩個:
- 增大系統容量,如內存、磁盤、使得es集群可以支持PB級的數據
- 提高系統可用性,即使部分節點停止服務,整個集群依然可以正常服務
- es集群由多個es實例組成
- 不同集群通過集群名字來區分,可通過cluster.name進行修改,默認為elasticsearch
- 每個es實例本質上是一個JVM進程,且有自己的名字,通過node.name進行修改
cerebro的安裝與運行
cerebro地址:https://github.com/lmenezes/cerebro
下載解壓
https://github.com/lmenezes/cerebro/releases
啟動cerebro
wget https://github.com/lmenezes/cerebro/releases/download/v0.8.1/cerebro-0.8.1.tgz
tar xzf cerebro-0.8.1.tgz
cerebro-0.8.1/bin/cerebro
[info] play.api.Play - Application started (Prod)
[info] p.c.s.AkkaHttpServer - Listening for HTTP on /0:0:0:0:0:0:0:0:9000
- 指定端口
bin/cerebro -Dhttp.port=8080
- 配置服務器
非必須:如果經常使用的話,可以先在conf/application.conf中配置好ElasticSearch服務器地址
訪問cerebro服務
輸入ElasticSearch的URL并點擊connect按鈕,成功連接即可顯示如下圖所示信息。需要注意的是由于cerebro運行在容器中,直接輸入localhost:9200即使通過瀏覽器能夠訪問也可能無法連接,需要保證的是在cerebro的容器中能夠訪問到的URL,比如這里使用的本機的IP
- 概要信息
- 節點信息
- Rest接口
- 其它功能
啟動一個節點
bin/elasticsearch -E cluster.name=my_cluster -E node.name=node1