ElasticSearch 是一個近實時的搜索平臺。也就是說當你索引一個文檔時可能出現輕微的延遲(通常都是秒級別),公司的logcenter出現的延時是出如今Kafka2ES層,而非索引層。html
ElasticSearch 是一個分佈式可擴展的實時搜索和分析引擎,一個創建在全文搜索引擎 Apache Lucene(TM) 基礎上的搜索引擎。固然 ElasticSearch 並不只僅是 Lucene 那麼簡單,它不只包括了全文搜索功能,還能夠進行如下工做:node
一個分佈式的實時文檔存儲,每一個字段均可以被索引與搜索mysql
一個分佈式實時分析搜索引擎sql
能勝任上百個服務節點的擴展,並支持 PB 級別的結構化或者非結構化數據數據庫
ElasticSearch英文翻譯:彈性搜索。json
能夠這樣理解:ElasticSearch是一個面向文檔型的數據庫,一條數據在裏面就是一個文檔,用JSON做爲文檔序列化格式。下面是一份ElasticSearch和關係型數據庫術語的對比關係表:api
MySQL數組 |
ElasticSearch緩存 |
|
---|---|---|
Database(數據庫)安全 |
對應的術語 |
含義 |
索引(Index) |
一系列文檔的集合,相似於mysql中數據庫的概念 |
|
Table(表) |
類型(type) |
在Index裏面能夠定義不一樣的type,type的概念相似於mysql中表的概念,是一系列具備相同特徵數據的結合。 |
Row (行) |
文檔(Document) |
文檔的概念相似於mysql中的一條存儲記錄,而且爲json格式,在Index下的不一樣type下,能夠有許多document。 |
Column (列) |
字段(Fields) |
|
Index (索引) |
Everything Indexed by default (全部字段默認都被索引) |
|
SQL (結構化查詢語言) |
Query DSL (查詢專用語言) |
|
Shards |
在數據量很大的時候,進行水平的擴展,提升搜索性能。 分片只保存了索引中全部數據的一部分。 咱們的文檔存儲在分片中,而且在分片中被索引,可是咱們的應用程序不會直接與它們通訊,取而代之的是,直接與索引通訊。 文檔存儲在分片中,而後分片分配到你集羣中的節點上。當你的集羣擴容或縮小,Elasticsearch將會自動在你的節點間遷移分片,以使集羣保持平衡。 |
|
Replicas |
防止某個分片的數據丟失,能夠並行得在備份數據裏及搜索提升性能。 |
優點 |
含義 |
---|---|
橫向可擴展性 |
增長服務器可直接配置在集羣中,只須要保證cluster.name一致便可。 |
分片機制 |
可以提供更好的分佈性,分而治之的方式來提高處理效率。 |
高可用 |
提供複製備份(replica)機制。 |
實時性 |
經過將磁盤上的文件放入文件緩存系統來提升查詢速度。 |
關於數據庫的水平擴展和豎直擴展:對於大多數數據庫而言,橫向擴展意味着你的程序將作很是大的改動才能利用這些新添加的設備。對比來講,Elasticsearch天生就是分佈式的,它知道如何管理節點來提供高擴展和高可用。這意味着你的程序不須要關心這些。 只要在建立集羣(cluster)、節點(node)和分片(shards)的時候,按照必定的規則,則能按照你的需求進行擴展,並保證在硬件故障的時候數據依然安全。
爲說明分片和複製分片的含義,以及如何擴展,這裏舉一個栗子:
(1)、啓動一個空節點,這時它沒有索引也沒有文檔數據。
(2)、咱們添加了一個名爲log的索引,設置它有三個主分片。(ES默認是5個主分片)。
(3)、單一節點運行很容易出現單點故障--數據丟失,這時咱們擴展第二個節點,設置相同的cluster.name就能夠加入同個集羣,設置log索引每一個主分片有一個複製分片,這時任意一個節點故障都能依然支持客戶端的查詢需求。
(4)、這時咱們繼續擴展,擴展第三個節點,ES集羣會從新組織本身,分片會從新被分配以達到平衡負載,這時每一個節點只有兩個分片,與以前相比少了一個,意味着每一個節點的分片有更多的資源,好比CPU、I/O等。
(5)、若是一個節點只有一個分片的話,那麼該分片就可獨享當前節點的全部資源。若是咱們須要擴展到6個節點以上?主分片的數量在建立索引時已經肯定,那麼咱們能夠增長複製分片的數量,能夠設置每一個分片有一個複製分片爲兩個。
(6)、ES能夠應對單點故障,這時咱們殺掉一個節點進程,且是主節點,ES會在瞬間選舉出一個新的主節點,且可以支持全部數據的查詢訪問。
關係型數據庫的B-/B+Tree,ES採用倒排索引,ES索引的一切設計都是爲了提升搜索的性能。
是爲優化寫入的索引結構,特色是二叉查找效率爲logN,同時插入新的節點沒必要移動所有節點,因此用樹型結構存儲索引,能同時兼顧插入和查詢的性能。
倒排索引的結構:
舉個栗子:
ID |
Name |
Age |
Sex |
---|---|---|---|
1 |
Kate |
24 |
女 |
2 |
John |
24 |
男 |
3 |
Bill |
29 |
男 |
那麼ES創建的索引以下:
Name:
Term |
Posting List |
---|---|
Kate |
[1] |
John |
[2] |
Bill |
[3] |
Age:
Term |
Posting List |
---|---|
24 |
[1,2] |
29 |
[3] |
Sex:
Term |
Posting List |
---|---|
男 |
[2,3] |
女 |
[1] |
如上,Elasticsearch分別爲每一個field都創建了一個倒排索引,Kate, John, 24, Female這些叫term,而1,2就是Posting List。Posting list就是一個int的數組,存儲了全部符合某個term的文檔id。在ES的每一部分中都採用了一些優化及壓縮技術,例如Term Index採用相似字典的索引頁的方式,能夠理解爲一棵樹,Term Dictionary存儲block,從Term Index找到對應的節點後再去Term Dictionary中尋找對應的block,從而磁盤去尋找Term。
這樣簡化存儲後,ES仍然沒有知足,爲了將Term Index、Term Dictionary及Posting List存儲入內存,Term Index使用了FST的壓縮,Posting List採用:增量編碼壓縮,將大數變小數,按字節存儲的方式進行壓縮。
Posting List的壓縮:
和ES的交互方式取決於你是否使用JAVA。如下咱們是以JAVA爲例對ES的查詢進行說明。
若是你正在使用 Java,在代碼中你可使用 ElasticSearch 內置的兩個客戶端:節點客戶端(Node client)、傳輸客戶端(Transport client)。Java客戶端默認端口是9300,而且使用ES的原生傳輸協議和集羣進行交互。
curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'複製代碼
被 < > 標記的部件 |
含義 |
VERB |
適當的 HTTP
方法
或
謂詞
: GET`、 `POST`、 `PUT`、 `HEAD 或者 `DELETE`。 |
PROTOCOL |
http 或者 https`(若是你在 ElasticSearch 前面有一個 `https 代理) |
HOST |
ElasticSearch 集羣中任意節點的主機名,或者用 localhost 表明本地機器上的節點。 |
PORT |
運行 ElasticSearch HTTP 服務的端口號,默認是 9200 。 |
PATH |
API 的終端路徑(例如 _count 將返回集羣中文檔數量)。Path 可能包含多個組件,例如:_cluster/stats 和 _nodes/stats/jvm 。 |
QUERY_STRING |
任意可選的查詢字符串參數 (例如 pretty 將格式化地輸出 JSON 返回值,使其更容易閱讀) |
BODY |
一個 JSON 格式的請求體 (若是請求須要的話) |
舉兩個栗子:
(1)、計算集羣中文檔的數量,咱們能夠用這個:
curl -XGET 'http://localhost:9200/_count?pretty' -d ' { "query": { "match_all": {} } }複製代碼
ES將返回一個HTTP狀態碼(例如:200 OK`)和(除`HEAD`請求)一個JSON 格式的返回值。JSON 體以下:
{
"count" : 0,
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
}
}複製代碼
(2)、以新美大日誌中心的查詢爲例:
curl -XPOST 'http://es.data.sankuai.com/log.mapi-log-service.userbehaviours_all/_search?pretty' -d' { "query": { //TODO:查詢語句 }, "size":"100" }'複製代碼
兩種方式:發送HTTP GET請求進行檢索、使用ES查詢表達式 (DSL) 檢索。
第一種方式即構造HTTP GET請求:(如下爲縮寫格式,即省略了請求中全部的相同部分,例如主機名、端口號以及curl命令自己,非完整請求)
參考:www.elastic.co/guide/cn/el…
curl -XGET /megacorp/employee/1複製代碼
返回信息包含一些基本信息以及搜索的JSON元數據:
{
"_index" : "megacorp",
"_type" : "employee",
"_id" : "1",
"_version" : 1,
"found" : true,
"_source" : {
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}
}複製代碼
第二種方式即便用使用ES查詢表達式 (DSL) 檢索:將請求參數按照ES約定的格式構造爲一個JSON進行請求。
參考:www.elastic.co/guide/cn/el…
經常使用的查詢:
查詢方式 |
含義 |
使用方法 |
備註 |
||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
term過濾 |
term主要用於精確匹配哪些值,好比數字,日期,布爾值或 not_analyzed 的字符串。 not_analyzed 的字符串:未經切詞的文本數據類型。 |
{
"query": {
"term": {
"title": "內蒙古"
}
}
}複製代碼
|
|||||||||||
terms過濾 |
terms 跟 term 有點相似,但 terms 容許指定多個匹配條件。 若是某個字段指定了多個值,那麼document須要一塊兒去作匹配。 |
{
"query": {
"terms": {
"title": [
"內蒙古",
"黑龍江"
]
}
}
}複製代碼
|
|||||||||||
range |
range過濾容許咱們按照指定範圍查找一批數據。 |
{
"query":{
"range": {
"pubTime": {
"gt": "2017-06-25",
"lt": "2017-07-01"
}
}
}
}複製代碼
|
範圍操做符包含:
|
||||||||||
exists和missing |
exists 和 missing 過濾能夠用於查找文檔中是否包含指定字段或沒有某個字段,相似於SQL語句中的IS_NULL條件。 這兩個過濾只是針對已經查出一批數據來,可是想區分出某個字段是否存在的時候使用。 |
{
"exists":{
"field":"title"
}
}複製代碼
|
|||||||||||
bool過濾 |
bool 過濾能夠用來合併多個過濾條件查詢結果的布爾邏輯,它包含一下操做符: must :: 多個查詢條件的徹底匹配,至關於 and。 must_not :: 多個查詢條件的相反匹配,至關於 not。 should :: 至少有一個查詢條件匹配, 至關於 or。 這些參數能夠分別繼承一個過濾條件或者一個過濾條件的數組 |
{
"bool":{
"must":{
"term":{
"folder":"inbox"
}
},
"must_not":{
"term":{
"tag":"spam"
}
},
"should":[
{
"term":{
"starred":true
}
},
{
"term":{
"unread":true
}
}
]
}
}複製代碼
|