概要
索引是我們使用Elasticsearch里最頻繁的部分日常的操作都與索引有關(guān),本篇從運(yùn)維人員的視角,來玩一玩Elasticsearch的索引操作。
基本操作
在運(yùn)維童鞋的視角里,索引的日常操作除了CRUD,還是打開關(guān)閉、壓縮、alias重置,我們來了解一下。
創(chuàng)建索引
[esuser@elasticsearch02 ~]$curl -XPUT 'http://elasticsearch02:9200/music?pretty' -H 'Content-Type: application/json' -d '
{
"settings" : {
"index" : {
"number_of_shards" : 3,
"number_of_replicas" : 2
}
},
"mappings" : {
"type1" : {
"properties" : {
"name" : { "type" : "text" }
}
}
}
}'
{
"acknowledged": true,
"shards_acknowledged": true
}
默認(rèn)情況下,索引創(chuàng)建命令會(huì)在每個(gè)primary shard的replica shard 開始進(jìn)行復(fù)制后,或者是請(qǐng)求超時(shí)之后,返回響應(yīng)消息,如上。
acknowledged表示這個(gè)索引是否創(chuàng)建成功,shards_acknowledged表明了每個(gè)primary shard有沒有足夠數(shù)量的replica開始進(jìn)行復(fù)制。
可能這兩個(gè)參數(shù)會(huì)為false,但是索引依然可以創(chuàng)建成功。因?yàn)檫@些參數(shù)僅僅是表明在請(qǐng)求超時(shí)之前,這兩個(gè)操作有沒有成功,也有可能請(qǐng)求超時(shí)了,在超時(shí)前都沒成功,但是實(shí)際上Elasticsearch Server端接收到了消息,并且都執(zhí)行了,只是響應(yīng)前還沒來得及執(zhí)行,所以響應(yīng)的是false。
刪除索引
curl -XDELETE 'http://elasticsearch02:9200/music?pretty'
查詢索引設(shè)置信息
curl -XGET 'http://elasticsearch02:9200/music?pretty'
打開/關(guān)閉索引
curl -XPOST 'http://elasticsearch02:9200/music/_close?pretty'
curl -XPOST 'http://elasticsearch02:9200/music/_open?pretty'
如果一個(gè)索引關(guān)閉了,那么這個(gè)索引就沒有任何的性能開銷了,只要保留這個(gè)索引的元數(shù)據(jù)即可,然后對(duì)這個(gè)索引的讀寫操作都不會(huì)成功。一個(gè)關(guān)閉的索引可以接著再打開,打開以后會(huì)進(jìn)行shard recovery過程。
如果集群數(shù)據(jù)定時(shí)有備份,在執(zhí)行恢復(fù)的操作之前,必須將待恢復(fù)的索引關(guān)閉,否則恢復(fù)會(huì)報(bào)失敗。
壓縮索引
我們知道索引的primary shard數(shù)量在創(chuàng)建時(shí)一旦指定,后期就不能修改了,但是有一個(gè)這樣的情況:預(yù)估的shard數(shù)量在實(shí)際生產(chǎn)之后,發(fā)現(xiàn)估算得有點(diǎn)高,比如原來設(shè)置number_of_shards為8,結(jié)果生產(chǎn)上線后發(fā)現(xiàn)數(shù)據(jù)量沒那么大,我想把這個(gè)索引的primary shard壓縮一下,該如何操作呢?
shrink命令的作用就是對(duì)索引進(jìn)行壓縮的,不過有個(gè)限制:壓縮后的shard數(shù)量必須可以被原來的shard數(shù)量整除。如我們的8個(gè)primary shard的index可以只能被壓縮成4個(gè),2個(gè),或者1個(gè)primary shard的index。
shrink命令的工作流程:
- 創(chuàng)建一個(gè)跟source index的定義一樣的target index,但是唯一的變化就是primary shard變成了指定的數(shù)量。
- 將source index的segment file直接用hard-link的方式連接到target index的segment file,如果操作系統(tǒng)不支持hard-link,那么就會(huì)將source index的segment file都拷貝到target index的data dir中,會(huì)很耗時(shí)。如果用hard-link會(huì)很快。
- target index進(jìn)行shard recovery恢復(fù)。
案例演示
- 我們創(chuàng)建一個(gè)number_of_shards為8的索引,名稱為music8
curl -XPUT 'http://elasticsearch02:9200/music8?pretty' -H 'Content-Type: application/json' -d '
{
"settings" : {
"index" : {
"number_of_shards" : 8,
"number_of_replicas" : 2
}
},
"mappings" : {
"children" : {
"properties" : {
"name" : { "type" : "text" }
}
}
}
}'
- 在索引內(nèi)灌點(diǎn)數(shù)據(jù)進(jìn)去
- 將索引的shard都移到一個(gè)node上去,如node1
curl -XPUT 'http://elasticsearch02:9200/music8/_settings?pretty' -H 'Content-Type: application/json' -d '
{
"settings": {
"index.routing.allocation.require._name": "node-1",
"index.blocks.write": true
}
}'
這個(gè)過程叫shard copy relocate,使用
`curl -XGET 'http://elasticsearch02:9200/_cat/recovery?v'
可以查看該過程的進(jìn)度。
- 執(zhí)行shrink命令,新的索引名稱為music9
curl -XPOST 'http://elasticsearch02:9200/music8/_shrink/music9?pretty' -H 'Content-Type: application/json' -d '
{
"settings": {
"index.number_of_shards": 2,
"index.number_of_replicas": 1,
"index.codec": "best_compression"
}
}'
執(zhí)行完成后,可以看到music9的shard數(shù)據(jù)變化了,并且擁有music8所有的數(shù)據(jù)。
- 將別名指向新的music9索引,客戶端訪問無感知。
rollover索引
我們最常見的日志索引,需要每天創(chuàng)建一個(gè)新的帶日期的索引,但客戶端又使用同一個(gè)alias進(jìn)行寫入,此時(shí)可以用rollover命令將alias重置到這個(gè)新的索引上。
假設(shè)log_write別名已經(jīng)存在,示例命令:
curl -XPOST 'http://elasticsearch02:9200/log_write/_rollover/log-20120122
-H 'Content-Type: application/json' -d '
{
"conditions": {
"max_age": "1d"
}
}'
用crontab定時(shí)每天執(zhí)行一次,并且將日期部分用shell腳本進(jìn)行參數(shù)化,這樣每天都創(chuàng)建一個(gè)帶日期的索引名字,而客戶端那邊一直使用log_write別名作寫入操作,對(duì)日志系統(tǒng)非常實(shí)用。
索引mapping管理
索引的mapping管理是非?;A(chǔ)的操作,我們可以在創(chuàng)建索引時(shí)定義mapping信息,也可以在索引創(chuàng)建成功后執(zhí)行增加字段操作。
列舉以下幾個(gè)常用示例:
查看索引的mapping信息
curl -XGET 'http://elasticsearch02:9200/music/_mapping/children?pretty'
查看索引指定field的mapping信息
curl -XGET 'http://elasticsearch02:9200/music/_mapping/children/field/content?pretty'
創(chuàng)建索引時(shí)帶上mapping信息
# 節(jié)省篇幅,省略大部分字段
curl -XPUT 'http://elasticsearch02:9200/music?pretty' -H 'Content-Type: application/json' -d '
{
"mappings": {
"children": {
"properties": {
"content": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
}'
為索引增加一個(gè)字段name,類型為text
curl -XPUT 'http://elasticsearch02:9200/music/_mapping/children?pretty' -H 'Content-Type: application/json' -d '
{
"properties": {
"name": {
"type": "text"
}
}
}'
索引別名
客戶端訪問Elasticsearch的索引時(shí),規(guī)范化操作都不會(huì)直接使用索引名稱,而是使用索引別名,索引別名能夠起到封裝Elasticsearch真實(shí)索引的作用,像上面的rollover操作,索引重建操作,別名起到了非常關(guān)鍵的作用。
我們來簡(jiǎn)單看一下索引的基本操作:
# 創(chuàng)建索引別名
curl -XPOST 'http://elasticsearch02:9200/_aliases?pretty' -H 'Content-Type: application/json' -d '
{
"actions" : [
{ "add" : { "index" : "music", "alias" : "music_prd" } }
]
}'
# 刪除索引別名
curl -XPOST 'http://elasticsearch02:9200/_aliases?pretty' -H 'Content-Type: application/json' -d '
{
"actions" : [
{ "remove" : { "index" : "music", "alias" : "music_prd" } }
]
}'
# 重命名別名:先刪掉后添加
curl -XPOST 'http://elasticsearch02:9200/_aliases?pretty' -H 'Content-Type: application/json' -d '
{
"actions" : [
{ "remove" : { "index" : "music", "alias" : "music_prd" } },
{ "add" : { "index" : "music2", "alias" : "music_prd" } }
]
}'
# 多個(gè)索引綁定一個(gè)別名
curl -XPOST 'http://elasticsearch02:9200/_aliases?pretty' -H 'Content-Type: application/json' -d '
{
"actions" : [
{ "add" : { "indices" : ["music1", "music2"], "alias" : "music_prd" } }
]
}'
索引setting修改
查看索引setting信息:
curl -XGET 'http://elasticsearch02:9200/music/_settings?pretty'
修改setting信息:
curl -XPUT 'http://elasticsearch02:9200/music/_settings?pretty' -H 'Content-Type: application/json' -d '
{
"index" : {
"number_of_replicas" : 1
}
}'
setting最常見的修改項(xiàng)就是replicas的數(shù)量,其他的參數(shù)修改的場(chǎng)景不是特別多。
索引template
假設(shè)我們正在設(shè)計(jì)日志系統(tǒng)的索引結(jié)構(gòu),日志數(shù)據(jù)量較大,可能每天創(chuàng)建一個(gè)新的索引,索引名稱按日期標(biāo)記,但別名是同一個(gè),這種場(chǎng)景就比較適合使用index template。
我們舉個(gè)示例,先創(chuàng)建一個(gè)索引模板:
curl -XPUT 'http://elasticsearch02:9200/_template/template_access_log?pretty' -H 'Content-Type: application/json' -d '
{
"template": "access-log-*",
"settings": {
"number_of_shards": 2
},
"mappings": {
"log": {
"_source": {
"enabled": false
},
"properties": {
"host_name": {
"type": "keyword"
},
"thread_name": {
"type": "keyword"
},
"created_at": {
"type": "date",
"format": "YYYY-MM-dd HH:mm:ss"
}
}
}
},
"aliases" : {
"access-log" : {}
}
}'
索引名稱符合"access-log-*"將使用該模板,我們創(chuàng)建一個(gè)索引:
curl -XPUT 'http://elasticsearch02:9200/access-log-01?pretty'
查看該索引:
curl -XGET 'http://elasticsearch02:9200/access-log-01?pretty'
可以看到如下結(jié)構(gòu):
[esuser@elasticsearch02 bin]$ curl -XGET 'http://elasticsearch02:9200/access-log-01?pretty'
{
"access-log-01" : {
"aliases" : {
"access-log" : { }
},
"mappings" : {
"log" : {
"_source" : {
"enabled" : false
},
"properties" : {
"created_at" : {
"type" : "date",
"format" : "YYYY-MM-dd HH:mm:ss"
},
"host_name" : {
"type" : "keyword"
},
"thread_name" : {
"type" : "keyword"
}
}
}
},
"settings" : {
"index" : {
"creation_date" : "1581373546223",
"number_of_shards" : "2",
"number_of_replicas" : "1",
"uuid" : "N8AHh3wITg-Zh4T6umCS2Q",
"version" : {
"created" : "6030199"
},
"provided_name" : "access-log-01"
}
}
}
}
說明使用了模板的內(nèi)容。
當(dāng)然也有命令可以查看和刪除template:
curl -XGET 'http://elasticsearch02:9200/_template/template_access_log?pretty'
curl -XDELETE 'http://elasticsearch02:9200/_template/template_access_log?pretty'
索引常用查詢
索引操作統(tǒng)計(jì)查詢
發(fā)生在索引上的所有CRUD操作,Elasticsearch都是會(huì)做統(tǒng)計(jì)的,而且統(tǒng)計(jì)的內(nèi)容非常翔實(shí),我們可以使用這條命令:
curl -XGET 'http://elasticsearch02:9200/music/_stats?pretty'
內(nèi)容非常詳細(xì),有好幾百行,從doc的數(shù)據(jù)和占用的磁盤字節(jié)數(shù),到get、search、merge、translog等底層數(shù)據(jù)應(yīng)有盡有。
segment信息查詢
索引下的segment信息,可以使用這條命令進(jìn)行查詢:
curl -XGET 'http://elasticsearch02:9200/music/_segments?pretty'
內(nèi)容也同樣挺多,我們摘抄出關(guān)鍵的部分做個(gè)示例:
"segments" : {
"_1" : {
"generation" : 1,
"num_docs" : 1,
"deleted_docs" : 0,
"size_in_bytes" : 7013,
"memory_in_bytes" : 3823,
"committed" : true,
"search" : true,
"version" : "7.3.1",
"compound" : true,
"attributes" : {
"Lucene50StoredFieldsFormat.mode" : "BEST_SPEED"
}
}
}
這個(gè)片段表示名稱為_1的segment的信息。詳細(xì)如下:
- _1:segment的名稱
- generation:segment的自增長(zhǎng)ID
- num_docs:segment中沒有被刪除的document的數(shù)量
- deleted_docs:segment中被刪除的document數(shù)量
- size_in_bytes:segment占用的磁盤空間
- memory_in_bytes:segment會(huì)將一些數(shù)據(jù)緩存在內(nèi)存中,這個(gè)數(shù)值就是segment占用的內(nèi)存的空間大小
- committed:segment是否被sync到磁盤上去了
- search:segment是否可被搜索,如果這個(gè)segment已經(jīng)被sync到磁盤上,但是還沒有進(jìn)行refresh,值為false
- version:lucene的版本號(hào)
- compound:true表示lucene已將這個(gè)segment所有的文件都merge成了一個(gè)文件
shard存儲(chǔ)信息
查看索引下shard的存儲(chǔ)情況,分布在哪個(gè)node上,這條命令還是挺有用處的:
curl -XGET 'http://elasticsearch02:9200/music/_shard_stores?status=green&pretty'
摘抄了一個(gè)片段,3表示shard的id:
"3" : {
"stores" : [
{
"A1s1uus7TpuDSiT4xFLOoQ" : {
"name" : "node-2",
"ephemeral_id" : "Q3uoxLeJRnWQrw3E2nOq-Q",
"transport_address" : "192.168.17.137:9300",
"attributes" : {
"ml.machine_memory" : "3954196480",
"rack" : "r1",
"xpack.installed" : "true",
"ml.max_open_jobs" : "20",
"ml.enabled" : "true"
}
},
"allocation_id" : "o-t-AwGZRrWTflYLP030jA",
"allocation" : "primary"
},
{
"RGw1IXzZR4CeZh9FUrGHDw" : {
"name" : "node-1",
"ephemeral_id" : "B1pv6c4TRuu1vQNvL40iPg",
"transport_address" : "192.168.17.138:9300",
"attributes" : {
"ml.machine_memory" : "3954184192",
"rack" : "r1",
"ml.max_open_jobs" : "20",
"xpack.installed" : "true",
"ml.enabled" : "true"
}
},
"allocation_id" : "SaXqL8igRUmLAoBBQyQNqw",
"allocation" : "replica"
}
]
},
補(bǔ)充幾個(gè)操作
- 清空索引緩存
curl -XPOST 'http://elasticsearch02:9200/music/_cache/clear?pretty'
- 強(qiáng)制flush
強(qiáng)行將os cache里的數(shù)據(jù)強(qiáng)制fsync到磁盤上去,同時(shí)還會(huì)清理掉translog中的日志
curl -XPOST 'http://elasticsearch02:9200/music/_flush?pretty'
- refresh操作
顯式地刷新索引,讓在自動(dòng)refresh前的所有操作變成可見
curl -XPOST 'http://elasticsearch02:9200/music/_flush?pretty'
- force merge
強(qiáng)制合并segment file,可以減小segment的數(shù)量
curl -XPOST 'http://elasticsearch02:9200/music/_forcemerge?pretty'
以上4個(gè)操作,一般是由Elasticsearch自動(dòng)去執(zhí)行,非特殊情況下不需要人工干預(yù)。
小結(jié)
本篇從運(yùn)維角度簡(jiǎn)單介紹了一下索引的一些日常操作與管理,能夠熟練應(yīng)用的話,可以提升操縱索引的效率。
專注Java高并發(fā)、分布式架構(gòu),更多技術(shù)干貨分享與心得,請(qǐng)關(guān)注公眾號(hào):Java架構(gòu)社區(qū)