首先是推薦一下參考資料
- 中文資料:http://kibana.logstash.es/content/elasticsearch/index.html
- 官方文檔:https://www.elastic.co/guide/index.html
- 中文資料:http://es.xiaoleilu.com/
2016年3月3日:更新非文件方式模板配置和模板order覆蓋問題
后面如果再寫ElasticSearch(后面簡稱 ES)文章,重新整理一下參考文檔匯總一下。
為什么采用索引模板文件
ES的http接口非常好用,索引配置其實是可以通過接口完成的。但是
你肯定不希望每次重新部署ES都重新到自己的筆記上復制粘貼配置文件,采用索引模板文件來配置ES索引,模板就和其他服務器比如:Nginx apache的conf文件,可以方便通過類似rsync等工具分發,當然將索引配置保存於數據庫中也是可以的,但這里主要是說明文件的方式,比較符合運維習慣。
在什么地方放置模板配置文件?
config路徑下面的templates目錄,正常可能長成這樣:/usr/local/elasticsearch-1.7.1/config/templates/
配置內容說明
{
"order": 10,
"myaccess": { //模板名稱,用於更新和識別這個模板
"mappings": { //mappings下面是模板的具體配置了
"system": { //這里坑比較多,system只不過是一個命名空間而已,你也可以取別的名字,比如官方喜歡用tweet
"properties": {//這里面就可以放具體每個索引的配置了
"@timestamp": {//這是專門給kibana用的一個字段,時間索引
"doc_values": true,//未知
"format": "dateOptionalTime",//數據格式,也可以是Y-m-d H:i:s等等,具體可以看中文文檔
"index": "not_analyzed",//常見的分析模式,analyzed 和 not_analyzed 一般來說,not_analyzed會導致無法進行分詞查詢,默認不寫這個屬性的話,就是analyzed(可分詞和模糊查詢)
"type": "date"//日期類型,其他常見類型包括float integer string等,具體見文檔說明
},
"status": {
"index": "analyzed",
"type": "short"
},
"ua": {
"type": "string"
},
"uri": {//uri 嵌套了2級
"fields": {//第二級索引的訪問方式很簡單,就是uri.raw(raw是自己取的名字),這樣你可以方便的對同一個字段做多種分析索引,以應對不同的查詢方式
"raw": {
"index": "not_analyzed",
"type": "string"
}
},
"index": "analyzed",
"type": "string"
}
}
}
},
"settings": {
"index.number_of_replicas": 0, //副本的個數,也就是同一份數據有額外多少個拷貝,默認1,如果你本地起一個節點測試,最好改為0,因為這邊如果不是0,集群會一直提示說少一個節點來放副本,這個值可以動態修改
"index.number_of_shards": 5//索引分片數量,具體作用尚未閱讀文檔,下面有一些通過文檔介紹的理解
},
"template": "myaccess*"//什么樣的索引可以采用當前的模板,這是一個通配符(wildcard 這單詞會經常出現在ES中),如果我們按月分索引比如 myaccess-2015.08這種索引,就會使用這個模板。
}
}
比較常見的問題是,我新建模板要不要重啟 ES?或者做一個什么reload config的操作?
當模板新建完成是不需要重啟ES的,有新索引被創建,這個模板文件會被應用到這新索引當中,一旦索引建立完畢,模板和索引就沒有什么太大關系了。修改模板只會導致下一個被創建的索引的改動。如果要讓索引使用新的模板,需要通過API來配置。
參數index.num_of_shards
當執行一個查詢時,查詢用的節點服務器需要查詢的數據總量是:
number_of_shards * (from + size)
就是說,如果分片為5,要查 第10頁,每頁30條數據,需要查詢的數據就是:
5 * (270 + 30) = 1500 條
每個分片都需要查300條數據,並取最后的30條,這和MySQ limit的原理是一樣的,更多的分片導致更多的CPU消耗是必然。
至於分片作用:下面節選一段
Indexes in elasticsearch are not 1:1 mappings to Lucene indexes, they are in fact sharded across a configurable number of Lucene indexes, 5 by default, with 1 replica per shard. A single machine may have a greater or lesser number of shards for a given index than other machines in the cluster. Elasticsearch tries to keep the total data across all indexes about equal on all machines, even if that means that certain indexes may be disproportionately represented on a given machine. Each shard has a configurable number of full replicas, which are always stored on unique instances. If the cluster is not big enough to support the specified number of replicas the cluster’s health will be reported as a degraded ‘yellow’ state. The basic dev setup for elasticsearch, consequently, always thinks that it’s operating in a degraded state given that by default indexes, a single running instance has no peers to replicate its data to. Note that this has no practical effect on its operation for development purposes. It is, however, recommended that elasticsearch always run on multiple servers in production environments. As a clustered database, many of data guarantees hinge on multiple nodes being available.
大體可以認為分片可以將同一個請求的負載分到集群的不同節點上。
關於大分頁
從上面的shard的原理來看,大的分頁查詢對於集群來說,開銷非常巨大。
正常對於一個搜索的應用來說,當用戶無法在前三頁搜索到需要的內容時,應該引導用戶增加搜索條件以便縮小搜索范圍,而不是不斷往后翻,這樣不僅服務器壓力大,體驗也不好。
還有什么方式來管理模板?(2016年3月3日更新)
還可以通過ES提供的接口來管理模板。這種管理方式最近用的比較多,相比之前我認為文件的管理方式來說,會更直觀一些。
curl -XPUT http://127.0.0.1:9200/_template/user -d '
{
...模板配置
}'
通過上面的方式,直接更新ES集群中名稱為user的模板
-如何管理?
現在用的方式是將模板保存為一個個.json文件,並且放在git庫中。另外用python寫一個腳本來代替curl繁瑣的指令操作,腳本功能如下,這樣管理起來就方便了。
Usage: utp.py [options] <template file name>
Examples:
utp.py -f 0-base.json
Options:
-h, --help show this help message and exit
-a, --all 遍歷所有目錄的模板發送到服務器
-d, --delete 刪除指定文件的模板,如果和--all一起使用,刪除全部以目錄中模板名相同的模板
-f FILE, --file=FILE 指定模板文件,模板文件也可以直接跟在最后
-n NODE, --node=NODE Elasticsearch 節點ip [default:127.0.0.1]
-p PORT, --port=PORT Elasticsearch 節點端口 [default:9200]
關於模板相互覆蓋的問題
如果你正好在做一個ELK 日志管理的項目,應該會遇到這個問題,就是很多日志的格式其實是相同的,我們並不希望反復去寫模板。處理這個問題有很多手段,而且這些手段往往需要一起使用。
- 模板覆蓋
- 默認模板
- 動態字段
-模板覆蓋
在上面的模板配置中,有一個order字段。之前我沒太在意,因為項目要的模板是很特殊的,沒法通用。
比如我有一個日志系統,里面要放nginx日志,而公司項目很多,並不希望公用一個索引。當我們建立模板的時候,可以建立這樣幾個。
- nginx 只有mappings的配置,字段名和類型,匹配所有 *-nginx-* 的模板,order=0。
- base 只有settings的配置,主要是配置分片規則、備份規則等等,匹配所有 * 的模板 order=0
- 項目名模板(比如user) 基本可以是空的,匹配所有user-*的模板 order = 1(或者更高)
現在建立一個索引叫做 user-nginx-2016.03.03,系統會發現符合 * 的匹配規則,調用base模板,進行配置,然后會發現也符合-nginx-規則,調用nginx模板進行配置,最后發現符合項目名模板的配置user-*,再調用項目模板。order越大,優先權也越大,同樣一個配置,系統會采用order更大的模板。
這樣,當有另個項目的nginx日志過來,就不用在建立新的模板了,除非這個項目有特殊需求。
-默認模板
其實就是_default_。比如你的一個索引下面有多個type,格式相同,可以建立一個名為_default_的type。當新建任意type的時候,都會先讀取這個配置。可以看下面一個代碼例子。
-動態字段
有時候服務器可能傳一些我們沒有配置好的字段過來,比如日志系統我們希望doc_values最好能是true的時候,就是true。沒有分詞需求的字符串字段,不要analyze。這些都可以通過動態字段來完成。比如下面一個如果遇到整數要怎么處理。
"mappings": {
"_default_": {
"dynamic_templates": [
{
"integer field": {
"mapping": {
"doc_values": true,
"type": "integer"
},
"match": "*",
"match_mapping_type": "integer"
}
},