原文鏈接:https://www.jianshu.com/p/60b242cbd8b4
1.ElasticSearch的簡介
Elasticsearch的特點
1)可以作為一個大型分布式集群(數百台服務器)技術,處理PB級數據,服務大公司;也可以運行在單機上,服務小公司
2)Elasticsearch不是什么新技術,主要是將全文檢索、數據分析以及分布式技術,合並在了一起,才形成了獨一無二的ES;lucene(全文檢索),商用的數據分析軟件(也是有的),分布式數據庫(mycat)
3)對用戶而言,是開箱即用的,非常簡單,作為中小型的應用,直接3分鍾部署一下ES,就可以作為生產環境的系統來使用了,數據量不大,操作不是太復雜
4)數據庫的功能面對很多領域是不夠用的(事務,還有各種聯機事務型的操作);特殊的功能,比如全文檢索,同義詞處理,相關度排名,復雜數據分析,海量數據的近實時處理;Elasticsearch作為傳統數據庫的一個補充,提供了數據庫所不能提供的很多功能
什么是搜索?
1)百度,谷歌,必應。我們可以通過他們去搜索我們需要的東西。但是我們的搜索不只是包含這些,還有京東站內搜索啊。
2)互聯網的搜索:電商網站。招聘網站。新聞網站。各種APP(百度外賣,美團等等)
3)windows系統的搜索,OA軟件,淘寶SSM網站,前后台的搜索功能
總結:搜索無處不在。通過一些關鍵字,給我們查詢出來跟這些關鍵字相關的信息
什么是全文檢索
全文檢索是指計算機索引程序通過掃描文章中的每一個詞,對每一個詞建立一個索引,指明該詞在文章中出現的次數和位置,當用戶查詢時,檢索程序就根據事先建立的索引進行查找,並將查找的結果反饋給用戶的檢索方式。這個過程類似於通過字典中的檢索字表查字的過程。
全文檢索的方法主要分為按字檢索和按詞檢索兩種。按字檢索是指對於文章中的每一個字都建立索引,檢索時將詞分解為字的組合。對於各種不同的語言而言,字有不同的含義,比如英文中字與詞實際上是合一的,而中文中字與詞有很大分別。按詞檢索指對文章中的詞,即語義單位建立索引,檢索時按詞檢索,並且可以處理同義項等。英文等西方文字由於按照空白切分詞,因此實現上與按字處理類似,添加同義處理也很容易。中文等東方文字則需要切分字詞,以達到按詞索引的目的,關於這方面的問題,是當前全文檢索技術尤其是中文全文檢索技術中的難點,在此不做詳述。
什么是倒排索引
以前是根據ID查內容,倒排索引之后是根據內容查ID,然后再拿着ID去查詢出來真正需要的東西。

什么是Lucene
Lucene就是一個jar包,里面包含了各種建立倒排索引的方法,java開發的時候只需要導入這個jar包就可以開發了。
Lucene的介紹及使用
典型的用空間換時間。
ES 和 Lucene的區別
Lucene不是分布式的。
ES的底層就是Lucene,ES是分布式的
為什么不用數據庫去實現搜索功能?
我們用搜索“牙膏”商品為例

如果用我們平時數據庫來實現搜索的功能在性能上就很差。
ES的由來
因為Lucene有兩個難以解決的問題,
1)數據越大,存不下來,那我就需要多台服務器存數據,那么我的Lucene不支持分布式的,那就需要安裝多個Lucene然后通過代碼來合並搜索結果。這樣很不好
2)數據要考慮安全性,一台服務器掛了,那么上面的數據不就消失了。
ES就是分布式的集群,每一個節點其實就是Lucene,當用戶搜索的時候,會隨機挑一台,然后這台機器自己知道數據在哪,不用我們管這些底層、

ES的優點
1.分布式的功能
2、數據高可用,集群高可用
3.API更簡單
4.API更高級。
5.支持的語言很多
6.支持PB級別的數據
7.完成搜索的功能和分析功能
基於Lucene,隱藏了Lucene的復雜性,提供簡單的API
ES的性能比HBase高,咱們的競價引擎最后還是要存到ES中的。
搜索引擎原理
反向索引又叫倒排索引,是根據文章內容中的關鍵字建立索引。
搜索引擎原理就是建立反向索引。
Elasticsearch 在 Lucene 的基礎上進行封裝,實現了分布式搜索引擎。
Elasticsearch 中的索引、類型和文檔的概念比較重要,類似於 MySQL 中的數據庫、表和行。
Elasticsearch 也是 Master-slave 架構,也實現了數據的分片和備份。
Elasticsearch 一個典型應用就是 ELK 日志分析系統。
ES的作用
1)全文檢索:
類似 select * from product where product_name like '%牙膏%'
類似百度效果(電商搜索的效果)
2)結構化搜索:
類似 select * from product where product_id = '1'
3)數據分析
類似 select count (*) from product
ES的安裝
參考https://www.jianshu.com/p/198a874cc14f
直接解壓就能用(針對中小型項目),大型項目還是要調一調參數的
2.用數據庫實現搜素的功能

3.ES的核心概念
3.1 NRT(Near Realtime)近實時

3.2 cluster集群,ES是一個分布式的系統
ES直接解壓不需要配置就可以使用,在hadoop1上解壓一個ES,在hadoop2上解壓了一個ES,接下來把這兩個ES啟動起來。他們就構成了一個集群。
在ES里面默認有一個配置,clustername 默認值就是ElasticSearch,如果這個值是一樣的就屬於同一個集群,不一樣的值就是不一樣的集群。
3.3 Node節點,就是集群中的一台服務器
3.4 Index(索引-數據庫)
我們為什么使用ES?因為想把數據存進去,然后再查詢出來。
我們在使用Mysql或者Oracle的時候,為了區分數據,我們會建立不同的數據庫,庫下面還有表的。
其實ES功能就像一個關系型數據庫,在這個數據庫我們可以往里面添加數據,查詢數據。
ES中的索引非傳統索引的含義,ES中的索引是存放數據的地方,是ES中的一個概念詞匯
index類似於我們Mysql里面的一個數據庫 create database user; 好比就是一個索引庫
3.5 Type(類型-表)
ES6以后一個index只能有一個type,為了提高查詢效率。
3.6 Document(文檔-行)
文檔就是最終的數據了,可以認為一個文檔就是一條記錄。
是ES里面最小的數據單元,就好比表里面的一條數據
3.7 Field(字段-列)
好比關系型數據庫中列的概念,一個document有一個或者多個field組成。
3.8 mapping(映射-約束)
數據如何存放到索引對象上,需要有一個映射配置,包括:數據類型、是否存儲、是否分詞等。
elasticsearch與數據庫的類比
關系型數據庫(比如Mysql) | 非關系型數據庫(Elasticsearch) |
---|---|
數據庫Database | 索引Index |
表Table | 類型Type |
數據行Row | 文檔Document |
數據列Column | 字段Field |
約束 Schema | 映射Mapping |
3.9 shard:分片
一台服務器,無法存儲大量的數據,ES把一個index里面的數據,分為多個shard,分布式的存儲在各個服務器上面。
kafka:為什么支持分布式的功能,因為里面是有topic,支持分區的概念。所以topic A可以存在不同的節點上面。就可以支持海量數據和高並發,提升性能和吞吐量
3.10 replica:副本
一個分布式的集群,難免會有一台或者多台服務器宕機,如果我們沒有副本這個概念。就會造成我們的shard發生故障,無法提供正常服務。
我們為了保證數據的安全,我們引入了replica的概念,跟hdfs里面的概念是一個意思。
可以保證我們數據的安全。
在ES集群中,我們一模一樣的數據有多份,能正常提供查詢和插入的分片我們叫做 primary shard,其余的我們就管他們叫做 replica shard(備份的分片)
當我們去查詢數據的時候,我們數據是有備份的,它會同時發出命令讓我們有數據的機器去查詢結果,最后誰的查詢結果快,我們就要誰的數據(這個不需要我們去控制,它內部就自己控制了)
總結:
在默認情況下,我們創建一個庫的時候,默認會幫我們創建5個主分片(primary shrad)和5個副分片(replica shard),所以說正常情況下是有10個分片的。
同一個節點上面,副本和主分片是一定不會在一台機器上面的,就是擁有相同數據的分片,是不會在同一個節點上面的。
所以當你有一個節點的時候,這個分片是不會把副本存在這僅有的一個節點上的,當你新加入了一台節點,ES會自動的給你在新機器上創建一個之前分片的副本。

3.11 舉例
比如一首詩,有詩題、作者、朝代、字數、詩內容等字段,那么首先,我們可以建立一個名叫 Poems 的索引,然后創建一個名叫 Poem 的類型,類型是通過 Mapping 來定義每個字段的類型。
比如詩題、作者、朝代都是 Keyword 類型,詩內容是 Text 類型,而字數是 Integer 類型,最后就是把數據組織成 Json 格式存放進去了。

Keyword 類型是不會分詞的,直接根據字符串內容建立反向索引,Text 類型在存入 Elasticsearch 的時候,會先分詞,然后根據分詞后的內容建立反向索引。

4. ES集群的安裝
以后補充
5. 安裝 Kibana
https://www.jianshu.com/p/198a874cc14f
6. ES的相關命令
GET _cat/health 查看集群的健康狀況
GET _all
PUT 類似於SQL中的增
DELETE 類似於SQL中的刪
POST 類似於SQL中的改
GET 類似於SQL中的查
index的操作:
PUT /aura_index 增加一個aura_index的index庫

GET _cat/indices 命令查詢ES中所有的index索引庫

5:代表的是 primary shard的個數
1:代表的是replica shard的個數是5,因為副本數為1代表有5個副分片,注意這個地方說的1是不包括自己本身的,我們的HDFS block3代表的是包括自己本身的
DELETE /aura_index 刪除一個aura_index的index庫

7. ES的CURD操作
通過演示一個電商的例子,感受到ES的語法特點
1)插入一條商品數據

注意:我們插入數據的時候,如果我們的語句中指明了index和type,如果ES里面不存在,默認幫我們自動創建
2)查詢商品數據
使用這種語法: GET /index/type/id

3)修改商品數據
使用POST來修改數據,其實使用PUT也可以實現修改數據,原理和hbase比較像。POST的修改數據的方法在第4條中


換個方式,下面這種操作也是成功的,會丟數據,是全局的修改


4)刪除商品數據

再次插入之前的數據,發現version是5,這就說明跟hbase是類似的,不會立刻刪除,會在合適的時機進行刪除。

這次我們使用POST的方式進行修改數據,POST是局部更新數據,別的數據不動。PUT是全局更新


5)接着插入兩條數據


現在查看所有數據,類似於全表掃描

took:耗費了6毫秒
shards:分片的情況
hits:獲取到的數據的情況
total:3 總的數據條數
max_score:1 所有數據里面打分最高的分數
_index:"ecommerce" index名稱
_type:"product" type的名稱
_id:"2" id號
_score:1 分數,這個分數越大越靠前出來,百度也是這樣。除非是花錢。否則匹配度越高越靠前


8.DSL語言
ES最主要是用來做搜索和分析的。所以DSL還是對於ES很重要的
下面我們寫的代碼都是RESTful風格
query DSL:domain Specialed Lanaguage 在特定領域的語言
案例:我們要進行全表掃描使用DSL語言,查詢所有的商品

使用match_all 可以查詢到所有文檔,是沒有查詢條件下的默認語句。
案例:查詢所有名稱里面包含chenyi的商品,同時按價格進行降序排序
如上圖所示,name為dior chenyi的數據會在ES中進行倒排索引分詞的操作,這樣的數據也會被查詢出來。

match查詢是一個標准查詢,不管你需要全文本查詢還是精確查詢基本上都要用到它。
下面我們按照價格進行排序:因為不屬於查詢的范圍了。所以要寫一個 逗號

這樣我們的排序就完成了
案例:實現分頁查詢
條件:根據查詢結果(包含chenyi的商品),再進行每頁展示2個商品

案例:進行全表掃面,但返回指定字段的數據
現在的情況是把所有的數據都返回了,但是我們想返回指定字段的數據內容就需要下面的方法了

案例:搜索名稱里面包含chenyi的,並且價格大於250元的商品
相當於 select * form product where name like %chenyi% and price >250;
因為有兩個查詢條件,我們就需要使用下面的查詢方式
如果需要多個查詢條件拼接在一起就需要使用bool
bool 過濾可以用來合並多個過濾條件查詢結果的布爾邏輯,它包含以下操作符:
must :: 多個查詢條件的完全匹配,相當於 and。
must_not :: 多個查詢條件的相反匹配,相當於 not。
should :: 至少有一個查詢條件匹配, 相當於 or。
這些參數可以分別繼承一個過濾條件或者一個過濾條件的數組

案例:展示一個全文檢索的效果

首先查詢條件也會進行分詞
kama
chenyi
並集
案例:不要把條件分詞,要精確匹配
但是我們現有有一種需求我就是想查詢kama chenyi不要分詞,要精確匹配到

百度就類似於這樣
案例:把查詢結果進行高亮展示

<em>kama</em>這個標簽是默認的標簽,是可以自定義的進行替換的,比如我們可以替換成<span style="color:red">kama</span>,把這個輸出到網頁上,自然而然就是紅色的了。
9.聚合分析
案例:計算每個標簽tag下商品的數量
按標簽進行分組類似於 select count(*) from product group by tag;


terms 跟 term 有點類似,但 terms 允許指定多個匹配條件。 如果某個字段指定了多個值,那么文檔需要一起去做匹配
error是報錯,但是這個語句是對的,這個報錯在ES2之前是沒有的,在ES5以后才有的,在5中fielddata=true 默認是false,以前都是true
group_by_tag是個名字隨意取
所以我們需要先執行下面的代碼進行一下設置的修改:

再次執行一次

如果不想顯示具體內容,加上"size":0
GET ecommerce/product/_search
{
"size": 0,
"aggs": {
"group_by_tags": {
"terms": {
"field": "tags"
}
}
}
}
案例:對商品名稱里面包含chenyi的,計算每個tag下商品的數量

案例:查詢商品名稱里面包含chenyi的數據,並且按照tag進行分組,計算每個分組下的平均價格

案例:查詢商品名稱里面包含chenyi的數據,並且按照tag進行分組,計算每個分組下的平均價格,按照平均價格進行降序排序

注意寫的位置
案例:查詢出producer里面包含producer的數據,按照指定的價格區間進行分組,在每個組內再按tag進行分組,分完組以后再求每個組的平均價格,並且按照降序進行排序
range過濾允許我們按照指定范圍查找一批數據


Elasticsearch對復雜分布式機制的透明隱藏特性
1)Elasticsearch是一套分布式系統,分布式是為了應對大數據量,隱藏了復雜的分布式機制
分片機制
(我們之前隨隨便便就將一些document插入到es集群中,我們沒有關心過數據是怎么進行分片的,數據到哪個shard中去)
cluster discovery
(集群發現機制,我們之前做集群status從yellow轉green,直接啟動第二個es進程,那個進程直接作為一個node自動就發現了集群,並且加入了進去,還接受了部分數據,replica shard)
shard負載均衡
(假設現在有3個node,總共有25個shard要分配到3個節點上去,es會自動進行均勻分配,以保持每個節點的均衡的讀寫負載請求)
shard副本
,請求路由
,集群擴容
,shard重分配
2)Elasticsearch的垂直擴容與水平擴容
垂直擴容:
采購更強大的服務器,成本高昂,會有瓶頸
水平擴容:
業界經常采用的方式,采購越來越多的普通服務器,性能比較一般,但是很多普通服務器組織在一起,就能構成強大的計算和存儲能力。
3)增加或減少節點時的數據rebalance:
比如現在有3個節點,4個shard。這樣肯定有一台節點上存儲2個shard,總會有那么一台節點負荷重一點,當增加一個節點時,es集群會自動把有2個shard的節點分出一個shard給新增加的節點,保持負載均衡。
4)master節點
管理es集群的元數據:比如創建或刪除index,維護索引元數據,節點的增加和刪除,維護集群的元數據。
默認情況下,會自動選擇出一台節點,作為master節點。
master節點不承載所有的請求,所以不會是一個單點瓶頸。
5)節點對等的分布式架構
節點對等,每個節點都能接收所有的請求
自動請求路由(如果請求要找的數據不在這台節點上,這個節點會自動把請求路由到數據所在的節點)
響應收集(數據所在節點會接收到其他節點發送的請求,並且響應回client)
shard&replica機制梳理
(1)index包含多個shard
(2)每個shard都是一個最小工作單元,承載部分數據,lucene實例,完整的建立索引和處理請求的能力
(3)增減節點時,shard會自動在nodes中負載均衡
(4)primary shard和replica shard,每個document肯定只存在於某一個primary shard以及其對應的replica shard中,不可能存在於多個primary shard
(5)replica shard是primary shard的副本,負責容錯,以及承擔讀請求負載
(6)primary shard的數量在創建索引的時候就固定了,replica shard數量可以隨時修改
(7)primary shard的默認數量是5,replica默認是1,默認有10個shard,5個primary shard,5個replica shard
(8)primary shard不能和自己的replica shard放在同一個節點上(否則節點宕機,primary shard和副本全部丟失,起不到容錯作用),但是可以和其他primary shard的replica shard放在同一個節點
單node環境下創建index是什么樣子
(1)單node環境下,創建一個index,有3個primary shard,3個replica shard
(2)集群status是yellow
(3)這個時候,只會將3個primary shard分配到僅有的一台node上去,另外3個replica shard無法分配
(4)集群可以正常工作,但是一旦出現節點宕機,數據全部丟失,而且集群不可用,無法承載任何請求
PUT /test_index
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
}
}