您好,登錄后才能下訂單哦!
上一篇主要學習了ES及其插件的安裝,這一篇主要學習ES集群及其節點管理
一、ES集群概述
1、ES集群簡介
ES就是為高可用和可擴展而生的,服務器的擴展可以通過購置性能更強的服務器(垂直擴展或者向上擴展,Vertical Scale/Scaling Up),亦或是通過購置更多的服務器(水平擴展或者向外擴展,Horizontal Scale/Scaling Out)來完成。盡管ES能夠利用更強勁的硬件,垂直擴展畢竟還是有它的極限。真正的可擴展性來自于水平擴展 - 通過向集群中添加更多的節點來分布負載,增加可靠性。
在大多數數據庫中,水平擴展通常都需要你對應用進行一次大的重構來利用更多的節點。
相反,ES天生就是分布式的:它知道如何管理多個節點來完成擴展和實現高可用性。這也意味著你的應用不需要在乎這一點。
2、ES集群的主節點
集群中的一個節點會被選為主節點(Master Node),它負責管理整個集群的變化,如創建或者刪除一個索引(Index),向集群中添加或者刪除節點。主節點并不需要參與到文檔級別的變化或者搜索中,這意味著雖然只有一個主節點,但它并不會隨著流量的增加而成為瓶頸。任何節點都可以成為主節點。在我們的例子中只有一個節點,所以它就承擔了主節點的功能。
對于用戶,可以和集群中的任意節點進行通信,包括主節點。每個節點都知道每份文檔的存放位置,并且能夠將請求轉發到持有所需數據的節點。用戶通信的節點會負責將需要的數據從各個節點收集起來,然后返回給用戶。以上整個過程都會由ES透明地進行管理。
3、ES集群的特性
elasticsearch集群一旦建立起來以后,會選舉出一個master,其他都為slave節點。
但是具體操作的時候,每個節點都提供寫和讀的操作。就是說,你不論往哪個節點中做寫操作,這個數據也會分配到集群上的所有節點中。
這里有某個節點掛掉的情況,如果是slave節點掛掉了,那么首先關心,數據會不會丟呢?不會。如果你開啟了replicate,那么這個數據一定在別的機器上是有備份的。
別的節點上的備份分片會自動升格為這份分片數據的主分片。這里要注意的是這里會有一小段時間的yellow狀態時間。
如果是主節點掛掉怎么辦呢?當從節點們發現和主節點連接不上了,那么他們會自己決定再選舉出一個節點為主節點。
但是這里有個腦裂的問題,假設有5臺機器,3臺在一個機房,2臺在另一個機房,當兩個機房之間的聯系斷了之后,每個機房的節點會自己聚會,推舉出一個主節點。
這個時候就有兩個主節點存在了,當機房之間的聯系恢復了之后,這個時候就會出現數據沖突了。
解決的辦法就是設置參數:
discovery.zen.minimum_master_nodes
為3(超過一半的節點數),那么當兩個機房的連接斷了之后,就會以大于等于3的機房的master為主,另外一個機房的節點就停止服務了。
對于自發現動能這里不難看出,如果把節點直接暴露在外面,不管怎么切換master,必然會有單節點問題。所以一般我們會在可提供服務的節點前面加一個負載均衡。
4、ES集群的自動發現功能
elasticsearch的集群是內嵌自動發現功能的。
意思就是說,你只需要在每個節點配置好了集群名稱,節點名稱,互相通信的節點會根據es自定義的服務發現協議去按照多播的方式來尋找網絡上配置在同樣集群內的節點。
和其他的服務發現功能一樣,es是支持多播和單播的。多播和單播的配置分別根據這幾個參數:
discovery.zen.ping.multicast.enabled: false # 這個設置把組播的自動發現給關閉了,為了防止其他機器上的節點自動連入。 discovery.zen.fd.ping_timeout: 100 sdiscovery.zen.ping.timeout: 100 # 設置了節點與節點之間的連接ping時長 sdiscovery.zen.minimum_master_nodes: 2 # 這個設置為了避免腦裂。比如3個節點的集群,如果設置為2,那么當一臺節點脫離后,不會自動成為master discovery.zen.ping.unicast.hosts: ["12.12.12.12:10801"] # 這個設置了自動發現的節點
多播是需要看服務器是否支持的,由于其安全性,其實現在基本的云服務(比如阿里云)是不支持多播的,所以即使你開啟了多播模式,你也僅僅只能找到本機上的節點。
單播模式安全,也高效,但是缺點就是如果增加了一個新的機器的話,就需要每個節點上進行配置才生效了。
二、ES集群的管理
ES集群提供了Restful風格的訪問接口API
ES訪問接口:9200/tcp 基于http協議工作
1、Restful風格API
四類API:
檢查集群、節點、索引等是否健康以及獲取其相應狀態
管理集群,節點、索引及元數據
執行CRUD操作
執行高級操作,例如paging,filtering等
語法格式:
curl -X <VERB> '<protocol>://HOST:PORT/<PATH>?<QUERY_STRING>' -d '<body>'
VERB:
GET,PUT,DELETE等 (GET方法可以省略)
PROTOCOL:
http,https
QUERY_STRING:
查詢參數、例如:?pretty表示使用易讀的JSON格式輸出
BODY:
請求的主體
查看ES節點是否工作正常:
[root@Node2 ~]# curl localhost:9200 { # JSON格式 "name" : "node2", "cluster_name" : "RK", "cluster_uuid" : "pwffDjOKQT6Ss2CRQLXt0g", "version" : { "number" : "5.3.0", "build_hash" : "3adb13b", "build_date" : "2017-03-23T03:31:50.652Z", "build_snapshot" : false, "lucene_version" : "6.4.1" }, "tagline" : "You Know, for Search" # 正常 }
Elasticsearch通過使用JSON來作為溝通的數據格式,這對于開發者來說很友好,因為很多程序都支持JSON格式。比如js就不說了,Java也有fastjson,ruby什么的都自帶json。
1)_cat API
Elasticsearch中信息很多,如果單憑肉眼來尋找復雜數據之間的關系,是很困難的。因此cat命令應運而生,它幫助開發者快速查詢Elasticsearch的相關信息。
查看_cat api的所有操作:
[root@Node2 ~]# curl 192.168.10.7:9200/_cat =^.^= /_cat/allocation /_cat/shards /_cat/shards/{index} /_cat/master /_cat/nodes /_cat/tasks /_cat/indices /_cat/indices/{index} /_cat/segments /_cat/segments/{index} /_cat/count /_cat/count/{index} /_cat/recovery /_cat/recovery/{index} /_cat/health /_cat/pending_tasks /_cat/aliases /_cat/aliases/{alias} /_cat/thread_pool /_cat/thread_pool/{thread_pools} /_cat/plugins /_cat/fielddata /_cat/fielddata/{fields} /_cat/nodeattrs /_cat/repositories /_cat/snapshots/{repository} /_cat/templates
每個命令都支持使用?v參數,來顯示詳細的信息:
每個命令都支持使用help參數,來輸出可以顯示的列:
$ curl localhost:9200/_cat/master?help id | | node id host | h | host name ip | | ip address node | n | node name
通過h參數,可以指定輸出的字段:
$ curl localhost:9200/_cat/master?v id host ip node QG6QrX32QSi8C3-xQmrSoA 127.0.0.1 127.0.0.1 Manslaughter $ curl localhost:9200/_cat/master?h=host,ip,node 127.0.0.1 127.0.0.1 Manslaughter
[root@Node2 ~]# curl 192.168.10.2:9200/_cat/master?v id host ip node bMAYDjb2Rsyfpn92Lnax3w 192.168.2.116 192.168.2.116 node7 [root@Node2 ~]# curl 192.168.10.2:9200/_cat/master?help id | | node id host | h | host name ip | | ip address node | n | node name [root@Node2 ~]# curl 192.168.10.2:9200/_cat/master?h=host,id,host 192.168.2.116 bMAYDjb2Rsyfpn92Lnax3w
很多的命令都支持返回可讀性的大小數字,比如使用mb或者kb來表示。
$ curl localhost:9200/_cat/indices?v health status index pri rep docs.count docs.deleted store.size pri.store.sizeyellow open test 5 1 3 0 9.kb 9.kb
例子:
查看ES集群的切片信息:
[root@Node2 ~]# curl 192.168.10.7:9200/_cat/allocation 9 38.8mb 4.7gb 13gb 17.7gb 26 192.168.2.116 192.168.2.116 node7 9 38.8mb 9.1gb 8.6gb 17.7gb 51 192.168.2.114 192.168.2.114 node2 [root@Node2 ~]# curl 192.168.10.7:9200/_cat/allocation?v # ?v表示顯示詳細信息(字段名) shards disk.indices disk.used disk.avail disk.total disk.percent host ip node 9 38.8mb 9.1gb 8.6gb 17.7gb 51 192.168.2.114 192.168.2.114 node2 9 38.8mb 4.7gb 13gb 17.7gb 26 192.168.2.116 192.168.2.116 node7
查看ES集群節點信息:
[root@Node2 ~]# curl 192.168.10.7:9200/_cat/nodes?v ip heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name 192.168.2.114 10 96 1 0.00 0.01 0.00 mdi - node2 192.168.2.116 3 100 0 0.00 0.00 0.00 mdi * node7
heap.percent:堆內存占的內存百分比
cpu:表示使用的cpu核心
node.role:表示節點能充當的角色主、數據 節點
master:表示當前是否為主節點,*表示當前為主
2)_Cluster API
集群相關的api接口
[root@Node2 ~]# curl localhost:9200/_cluster/health {"cluster_name":"RK","status":"green","timed_out":false,"number_of_nodes":2,"number_of_data_nodes":2,"active_primary_shards":9,"active_shards":18,"relocating_shards":0,"initializing_shards":0,"unassigned_shards":0,"delayed_unassigned_shards":0,"number_of_pending_tasks":0,"number_of_in_flight_fetch":0,"task_max_waiting_in_queue_millis":0,"active_shards_percent_as_number":100.0} [root@Node2 ~]# curl localhost:9200/_cluster/health?pretty # ?pretty JSON格式顯示,易讀 { "cluster_name" : "RK", "status" : "green", "timed_out" : false, "number_of_nodes" : 2, "number_of_data_nodes" : 2, "active_primary_shards" : 9, "active_shards" : 18, "relocating_shards" : 0, "initializing_shards" : 0, "unassigned_shards" : 0, "delayed_unassigned_shards" : 0, "number_of_pending_tasks" : 0, "number_of_in_flight_fetch" : 0, "task_max_waiting_in_queue_millis" : 0, "active_shards_percent_as_number" : 100.0 }
輸出里最重要的就是 status 這行。很多開源的 ES 監控腳本,其實就是拿這行數據做報警判斷。status 有三個可能的值:
green 綠燈,所有分片都正確運行,集群非常健康。
yellow 黃燈,所有主分片都正確運行,但是有副本分片缺失。這種情況意味著 ES 當前還是正常運行的,但是有一定風險。注意,在 Kibana4 的 server 端啟動邏輯中,即使是黃燈狀態,Kibana 4 也會拒絕啟動,死循環等待集群狀態變成綠燈后才能繼續運行。
red 紅燈,有主分片缺失。這部分數據完全不可用。而考慮到 ES 在寫入端是簡單的取余算法,輪到這個分片上的數據也會持續寫入報錯。
對 Nagios 熟悉的讀者,可以直接將這個紅黃綠燈對應上 Nagios 體系中的 Critical,Warning,OK 。
number_of_nodes 集群內的總節點數。
number_of_data_nodes 集群內的總數據節點數。
active_primary_shards 集群內所有索引的主分片總數。
active_shards 集群內所有索引的分片總數。
relocating_shards 正在遷移中的分片數。
initializing_shards 正在初始化的分片數。
unassigned_shards 未分配到具體節點上的分片數。
delayed_unassigned_shards 延時待分配到具體節點上的分片數。
顯然,后面 4 項在正常情況下,一般都應該是 0。但是如果真的出來了長期非 0 的情況,怎么才能知道這些長期 unassign 或者 initialize 的分片影響的是哪個索引呢?本書隨后還有有更多接口獲取相關信息。不過在集群健康這層,本身就可以得到更詳細一點的內容了。
接口請求的時候,可以附加一個 level 參數,指定輸出信息以 indices 還是 shards 級別顯示。當然,有三個級別:cluster,indices,shards (如果寫錯了就默認輸出cluster級別)
一般來說,indices 級別就夠了。
health:健康信息
curl 'localhost:9200/_cluster/health?pretty'
[root@Node2 ~]# curl localhost:9200/_cluster/health?level=nodes {"cluster_name":"RK","status":"green","timed_out":false,"number_of_nodes":2,"number_of_data_nodes":2,"active_primary_shards":9,"active_shards":18,"relocating_shards":0,"initializing_shards":0,"unassigned_shards":0,"delayed_unassigned_shards":0,"number_of_pending_tasks":0,"number_of_in_flight_fetch":0,"task_max_waiting_in_queue_millis":0,"active_shards_percent_as_number":100.0}[root@Node2 ~]# [root@Node2 ~]# curl 'localhost:9200/_cluster/health?level=cluster&pretty' # 還需要使用JSON格式輸出需要加&pretty并使用引用 { "cluster_name" : "RK", "status" : "green", "timed_out" : false, "number_of_nodes" : 2, "number_of_data_nodes" : 2, "active_primary_shards" : 9, "active_shards" : 18, "relocating_shards" : 0, "initializing_shards" : 0, "unassigned_shards" : 0, "delayed_unassigned_shards" : 0, "number_of_pending_tasks" : 0, "number_of_in_flight_fetch" : 0, "task_max_waiting_in_queue_millis" : 0, "active_shards_percent_as_number" : 100.0 } [root@Node2 ~]# curl 'localhost:9200/_cluster/health?level=indices&pretty' { "cluster_name" : "RK", "status" : "green", "timed_out" : false, "number_of_nodes" : 2, "number_of_data_nodes" : 2, "active_primary_shards" : 9, "active_shards" : 18, "relocating_shards" : 0, "initializing_shards" : 0, "unassigned_shards" : 0, "delayed_unassigned_shards" : 0, "number_of_pending_tasks" : 0, "number_of_in_flight_fetch" : 0, "task_max_waiting_in_queue_millis" : 0, "active_shards_percent_as_number" : 100.0, "indices" : { ".monitoring-es-2-2017.04.20" : { "status" : "green", "number_of_shards" : 1, "number_of_replicas" : 1, "active_primary_shards" : 1, "active_shards" : 2, "relocating_shards" : 0, "initializing_shards" : 0, "unassigned_shards" : 0 }, ".kibana" : { "status" : "green", "number_of_shards" : 1, "number_of_replicas" : 1, "active_primary_shards" : 1, "active_shards" : 2, "relocating_shards" : 0, "initializing_shards" : 0, "unassigned_shards" : 0 }, ".monitoring-data-2" : { "status" : "green", "number_of_shards" : 1, "number_of_replicas" : 1, "active_primary_shards" : 1, "active_shards" : 2, "relocating_shards" : 0, "initializing_shards" : 0, "unassigned_shards" : 0 }, ".monitoring-es-2-2017.04.17" : { "status" : "green", "number_of_shards" : 1, "number_of_replicas" : 1, "active_primary_shards" : 1, "active_shards" : 2, "relocating_shards" : 0, "initializing_shards" : 0, "unassigned_shards" : 0 }, ".monitoring-kibana-2-2017.04.20" : { "status" : "green", "number_of_shards" : 1, "number_of_replicas" : 1, "active_primary_shards" : 1, "active_shards" : 2, "relocating_shards" : 0, "initializing_shards" : 0, "unassigned_shards" : 0 }, ".monitoring-es-2-2017.04.19" : { "status" : "green", "number_of_shards" : 1, "number_of_replicas" : 1, "active_primary_shards" : 1, "active_shards" : 2, "relocating_shards" : 0, "initializing_shards" : 0, "unassigned_shards" : 0 }, ".monitoring-es-2-2017.04.18" : { "status" : "green", "number_of_shards" : 1, "number_of_replicas" : 1, "active_primary_shards" : 1, "active_shards" : 2, "relocating_shards" : 0, "initializing_shards" : 0, "unassigned_shards" : 0 }, ".monitoring-kibana-2-2017.04.18" : { "status" : "green", "number_of_shards" : 1, "number_of_replicas" : 1, "active_primary_shards" : 1, "active_shards" : 2, "relocating_shards" : 0, "initializing_shards" : 0, "unassigned_shards" : 0 }, ".monitoring-kibana-2-2017.04.19" : { "status" : "green", "number_of_shards" : 1, "number_of_replicas" : 1, "active_primary_shards" : 1, "active_shards" : 2, "relocating_shards" : 0, "initializing_shards" : 0, "unassigned_shards" : 0 } } }
stats:集群統計信息
curl 'localhost:9200/_cluster/stats'
集群節點的統計信息:
curl 'localhost:9200/_nodes/stats'
[root@Node2 ~]# curl 'localhost:9200/_cluster/stats?pretty' { "_nodes" : { "total" : 2, "successful" : 2, "failed" : 0 }, "cluster_name" : "RK", "timestamp" : 1492754076865, "status" : "green", "indices" : { "count" : 9, "shards" : { "total" : 18, "primaries" : 9, "replication" : 1.0, "index" : { "shards" : { "min" : 2, "max" : 2, "avg" : 2.0 }, "primaries" : { "min" : 1, "max" : 1, "avg" : 1.0 }, "replication" : { "min" : 1.0, "max" : 1.0, "avg" : 1.0 } } }, "docs" : { "count" : 93528, "deleted" : 286 }, "store" : { "size_in_bytes" : 81565430, "throttle_time_in_millis" : 0 }, "fielddata" : { "memory_size_in_bytes" : 6608, "evictions" : 0 }, "query_cache" : { "memory_size_in_bytes" : 0, "total_count" : 16, "hit_count" : 0, "miss_count" : 16, "cache_size" : 0, "cache_count" : 0, "evictions" : 0 }, "completion" : { "size_in_bytes" : 0 }, "segments" : { "count" : 96, "memory_in_bytes" : 902530, "terms_memory_in_bytes" : 557988, "stored_fields_memory_in_bytes" : 38640, "term_vectors_memory_in_bytes" : 0, "norms_memory_in_bytes" : 3712, "points_memory_in_bytes" : 52750, "doc_values_memory_in_bytes" : 249440, "index_writer_memory_in_bytes" : 0, "version_map_memory_in_bytes" : 0, "fixed_bit_set_memory_in_bytes" : 0, "max_unsafe_auto_id_timestamp" : -1, "file_sizes" : { } } }, "nodes" : { "count" : { "total" : 2, "data" : 2, "coordinating_only" : 0, "master" : 2, "ingest" : 2 }, "versions" : [ "5.3.0" ], "os" : { "available_processors" : 3, "allocated_processors" : 3, "names" : [ { "name" : "Linux", "count" : 2 } ], "mem" : { "total_in_bytes" : 4227088384, "free_in_bytes" : 94605312, "used_in_bytes" : 4132483072, "free_percent" : 2, "used_percent" : 98 } }, "process" : { "cpu" : { "percent" : 0 }, "open_file_descriptors" : { "min" : 162, "max" : 214, "avg" : 188 } }, "jvm" : { "max_uptime_in_millis" : 30736656, "versions" : [ { "version" : "1.8.0_121", "vm_name" : "OpenJDK 64-Bit Server VM", "vm_version" : "25.121-b13", "vm_vendor" : "Oracle Corporation", "count" : 2 } ], "mem" : { "heap_used_in_bytes" : 224113584, "heap_max_in_bytes" : 4268818432 }, "threads" : 73 }, "fs" : { "total_in_bytes" : 38102884352, "free_in_bytes" : 25168912384, "available_in_bytes" : 23233347584, "spins" : "true" }, "plugins" : [ { "name" : "x-pack", "version" : "5.3.0", "description" : "Elasticsearch Expanded Pack Plugin", "classname" : "org.elasticsearch.xpack.XPackPlugin" } ], "network_types" : { "transport_types" : { "netty4" : 2 }, "http_types" : { "netty4" : 2 } } } }
集群狀態信息:
curl 'localhost:9200/_cluster/state/<metrics>?pretty'
metrics:
version
master_node
nodes
routing_table
metadata
blocks
[root@Node2 ~]# curl 'localhost:9200/_cluster/state?pretty' [root@Node2 ~]# curl 'localhost:9200/_cluster/state/version?pretty' { "cluster_name" : "RK", "version" : 19, "state_uuid" : "tXW8CtBXS1a3Sn1wCBci2g" } [root@Node2 ~]# curl 'localhost:9200/_cluster/state/master_node?pretty' { "cluster_name" : "RK", "master_node" : "bMAYDjb2Rsyfpn92Lnax3w" } [root@Node2 ~]# curl 'localhost:9200/_cat/master' bMAYDjb2Rsyfpn92Lnax3w 192.168.2.116 192.168.2.116 node7 [root@Node2 ~]# curl 'localhost:9200/_cat/nodes' 192.168.2.114 7 96 0 0.00 0.00 0.00 mdi - node2 192.168.2.116 5 100 0 0.00 0.00 0.00 mdi * node7
三、ES的術語詳解
在Elasticsearch中存儲數據的行為就叫做索引(indexing),不過在索引之前,我們需要明確數據應該存儲在哪里。
在Elasticsearch中,文檔歸屬于一種類型(type),而這些類型存在于索引(index)中,我們可以畫一些簡單的對比圖來類比傳統關系型數據庫:
Relational DB -> Databases -> Tables -> Rows -> Columns Elasticsearch -> Indices -> Types -> Documents -> Fields
Elasticsearch集群可以包含多個索引(indices)(數據庫),每一個索引可以包含多個類型(types)(表),每一個類型包含多個文檔(documents)(行),然后每個文檔包含多個字段(Fields)(列)。
你可能已經注意到索引(index)這個詞在Elasticsearch中有著不同的含義,所以有必要在此做一下區分:
索引(名詞) 如上文所述,一個索引(index)就像是傳統關系數據庫中的數據庫,它是相關文檔存儲的地方,index的復數是indices 或indexes。
索引(動詞) 「索引一個文檔」表示把一個文檔存儲到索引(名詞)里,以便它可以被檢索或者查詢。這很像SQL中的INSERT
關鍵字,差別是,如果文檔已經存在,新的文檔將覆蓋舊的文檔。
倒排索引 傳統數據庫為特定列增加一個索引,例如B-Tree索引來加速檢索。Elasticsearch和Lucene使用一種叫做倒排索引(inverted index)的數據結構來達到相同目的。
四、CRUD操作相關的API
創建:
[root@Node2 ~]# curl -X PUT localhost:9200/students/class1/1?pretty -d ' { "first_name":"Jing", "last_name":"Guo", "gender":"Male", "courses":"Xianglong Shiba Zhang" }' { "_index" : "students", "_type" : "class1", "_id" : "1", "_version" : 1, "result" : "created", "_shards" : { "total" : 2, "successful" : 2, "failed" : 0 }, "created" : true } [root@Node2 ~]# curl localhost:9200/_cat/indices?v health status index uuid pri rep docs.count docs.deleted store.size pri.store.size green open .monitoring-es-2-2017.04.19 EMZBcpI7RV6V9aZZ46KSWw 1 1 39720 84 34.1mb 17mb green open .monitoring-kibana-2-2017.04.20 JqpaERNnQwOhTpVu0F-yCA 1 1 169 0 285.9kb 142.9kb green open .monitoring-es-2-2017.04.20 nLnAKVKKSOavBc7dc2mOgA 1 1 5536 126 5.5mb 2.7mb green open .kibana FX7h92rvRwuxxPAYSeORTw 1 1 1 0 6.3kb 3.1kb green open .monitoring-es-2-2017.04.18 FuWnLKlRRoWlMKznkAle2w 1 1 38676 50 31.8mb 15.9mb green open .monitoring-kibana-2-2017.04.19 5DNI-F44TJmaErmQ2qRHPQ 1 1 2121 0 969.3kb 484.6kb green open .monitoring-es-2-2017.04.17 nyfdDSpsQKuyn4ZTAdm6aw 1 1 3874 24 3.2mb 1.6mb green open students 104QJMEGQjCtxMVI9rWvhQ 5 1 1 0 10.8kb 5.4kb green open .monitoring-data-2 pIeAPjAQTuihoJenwmlTGA 1 1 3 2 16.6kb 8.3kb green open .monitoring-kibana-2-2017.04.18 aV6CvYltR2aNl3URpPVDig 1 1 3428 0 1.6mb
我們看到path:/students/class1/1包含三部分信息:
名字 | 說明 |
---|---|
students | 索引名 |
class1 | 類型名 |
1 | 這個員工的ID(如果該ID已存在則替換) |
請求實體(JSON文檔),包含了這個員工的所有信息。他的名字叫“Guo Jing”,Male,學習Xianglong Shiba Zhang
很簡單吧!它不需要你做額外的管理操作,比如創建索引或者定義每個字段的數據類型。我們能夠直接索引文檔,Elasticsearch已經內置所有的缺省設置,所有管理操作都是透明的。
和mongodb數據庫的GRUD很像,索引和類別不用事先創建
接下來,讓我們在目錄中加入更多學員信息:
[root@Node2 ~]# curl -X PUT "localhost:9200/students/class1/2?pretty" -d ' { "first_name":"Rong", "last_name":"Huang", "gender":"Female", "age":23, "courses":"Luoying Shenjian" }' { "_index" : "students", "_type" : "class1", "_id" : "2", "_version" : 1, "result" : "created", "_shards" : { "total" : 2, "successful" : 2, "failed" : 0 }, "created" : true }
列出類型中的文檔:GET方法
[root@Node2 ~]# curl localhost:9200/students/class1/1?pretty { "_index" : "students", "_type" : "class1", "_id" : "1", "_version" : 1, "found" : true, "_source" : { "first_name" : "Jing", "last_name" : "Guo", "gender" : "Male", "courses" : "Xianglong Shiba Zhang" } } [root@Node2 ~]# curl localhost:9200/students/?pretty # 列出索引的有有類型結構 { "students" : { "aliases" : { }, "mappings" : { "class1" : { "properties" : { "age" : { "type" : "long" }, "courses" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "first_name" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "gender" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "last_name" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } } } } }, "settings" : { "index" : { "creation_date" : "1492762539451", "number_of_shards" : "5", "number_of_replicas" : "1", "uuid" : "104QJMEGQjCtxMVI9rWvhQ", "version" : { "created" : "5030099" }, "provided_name" : "students" } } } }
更新文檔:
PUT方法會覆蓋原有文檔
使用相同的ID替換掉原文檔
POST方法,使用_update API,可以只更新部分內容,得
[root@Node2 ~]# curl -X POST 'localhost:9200/students/class1/2/_update?pretty' -d ' > { > "doc": {"age":22} > }' { "_index" : "students", "_type" : "class1", "_id" : "2", "_version" : 2, "result" : "updated", "_shards" : { "total" : 2, "successful" : 2, "failed" : 0 } } [root@Node2 ~]# curl localhost:9200/students/class1/2?pretty { "_index" : "students", "_type" : "class1", "_id" : "2", "_version" : 2, "found" : true, "_source" : { "first_name" : "Rong", "last_name" : "Huang", "gender" : "Female", "age" : 22, "courses" : "Luoying Shenjian" } }
刪除文檔:DELETE 方法
[root@Node2 ~]# curl -X DELETE localhost:9200/students/class1/1?pretty { "found" : true, "_index" : "students", "_type" : "class1", "_id" : "1", "_version" : 2, "result" : "deleted", "_shards" : { "total" : 2, "successful" : 2, "failed" : 0 } } [root@Node2 ~]# curl localhost:9200/students/class1/1?pretty { "_index" : "students", "_type" : "class1", "_id" : "1", "found" : false }
刪除索引:
[root@Node2 ~]# curl localhost:9200/_cat/indices?v health status index uuid pri rep docs.count docs.deleted store.size pri.store.size green open .monitoring-es-2-2017.04.19 EMZBcpI7RV6V9aZZ46KSWw 1 1 39720 84 34.1mb 17mb green open .monitoring-kibana-2-2017.04.20 JqpaERNnQwOhTpVu0F-yCA 1 1 169 0 285.9kb 142.9kb green open .monitoring-es-2-2017.04.20 nLnAKVKKSOavBc7dc2mOgA 1 1 5536 126 5.5mb 2.7mb green open .kibana FX7h92rvRwuxxPAYSeORTw 1 1 1 0 6.3kb 3.1kb green open .monitoring-es-2-2017.04.18 FuWnLKlRRoWlMKznkAle2w 1 1 38676 50 31.8mb 15.9mb green open .monitoring-kibana-2-2017.04.19 5DNI-F44TJmaErmQ2qRHPQ 1 1 2121 0 969.3kb 484.6kb green open .monitoring-es-2-2017.04.17 nyfdDSpsQKuyn4ZTAdm6aw 1 1 3874 24 3.2mb 1.6mb green open .monitoring-data-2 pIeAPjAQTuihoJenwmlTGA 1 1 3 2 16.6kb 8.3kb green open .monitoring-kibana-2-2017.04.18 aV6CvYltR2aNl3URpPVDig 1 1 3428 0 1.6mb 850.9kb green open students 104QJMEGQjCtxMVI9rWvhQ 5 1 0 0 21.6kb 10.8kb [root@Node2 ~]# curl -X DELETE localhost:9200/students?pretty { "acknowledged" : true } [root@Node2 ~]# curl localhost:9200/_cat/indices?v health status index uuid pri rep docs.count docs.deleted store.size pri.store.size green open .monitoring-es-2-2017.04.19 EMZBcpI7RV6V9aZZ46KSWw 1 1 39720 84 34.1mb 17mb green open .monitoring-kibana-2-2017.04.20 JqpaERNnQwOhTpVu0F-yCA 1 1 169 0 285.9kb 142.9kb green open .monitoring-es-2-2017.04.20 nLnAKVKKSOavBc7dc2mOgA 1 1 5536 126 5.5mb 2.7mb green open .kibana FX7h92rvRwuxxPAYSeORTw 1 1 1 0 6.3kb 3.1kb green open .monitoring-es-2-2017.04.18 FuWnLKlRRoWlMKznkAle2w 1 1 38676 50 31.8mb 15.9mb green open .monitoring-kibana-2-2017.04.19 5DNI-F44TJmaErmQ2qRHPQ 1 1 2121 0 969.3kb 484.6kb green open .monitoring-es-2-2017.04.17 nyfdDSpsQKuyn4ZTAdm6aw 1 1 3874 24 3.2mb 1.6mb green open .monitoring-kibana-2-2017.04.18 aV6CvYltR2aNl3URpPVDig 1 1 3428 0 1.6mb 850.9kb green open .monitoring-data-2 pIeAPjAQTuihoJenwmlTGA 1 1 3
這里沒有對類型的操作?
五、搜索(查詢)數據
查詢數據需要使用ES的_search API
Query DSL:域類型(格式)查詢語言 ,基于JSON,用于實現諸多類型的查詢操作,
比如:簡單查詢,模糊插敘,范圍查詢,布爾查詢等
ES查詢操作的執行分為兩個階段:
分散階段:
合并階段:
ES中搜索的數據廣義上可被理解為兩類:
types:exact 在指定類型上做精確值搜索 ,在搜索時做精確搜索
精確值:指未經加工的原始值,如:Notebook,notebook就不是精確值
full-text:全文搜索
用于引用文本中數據,判斷文檔在多大程度上匹配查詢請求;即評估文檔與用戶請求查詢的相關度;為了完成full-text搜索,ES必須首先分析文本,并創建倒排索引。倒排索引中的數據還需要進行“正規化”為標準格式。
查詢方式:
向ES發起查詢請求的方式有兩種:
1、通過Restful request API查詢,也稱為query string
2、通過發送REST request body進行
列出索引的所有文檔:
[root@Node2 ~]# curl localhost:9200/students/_search?pretty # Restful request API "took" : 5, # 執行時長,ms "timed_out" : false, # 查詢是否超時 "_shards" : { "total" : 5, "successful" : 5, "failed" : 0 }, "hits" : { "total" : 2, "max_score" : 1.0, "hits" : [ { "_index" : "students", "_type" : "class1", "_id" : "2", "_score" : 1.0, "_source" : { "first_name" : "Rong", "last_name" : "Huang", "gender" : "Female", "age" : 23, "courses" : "Luoying Shenjian" } }, { "_index" : "students", "_type" : "class1", "_id" : "1", "_score" : 1.0, "_source" : { "first_name" : "Jing", "last_name" : "Guo", "gender" : "Male", "courses" : "Xianglong Shiba Zhang" } } ] } } [root@Node2 ~]# curl localhost:9200/students/_search?pretty -d ' # REST request body > { > "query":{"match_all":{}} > }' { "took" : 93, "timed_out" : false, "_shards" : { "total" : 5, "successful" : 5, "failed" : 0 }, "hits" : { "total" : 3, "max_score" : 1.0, "hits" : [ { "_index" : "students", "_type" : "class1", "_id" : "2", "_score" : 1.0, "_source" : { "first_name" : "Rong", "last_name" : "Huang", "gender" : "Female", "age" : 23, "courses" : "Luoying Shenjian" } }, { "_index" : "students", "_type" : "class1", "_id" : "1", "_score" : 1.0, "_source" : { "first_name" : "Jing", "last_name" : "Guo", "gender" : "Male", "courses" : "Xianglong Shiba Zhang" } }, { "_index" : "students", "_type" : "s1", "_id" : "yw", "_score" : 1.0, "_source" : { "first_name" : "xiejun", "age" : 27 } } ] } }
多索引,多類型查詢:
/_search:所有索引
/INDEX_NAME/_search:單索引
/INDEX1_NAME1,INDEX2_NAME/_search:多索引
/s*,t*/_search:
/students/class1/_search:單類型搜索
/students/class1,class1/_search:多類型搜索
Mapping和Analysis:映射和分析
ES對每一個文檔,會取得其所有域的所有值,生成一個名為“_all”的域;執行查詢時,如果在query_string未指定查詢的域,則在_all域上執行操作
例子:
GET /_search?q="Xianglog" # 沒有指定域則在_all域中查詢
GET /_search?q='Xianglong%20Shiba%20Zhang' # 指定域中查詢,空格需要使用%20代替
GET /_search?q=courses:'Xianglong'
GET /_search?q=courses:'Xianglong%20Shiba%20Zhang'
數據類型:
string,numbers,boolean,dates
查看文檔中域的數據類型:
[root@Node2 ~]# curl "localhost:9200/students/class1/_mapping?pretty" { "students" : { "mappings" : { "class1" : { "properties" : { "age" : { "type" : "long" }, "courses" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "first_name" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "gender" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "last_name" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } } } } } } }
創建倒排索引的過程:
分詞 -- 正規化;這個過程即是分析,分析需要分析器(analyzer)來進行
分析器由三個組件構成:
字符過濾器,分詞器,分詞過濾器
ES內置的分析器:
Standard analyzer:標準分析器,ES的默認分析器,適用于多種語言,基于unicode分析
Simple analyzer:簡單分析器,根據所有的非字母分詞(把非字母當作單詞邊界)
Whitespace analyzer:只把空白符當作單詞邊界
Language analyzer:適用于多種語言的專用語言分析器
分析器不僅在創建索引時用到,在構建查詢時也會用到
request body:
又分成2類:
query dsl:執行full-text查詢時,基于相關度來評判其匹配結果
查詢執行過程復雜,且不會被緩存
filter dsl:執行exact查詢時,基于其結果為"yes"或"no"進行評判
速度快,且結果緩存
filter dsl:
term filter:精確匹配包含指定term的文檔
如:{
"query":{
"term":{
"name":"Guo"
}
}
}
[root@Node2 ~]# curl "localhost:9200/students/_search?pretty" -d ' { "query":{ "term":{ "name":"Guo" } } }' { "took" : 3, "timed_out" : false, "_shards" : { "total" : 5, "successful" : 5, "failed" : 0 }, "hits" : { "total" : 0, "max_score" : null, "hits" : [ ] } }
terms filter:用于多值精確匹配
如:{
"query":{
"terms":{
“name”:["Guo","Rong"]
}
}
}
range filters:用于在指定范圍內查詢數值或時間
如:{
"query":{
“range”:{
"age":{
"gte":15,
"lte":25
}
}
}
}
[root@Node2 ~]# curl "localhost:9200/students/_search?pretty" -d ' { "query":{ "range":{ "age":{ "gte":15, "lte":27 } } } > }' { "took" : 24, "timed_out" : false, "_shards" : { "total" : 5, "successful" : 5, "failed" : 0 }, "hits" : { "total" : 2, "max_score" : 1.0, "hits" : [ { "_index" : "students", "_type" : "class1", "_id" : "2", "_score" : 1.0, "_source" : { "first_name" : "Rong", "last_name" : "Huang", "gender" : "Female", "age" : 23, "courses" : "Luoying Shenjian" } }, { "_index" : "students", "_type" : "s1", "_id" : "yw", "_score" : 1.0, "_source" : { "first_name" : "xiejun", "age" : 27 } } ] } }
exists and missing filters:
{
"query":{
"exists":{
"age":23
}
}
}
boolean filter:基于boolean的邏輯來合并多個filter子句
must:其內部所有的子句條件必須同時匹配,即and
例:
must:{
"term":{"age":25},
"term":{"gender":"Female"}
}
must_not:其所有子句必須不匹配,即not
must_not:{
"term":{"age":25}
}
should:至少有一個子句匹配,即or
should:{
"term":{"age":25},
"term":{"gender":"Female"}
}
QUERY DSL:
match_all Query:用于匹配所有文檔,沒有指定任何query,默認即為match_all query
{"match_all":{}}
match Query:在幾乎任何域上執行full-text或exact-value查詢
如果執行full-text查詢需要先做分析
{"match":{"students":"Guo}}
如果執行exact-value查詢則搜索精確值,此時,建議使用過濾而非查詢
{"match":{"name":"Guo"}}
multi_match Query:用于在多個域上執行相同的查詢
{
“multi_match”:{
“ query”:{
"students":"Guo"
}
"field":{
"name",
"description"
}
}
}
bool query:基于boolean邏輯合并多個查詢語句,與bool filter不同的是,查詢子句不是返回“yes”或"no",而是其計算出的匹配度分值,因此boolean query會為各子句合并其score:
must:
must_not:
should:
也可以合并filter和query語句:
{
"filterd":{
query:{"match":{"gender":"Female"}
filter:{"term":{"age":25}}
}
}
查詢語句語法檢查:
GET /INDEX/_validate/query?explain&pretty -d '
{
...
}'
顯示詳細信息:
GET /INDEX/_valudate/query?explain&pretty -d '
{
...
}'
[root@Node2 ~]# curl "localhost:9200/students/_validate/query?pretty" -d ' { "query":{ "range":{ "age":{ "gte":15, "lte":27 } } } }' { "valid" : true, "_shards" : { "total" : 1, "successful" : 1, "failed" : 0 } } [root@Node2 ~]# curl "localhost:9200/students/_validate/query?explain&pretty" -d ' { "query":{ "range":{ "age":{ "gte":15, "lte":27 } } } }' { "valid" : true, "_shards" : { "total" : 1, "successful" : 1, "failed" : 0 }, "explanations" : [ { "index" : "students", "valid" : true, "explanation" : "age:[15 TO 27]" } ] }
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。