資料庫複習 3 建立表 資料型別
本文是對ElasticSearch元件初步學習的一個知識總結,包括如下章節的內容:
- 概述
- 快速上手
- 邏輯概念
- 使用者介面
- 關於ELKB
預備知識:
1、本文對ElasticSerach的介紹會涉及與關係資料庫的對比,為了更好地學習,可提前對關係資料庫的基本概念有所瞭解。
2、ElasticSerach的資料儲存採用JSON的資料格式,為了更好地學習,可提前對JSON的概念有所瞭解。
3、ElasticSerach對外提供的是RESTful Api訪問介面,為了更好地學習,可提前對RESTful的概念有所瞭解。
二、快速上手
ES雖然是一個強大的分散式系統,但其易用性設計的非常好,安裝和使用都很簡單,下面我們來快速體驗下。
(一)安裝
ES需要java環境,最好是java8,需要設定JAVA_HOME環境變數。ES的安裝非常簡單,開箱即用,首先我們可以從官網www.elastic.co下載相應的二進位制版本,對於Windows作業系統,可下載zip檔案,對於linux作業系統,可下載tar檔案。
下載二進位制包後,解壓到任何一個目錄下。如果不做任何配置,則採用預設的配置啟動ES。執行ES安裝目錄下的bin目錄的elasticsearch指令碼(windows下為elasticsearch.bat)則可以以單例項的方式啟動ES。在linux系統中啟動ES有可能會報錯誤,這在下面會詳細介紹。
我們這裡是啟動的ES的單個例項,ES可以以叢集的方式執行(即在多臺機器上啟動多個ES例項)。因為單節點模式和叢集模式從使用角度看並沒有太多的區別,所以本文介紹的都是基於ES在單節點方式執行的。叢集的方式在後續的文章中介紹。
啟動ES後,下面就可以利用ES提供的RESTful API去使用它。我們可以在瀏覽器或任何web工具中輸入 http://localhost:9200 地址,得到如下的資訊(ES系統的基本資訊):
{ "name" : "H12K5tk", "cluster_name" : "elasticsearch", "cluster_uuid" : "2RAwSskjQh6xDxLrDHBTtQ", "version" : { "number" : "5.6.9", "build_hash" : "877a590", "build_date" : "2018-04-12T16:25:14.838Z", "build_snapshot" : false, "lucene_version" : "6.6.1" }, "tagline" : "You Know, for Search" }
返回的是本節點(ES例項的)name,以及ES叢集的一些基本資訊,如叢集名,版本資訊等
(二)啟動錯誤
在Linux系統中啟動ES,可能會報一些錯誤,導致啟動失敗。下面是一些常見的錯誤與解決方案(這也是本文在Centos7系統中啟動ES碰到的問題)。
1、錯誤1:max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536]錯誤很好理解,就是指es程序可允許開啟的最大檔案數只有4096,太小了,需要提升到65536。因為ES需要開啟很多檔案,最大4096個不夠,需要調整作業系統中的配置。
在Linux的系統中對於程序(Process)會有一些限制(limit),限制有很多種,常見的如對開啟檔案(Open Files)最大數量的限制。在linux中這些限制是分為軟限制(soft limit)和硬限制(hard limit)兩類。它們的區別就是軟限制可以在程式的程序中自行改變(突破限制),而硬限制則不行(除非程式程序有root許可權)。
使用ulimit 命令可以分別檢視軟限制和硬限制,區別是在檢視的引數前加 S 或 H。例如,檢視開啟檔案數限制(引數是n):
#檢視軟限制 ulimit -Sn #檢視硬限制 ulimit -Hn
改變這個限制的辦法是修改/etc/security/limits.conf檔案,增加配置,如在配置檔案中增加如下資訊:
* soft nofile 65536 * hard nofile 65536
注意,最前面的 * 代表這個設定對所有程序都有效,如果只對指定程序有效,將*改為具體的程序名。
2、錯誤2:max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
這個錯誤是指Linux程序的vma大小不足,需要提高。這可以修改/etc/sysctl.conf檔案,增加配置vm.max_map_count=262144,如:
vm.max_map_count=262144
修改配置檔案後,執行 命令sysctl -p 讓生效(注意,一定要執行),如:
[hadoop@master bin]$ sudo sysctl -p [sudo] password for hadoop: vm.max_map_count = 262144
另外,在作業系統配置檔案被修改後,最好重新登入,確保新的終端能獲取到修改後的資訊。
(三)訪問ES
因為ES對外提供了RESTful的訪問介面,所以我們可以用任意一種web client工具來訪問ES,最簡單的如linux下的curl程式,還可以用如Postman這樣的工具(Postman是一個非常有用的 Http Client 工具,可用來測試 Web 服務),也可以在瀏覽器上安裝外掛,如chrome中的Sense外掛(該外掛可以很方便的操作ES)。
當然我們可以利用第三方http client庫自己編寫程式碼來訪問ES。不過ES自身也提供了JAVA API來操作ES,這個在後面介紹
下面我們使用RESTful API來舉例使用ES。一個完整的REST請求包括如下三部分:
1、操作型別,如GET,PUT,POST,DELETE等
2、URL部分,如http://localhost:9200/blogs/blog/1
3、請求正文內容。對於GET請求,沒有單獨的請求正文內容,請求資訊都包含在URL中。對於PUT,POST等操作,可以帶正文內容,正文內容採用josn的格式,具體下面例子會看到。
ES的REST請求的返回內容的格式絕大部分都是JOSN格式的。也就是說請求和響應的內容都是JSON格式,這樣有較好的一致性。
下面來看具體的例子:
1、插入資料
往ES中插入資料,可以執行如下的操作:
PUT http://localhost:9200/blogs/blog/1 { "title": "es info", "content": "about elasticsearch", "author": "jack", "year":2018 }這裡執行的是http的PUT操作,url後面跟著的json格式內容是請求的正文,即儲存到ES中的資料。關於該url和json內容的含義我們在後面介紹,這裡只需知道這樣一個簡單的http的PUT請求就把一條json資料儲存到ES中。上述操作我們可以在如Postman這樣的工具中進行。
該請求成功後伺服器返回的資訊如下:
{ "_index": "blogs", "_type": "blog", "_id": "1", "_version": 1, "result": "created", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "created": true }
上面響應資訊的格式也是josn格式,其中欄位的含義我們後面再介紹。
2、查詢資料
上面往ES中插入了一條資料,下面我們可以利用http的GET操作來獲取剛才插入的資料。http請求如下:
GET http://localhost:9200/blogs/blog/1
該請求成功後伺服器返回的資訊如下:
{ "_index": "blogs", "_type": "blog", "_id": "1", "_version": 1, "found": true, "_source": { "title": "es info", "content": "about elasticsearch", "author": "jack", "year": 2018 } }
可以看出,返回的josn內容中,相比插入操作,有這幾個欄位的內容發生了變化:
"_version" : 2, "result" : "updated", "created" : false
可以看到,記錄的 Id 沒變,但是版本(version)從1變成2,操作型別(result)從created變成updated,created欄位變成false,因為這次不是新建記錄,而是修改操作。
這時如果我們執行
GET http://localhost:9200/blogs/blog/1
查詢操作,會看到返回的Document資料是修改後的資料。
ES文件的版本號是有用的,我們在修改資料時,可以傳入一個版本號。這樣當在一個客戶端讀取和更新文件的間隔中,有另外客戶端更新了資料。如果這個客戶端的更新操作傳入了版本號(前面讀取的版本號),這時因為傳入的版本號和當期實際的版本號不一致,就會操作失敗。這樣就防止可能的資料衝突。這也是ES採用樂觀併發控制(OCC)機制的體現。
加入版本號進行更新,只需在url後面加上version引數,如:
PUT http://localhost:9200/blogs/blog/1?version=2
4、刪除操作
通過DELETE操作,可以刪除ES中的資料。HTTP請求如下:
DELETE http://localhost:9200/blogs/blog/1
該請求成功後伺服器返回的資訊如下:
{ "found": true, "_index": "blogs", "_type": "blog", "_id": "1", "_version": 2, "result": "deleted", "_shards": { "total": 2, "successful": 1, "failed": 0 } }
如果我們這時去執行GET操作,如
GET http://localhost:9200/blogs/blog/1
該請求成功後伺服器返回的資訊如下:
{ "_index": "blogs", "_type": "blog", "_id": "1", "found": false }
從響應的結果可以看出,沒有查到資料。
5、搜尋操作
下面我們來看下ES最強大的搜尋操作,首先我們來先插入2條資料,包括前面插入和被刪除的資料。
PUT http://localhost:9200/blogs/blog/1 { "title": "es info", "content": "about elasticsearch", "author": "jack", "year":2018 } PUT http://localhost:9200/blogs/blog/2 { "title": "zk info", "content": "about zookeeper", "author": "jack", "year":2018 }
下面我們來執行根據給定的字串進行查詢,只要資料中有包含給定字串的內容就認為匹配上,查詢命令如下:
POST http://localhost:9200/_search { "query": { "query_string": { "query": "elasticsearch" } } }
返回的結果如下:
{ "took": 3, "timed_out": false, "_shards": { "total": 10, "successful": 10, "skipped": 0, "failed": 0 }, "hits": { "total": 1, "max_score": 0.26742277, "hits": [ { "_index": "blogs", "_type": "blog", "_id": "1", "_score": 0.26742277, "_source": { "title": "es info", "content": "about elasticsearch", "author": "jack", "year": 2018 } } ] } }
可以看出,搜尋到了資料。我們可以試著改變上面查詢條件中"query"引數的值,來觀察結果的變化。
上面的搜尋是搜尋整個json資料中的資訊,我們也可以只搜尋指定json欄位中的內容。如:
POST http://localhost:9200/_search { "query": { "query_string": { "query": "jack", "fields": ["author"] } } }
上面的REST語句表示只在欄位author中查詢存在jack字串的資料。欄位通過查詢條件中的filelds引數指定,可以看出,同時可指定多個欄位。 對比關係資料庫,ES的搜尋操作有點類似關係資料庫中帶like子句的select語句。
可以看出,利用ES的RESTful Api進行操作還是比較簡單的,當然我們只是列舉了幾個最基本的操作。上面通過舉例讓我們站在使用者的角度對ES有了個初步的認識,下面章節繼續展開更為詳細的介紹。
(四)遠端訪問
上面例子中我們都是在本地利用REST介面訪問ES的,即web客戶端執行在ES例項所在的機器上,所以url中用的是localhost。 如果需要支援對ES的遠端訪問,可以修改ES安裝目錄的config/elasticsearch.yml檔案,去掉network.host的註釋,將它的值改成0.0.0.0,然後重新啟動 ES。配置檔案中資訊如:
network.host: 0.0.0.0
上面配置,設成0.0.0.0讓任何一臺機器都可以訪問。線上服務不要這樣設定,要設成具體的 IP,如:
network.host: 192.168.0.1
三、邏輯概念
我們上面的例子使用了 http://localhost:9200/blogs/blog/1 這樣的ulr來進行資料的插入、查詢及搜尋和刪除操作。拋開操作的方式,感覺和關係資料庫的操作有類似的地方。這其實也是正常的,因為資料庫也是用來進行資料儲存和分析(查詢)的,所以從功能上說肯定有很多類似的地方。我們知道關係資料庫有資料庫、表、記錄、欄位等概念,為了更好地理解ES的邏輯架構,我們在介紹ES的一些重要概念的時候會對比關係資料庫中的一些概念(一)索引(Index)
ES資料管理的頂層單位就叫做 Index(索引)。它不是關係資料庫中索引的概念,是單個數據庫的同義詞,即可以把它等價於關係資料庫中的單個數據庫。Index的名稱必須小寫。
既然Index是ES管理資料的頂層單位,肯定先需要有索引,才能進行後續的資料儲存等操作,類似關係資料庫中得首先有資料庫一樣。可前面的操作我們並沒有看到建立Index的操作。是不是ES啟動後有一個預設的Index呢?
其實情況是這樣的,上面的REST請求 http://localhost:9200/blogs/blog/1 中的 blogs就是一個索引名,當我們執行資料插入操作時,如果url中指定的索引不存在,則ES會自動建立該索引。就如我們前面的例子,我們插入資料時,索引blogs並不存在,所以ES按照預設的設定自動建立了blogs索引。
我們可以單獨建立一個索引,操作如下:
PUT http://localhost:9200/topics
上面操作通過http的PUT操作,建立了一個名稱為topics的索引。
操作成功後的響應資訊如下:
{ "acknowledged": true, "shards_acknowledged": true, "index": "topics" }
我們可以檢視到ES中的所有索引,操作如下:
GET http://localhost:9200/_cat/indices?v
響應結果如下:
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size yellow open blogs hM... 5 1 2 0 10.2kb 10.2kb yellow open topics hV... 5 1 0 0 810b 810b
結果以表格的形式顯示,第一行為表頭。因為前面的操作我們已經建立了blogs索引,加上剛建立的topics索引,所以我們看到結果有2條記錄。
通過DELETE操作,我們可以刪除指定的索引,如下面操作:
DELETE http://localhost:9200/topics
操作成功的響應結果如下:
{ "acknowledged": true }
這表示刪除索引成功,如果我們這時再去查詢所有索引,會發現topics索引沒有了。
(二)型別(Type)
在索引中,可以定義一個或多個型別(type),型別是索引的邏輯分割槽,是同一索引中有公共欄位的文件的集合。比如在一個部落格系統中,我們可以將使用者資料放到一種型別中,將文章資料放到一種型別中,將對文章的評論資訊放到一種型別中。
型別不需要單獨建立,在插入資料(如上面的例子)會自動建立。對於 http://localhost:9200/blogs/blog/1 這個url,其中的blog就是型別(type)名。
相對關係資料庫來說,型別可以類比成關係資料庫中的表。
需要注意的是,根據規劃,Elastic 6.x 版只允許每個 Index 包含一個 Type,7.x 版將會徹底移除 Type。
所以我們在實際使用中,不用過多考慮Type的作用。
(三)文件(Document)
Document是Index中的單條記錄,它就像關係資料庫中表中的記錄(行)。Document 使用 JSON 格式表示,如上面插入資料時的url後面跟的請求資料:
PUT http://localhost:9200/blogs/blog/1 { "title": "es info", "content": "about elasticsearch", "author": "jack", "year":2018 }
ES的每個儲存在Index中的Document都有一個型別(type)和一個唯一的ID。這個ID可以使用者在建立文件時顯示指定,如上面url最後的1,也可以由ES自動生成(後面會介紹)。
JSON資料是一種半結構化的資料格式,它由一個個的欄位組成,欄位有欄位名、欄位的值,和欄位型別,比如上面的title欄位就是一個字串型別,year欄位就是一個整數型別。JSON資料的欄位型別不需要顯示定義,由欄位的內容推斷出來,比如字串是要放到引號中,整數則不能。
同一個 Index 裡面的 Document(即使是位於同一個Type下),不要求有相同的結構(即相同的欄位和欄位型別),但是最好保持相同,這樣有利於提高搜尋效率。需要注意的是,同一個欄位名的欄位,不能在這個文件中是字串型別,而在另外一個字串中是陣列型別。舉個例子,上面舉例中我們插入瞭如下的資料:
PUT http://localhost:9200/blogs/blog/1 { "title": "es info", "content": "about elasticsearch", "author": "jack", "year":2018 }
這時如果插入如下資料:
PUT http://localhost:9200/blogs/blog/2 { "title": "es info", "content": "about elasticsearch", "author": "jack", "year": "2018年" }
也就是這裡插入的year欄位值是個字串,則時ES的響應就會報錯,報型別不一致的錯誤,因為前面插入的資料已經讓ES把year欄位認作為整型資料。但如果我們寫成 "year": "2018" 這樣的格式,雖然看上去year欄位是字串型別,但因為實際資料是整數,則不會報錯。
因為即使是同一個Type下的Docuemnt也不要求有相同的資料模型,所以邏輯上Type與關係資料庫的表對應,實際意義差別還是挺大的。在關係資料庫下,表中的每條記錄資料模型都是嚴格相同的。
(四)欄位(Field)
上面已經提到了欄位,欄位就是Docuemnt對應的json內容的欄位。一個Docuemnt可以包括零個或多個欄位,欄位可以是一個簡單的值(如字串、整數、日期),也可以是一個數組或物件的巢狀結構。每個欄位都對應一個數據型別,如整數、字串、陣列、物件等。(五)對映(mapping)
mapping是類似於資料庫中的表結構定義,主要作用如下:
- 定義index下的欄位名
- 定義欄位型別,比如數值型、浮點型、布林型等
- 定義倒排索引相關的設定,比如是否索引、記錄position等。
- 設定分詞器等
與表結構不同的是,關係資料庫的表的結構必須事先通過create table語句來明確。而對映既可以顯示的通過命令來事先定義,也可以在儲存文件(插入資料)時由ES來自動識別。如我們上面的例子,並沒有顯示的去定義Index的mapping資訊。
可以通過 GET http://localhost:9200/_mapping 來檢視Index的mapping資訊。
(六)主鍵(ID)
ES中的每個Document都有一個唯一的ID(在type下唯一),也就是說 index/type/id必須是唯一的。
我們可以插入資料時顯示的指定ID,如前面的操作:
PUT http://localhost:9200/blogs/blog/1
也可以也ES系統自動生成,注意這時就不能用PUT操作,要用POST操作,如下面操作:
POST http://localhost:9200/blogs/blog { "title": "es info", "content": "about elasticsearch", "author": "jack", "year":"2018" }
上面請求中url的最後沒有指定要插入的Document的ID,操作成功後的響應資訊如下:
{ "_index": "blogs", "_type": "blog", "_id": "AWeXZiyTS_34KbUEtT3A", "_version": 1, "result": "created", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "created": true }
可以看出,響應資訊中帶回來了ES自動生成的ID值。
關於ELKB
先說下ELK,ELK是一個流行的日誌系統解決方案,注意,ELK不是一個軟體名,而是一個解決方案的縮寫,即Elasticsearch+Logstash+Kibana(ELK Stack)這三個軟體的集合。
這幾個都是開源的java產品,但是眾所周知,java的東西很吃記憶體和CPU,Logstash在作為收集日誌的Agent時,就顯得太過臃腫了。後來官方在logstash-forwarder的基礎上推出了beat系列,裡面包括四個系統,分別是:
1、Packetbeat(蒐集網路流量資料);
2、Topbeat(蒐集系統、程序和檔案系統級別的 CPU 和記憶體使用情況等資料);
3、Filebeat(蒐集檔案資料),Filebeat佔用資源少,適合於在各個伺服器上搜集日誌後傳輸給Logstash;
4、Winlogbeat(蒐集 Windows 事件日誌資料)。
所以Filebeat也就這樣加入了“日誌收集分析”的團隊裡,所以雖然大家還是習慣性的叫ELK,其實準確的說法已經是ELKB了。
ELKB中的幾個軟體的分工如下:
1、Elasticsearch:分散式搜尋和分析引擎,具有高可伸縮、高可靠和易管理等特點。基於 Apache Lucene 構建,能對大容量的資料進行接近實時的儲存、搜尋和分析操作。通常被用作某些應用的基礎搜尋引擎,使其具有複雜的搜尋功能。
2、Logstash:資料收集額外處理和資料引擎。它支援動態的從各種資料來源蒐集資料,並對資料進行過濾、分析、豐富、統一格式等操作,然後儲存到使用者指定的位置。
3、Kibana:資料分析和視覺化平臺。通常與 Elasticsearch 配合使用,對其中資料進行搜尋、分析和以統計圖表的方式展示。
4、Filebeat:ELK 協議棧的新成員,在需要採集日誌資料的伺服器上安裝 Filebeat,並指定日誌目錄或日誌檔案後,Filebeat 就能讀取資料,迅速傳送到 Logstash 進行解析,亦或直接傳送到 Elasticsearch 進行集中式儲存和分析。