Elasticsearch系列—生產集群的索引管理

概要

索引是我們使用Elasticsearch里最頻繁的部分日常的操作都與索引有關,本篇從運維人員的視角,來玩一玩Elasticsearch的索引操作。

基本操作

在運維童鞋的視角里,索引的日常操作除了CRUD,還是打開關閉、壓縮、alias重置,我們來了解一下。

創建索引

[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
}

默認情況下,索引創建命令會在每個primary shard的replica shard 開始進行複製后,或者是請求超時之後,返迴響應消息,如上。

acknowledged表示這個索引是否創建成功,shards_acknowledged表明了每個primary shard有沒有足夠數量的replica開始進行複製。

可能這兩個參數會為false,但是索引依然可以創建成功。因為這些參數僅僅是表明在請求超時之前,這兩個操作有沒有成功,也有可能請求超時了,在超時前都沒成功,但是實際上Elasticsearch Server端接收到了消息,並且都執行了,只是響應前還沒來得及執行,所以響應的是false。

刪除索引

curl -XDELETE 'http://elasticsearch02:9200/music?pretty'

查詢索引設置信息

curl -XGET 'http://elasticsearch02:9200/music?pretty'

打開/關閉索引

curl -XPOST 'http://elasticsearch02:9200/music/_close?pretty'
curl -XPOST 'http://elasticsearch02:9200/music/_open?pretty'

如果一個索引關閉了,那麼這個索引就沒有任何的性能開銷了,只要保留這個索引的元數據即可,然後對這個索引的讀寫操作都不會成功。一個關閉的索引可以接着再打開,打開以後會進行shard recovery過程。

如果集群數據定時有備份,在執行恢復的操作之前,必須將待恢復的索引關閉,否則恢復會報失敗。

壓縮索引

我們知道索引的primary shard數量在創建時一旦指定,後期就不能修改了,但是有一個這樣的情況:預估的shard數量在實際生產之後,發現估算得有點高,比如原來設置number_of_shards為8,結果生產上線后發現數據量沒那麼大,我想把這個索引的primary shard壓縮一下,該如何操作呢?

shrink命令的作用就是對索引進行壓縮的,不過有個限制:壓縮后的shard數量必須可以被原來的shard數量整除。如我們的8個primary shard的index可以只能被壓縮成4個,2個,或者1個primary shard的index。

shrink命令的工作流程:
  1. 創建一個跟source index的定義一樣的target index,但是唯一的變化就是primary shard變成了指定的數量。
  2. 將source index的segment file直接用hard-link的方式連接到target index的segment file,如果操作系統不支持hard-link,那麼就會將source index的segment file都拷貝到target index的data dir中,會很耗時。如果用hard-link會很快。
  3. target index進行shard recovery恢復。
案例演示
  1. 我們創建一個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" }
            }
        }
    }
}'
  1. 在索引內灌點數據進去
  2. 將索引的shard都移到一個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 
  }
}'

這個過程叫shard copy relocate,使用

`curl -XGET ‘http://elasticsearch02:9200/_cat/recovery?v’

可以查看該過程的進度。

  1. 執行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" 
  }
}'

執行完成后,可以看到music9的shard數據變化了,並且擁有music8所有的數據。

  1. 將別名指向新的music9索引,客戶端訪問無感知。

rollover索引

我們最常見的日誌索引,需要每天創建一個新的帶日期的索引,但客戶端又使用同一個alias進行寫入,此時可以用rollover命令將alias重置到這個新的索引上。

假設log_write別名已經存在,示例命令:

curl -XPOST 'http://elasticsearch02:9200/log_write/_rollover/log-20120122
-H 'Content-Type: application/json' -d '
{
  "conditions": {
    "max_age":   "1d"
  }
}'

用crontab定時每天執行一次,並且將日期部分用shell腳本進行參數化,這樣每天都創建一個帶日期的索引名字,而客戶端那邊一直使用log_write別名作寫入操作,對日誌系統非常實用。

索引mapping管理

索引的mapping管理是非常基礎的操作,我們可以在創建索引時定義mapping信息,也可以在索引創建成功后執行增加字段操作。

列舉以下幾個常用示例:

查看索引的mapping信息

curl -XGET 'http://elasticsearch02:9200/music/_mapping/children?pretty'

查看索引指定field的mapping信息

curl -XGET 'http://elasticsearch02:9200/music/_mapping/children/field/content?pretty'

創建索引時帶上mapping信息

# 節省篇幅,省略大部分字段
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
            }
          }
		}
      }
    }
  }
}'

為索引增加一個字段name,類型為text

curl -XPUT 'http://elasticsearch02:9200/music/_mapping/children?pretty' -H 'Content-Type: application/json' -d ' 
{
  "properties": {
    "name": {
      "type": "text"
    }
  }
}'

索引別名

客戶端訪問Elasticsearch的索引時,規範化操作都不會直接使用索引名稱,而是使用索引別名,索引別名能夠起到封裝Elasticsearch真實索引的作用,像上面的rollover操作,索引重建操作,別名起到了非常關鍵的作用。

我們來簡單看一下索引的基本操作:

# 創建索引別名
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" } }
    ]
}'
# 多個索引綁定一個別名
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最常見的修改項就是replicas的數量,其他的參數修改的場景不是特別多。

索引template

假設我們正在設計日誌系統的索引結構,日誌數據量較大,可能每天創建一個新的索引,索引名稱按日期標記,但別名是同一個,這種場景就比較適合使用index template。

我們舉個示例,先創建一個索引模板:

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-*”將使用該模板,我們創建一個索引:

curl -XPUT 'http://elasticsearch02:9200/access-log-01?pretty'

查看該索引:

curl -XGET 'http://elasticsearch02:9200/access-log-01?pretty'

可以看到如下結構:

[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"
      }
    }
  }
}

說明使用了模板的內容。

當然也有命令可以查看和刪除template:

curl -XGET 'http://elasticsearch02:9200/_template/template_access_log?pretty'

curl -XDELETE 'http://elasticsearch02:9200/_template/template_access_log?pretty'

索引常用查詢

索引操作統計查詢

發生在索引上的所有CRUD操作,Elasticsearch都是會做統計的,而且統計的內容非常翔實,我們可以使用這條命令:

curl -XGET 'http://elasticsearch02:9200/music/_stats?pretty'

內容非常詳細,有好幾百行,從doc的數據和佔用的磁盤字節數,到get、search、merge、translog等底層數據應有盡有。

segment信息查詢

索引下的segment信息,可以使用這條命令進行查詢:

curl -XGET 'http://elasticsearch02:9200/music/_segments?pretty'

內容也同樣挺多,我們摘抄出關鍵的部分做個示例:

"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"
    }
  }
}

這個片段表示名稱為_1的segment的信息。詳細如下:

  • _1:segment的名稱
  • generation:segment的自增長ID
  • num_docs:segment中沒有被刪除的document的數量
  • deleted_docs:segment中被刪除的document數量
  • size_in_bytes:segment佔用的磁盤空間
  • memory_in_bytes:segment會將一些數據緩存在內存中,這個數值就是segment佔用的內存的空間大小
  • committed:segment是否被sync到磁盤上去了
  • search:segment是否可被搜索,如果這個segment已經被sync到磁盤上,但是還沒有進行refresh,值為false
  • version:lucene的版本號
  • compound:true表示lucene已將這個segment所有的文件都merge成了一個文件
shard存儲信息

查看索引下shard的存儲情況,分佈在哪個node上,這條命令還是挺有用處的:

curl -XGET 'http://elasticsearch02:9200/music/_shard_stores?status=green&pretty'

摘抄了一個片段,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"
    }
  ]
},
補充幾個操作
  1. 清空索引緩存

curl -XPOST 'http://elasticsearch02:9200/music/_cache/clear?pretty'

  1. 強制flush

強行將os cache里的數據強制fsync到磁盤上去,同時還會清理掉translog中的日誌

curl -XPOST 'http://elasticsearch02:9200/music/_flush?pretty'

  1. refresh操作

顯式地刷新索引,讓在自動refresh前的所有操作變成可見

curl -XPOST 'http://elasticsearch02:9200/music/_flush?pretty'

  1. force merge

強制合併segment file,可以減小segment的數量
curl -XPOST 'http://elasticsearch02:9200/music/_forcemerge?pretty'

以上4個操作,一般是由Elasticsearch自動去執行,非特殊情況下不需要人工干預。

小結

本篇從運維角度簡單介紹了一下索引的一些日常操作與管理,能夠熟練應用的話,可以提升操縱索引的效率。

專註Java高併發、分佈式架構,更多技術乾貨分享與心得,請關注公眾號:Java架構社區
可以掃左邊二維碼添加好友,邀請你加入Java架構社區微信群共同探討技術

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

您可能也會喜歡…