Elasticsearch生產環境索引管理深刻剖析-搜索系統線上實戰

本套技術專欄做者(秦凱新)專一於大數據及容器雲核心技術解密,具有5年工業級IOT大數據雲平臺建設經驗,可提供全棧的大數據+雲原平生臺諮詢方案,請持續關注本套博客。QQ郵箱地址:1120746959@qq.com,若有任何學術交流,可隨時聯繫。node

1. 索引管理

1.1 建立索引

  • 用settings給這個索引在建立時能夠添加一些設置,還有能夠初始化一些type的mapping算法

    curl -XPUT 'http://elasticsearch02:9200/twitter?pretty' -d '
      {
          "settings" : {
              "index" : {
                  "number_of_shards" : 3, 
                  "number_of_replicas" : 2 
              }
          },
          "mappings" : {
              "type1" : {
                  "properties" : {
                      "field1" : { "type" : "text" }
                  }
              }
          }
      }'
    複製代碼

1.2 索引建立返回消息的解釋

  • 默認狀況下,索引建立命令會在每一個primary shard的副本開始進行復制之後,或者是請求超時之後,返回一個響應消息,相似下面這樣的。shell

  • 其中acknowledged代表了這個索引有沒有建立成功,shards_acknowledged代表了每一個primary shard有沒有足夠數量的replica開始進行復制了。有可能這兩個參數會爲false,可是索引依然能夠建立成功。由於這些參數僅僅是代表在請求超時以前,那兩個行爲有沒有成功,也有可能請求超時了,在超時前都沒成功,可是超時後在es server端仍是都執行了。json

  • 若是acknoledged是false,那麼就多是超時了,此時接受到響應消息的時候,cluster state都還沒變動,沒有加入新建立的index,可是也許以後仍是會建立這個index。若是shards_acknowledged是false,那麼可能在primary shard進行副本copy以前,就timeout了,可是此時也許index建立成功了,並且cluster state已經加入了新建立的index。api

    {
          "acknowledged": true,
          "shards_acknowledged": true
      }
    複製代碼

1.3 刪除索引

刪除索引中的一個type
curl -XDELETE 'http://elasticsearch02:9200/twitter?pretty'
複製代碼

1.4 查詢索引設置信息

curl -XGET 'http://elasticsearch02:9200/twitter?pretty'
複製代碼

1.5 打開/關閉索引

  • 若是關閉了一個索引以後,那麼這個索引是不會帶來任何的性能開銷了,只要保留這個索引的元數據便可,而後對這個索引的讀寫操做都不會成功。一個關閉的索引能夠接着再打開,打開之後會進行shard recovery過程。緩存

  • 好比說你在作一些運維操做的時候,如今你要對某一個索引作一些配置,運維操做,修改一些設置,關閉索引,不容許寫入,成功之後再打開索引數據結構

    curl -XPOST 'http://elasticsearch02:9200/twitter/_close?pretty'
      curl -XPOST 'http://elasticsearch02:9200/twitter/_open?pretty'
      
      curl -XPUT 'http://elasticsearch02:9200/twitter/type1/1?pretty' -d '
      {
      	"field1": "1"
      }'
    複製代碼

1.6 壓縮索引

  • shrink命令能夠將一個已有的索引壓縮成一個新的索引,同時primary shard會更少。app

  • primary shard由於涉及到document的hash路由問題,因此是不容許修改的。可是若是要減小index的primary shard,能夠用shrink命令來壓縮index。可是壓縮後的shard數量必須能夠被原來的shard數量整除。舉例來講,一個有8個primary shard的index能夠被壓縮成4個,2個,或者1個primary shard的index。運維

  • 壓縮索引,好比是要保留7天的數據,那麼給了10個shard,可是如今需求變了,這個索引只要保留3天的數據就能夠了,那麼數據量變小了,就不須要10個shard了,就能夠作shrink操做,5個shard。curl

  • 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恢復
    複製代碼
  • 若是要shrink index,那麼這個index必須先被標記爲read only,並且這個index的每一個shard的某一個copy,能夠是primary或者是replica,都必須被複制到一個節點上去。

  • 默認狀況下,index的每一個shard有可能在不一樣機器上的,好比說,index有5個shard,shard0和shard1在機器1上,shard二、shard3在機器2上,shard4在機器3上。如今還得把shard0,shard1,shard2,shard3,shard4所有拷貝到一個同一個機器上去,可是能夠是shard0的replica shard。並且每一個primary shard都必須存在。能夠經過下面的命令來完成。其中index.routing.allocation.require._name必須是某個node的名稱,這個都是能夠本身設置的。

    curl -XPUT 'http://elasticsearch02:9200/twitter/_settings?pretty' -d '
      {
        "settings": {
          "index.routing.allocation.require._name": "node-elasticsearch-02", 
          "index.blocks.write": true 
        }
      }'
    複製代碼
  • 這個命令會花費一點時間將source index每一個shard的一個copy都複製到指定的node上去,能夠經過GET _cat/recovery?v命令來追蹤這個過程的進度。

  • 等上面的shard copy relocate過程結束以後,就能夠shrink一個index,用下面的命令便可:

    POST my_source_index/_shrink/my_target_inde
    複製代碼
  • 若是target index被添加進了cluster state以後,這個命令就會當即返回,不是等待shrink過程完成以後才返回的。固然還能夠用下面的命令來shrink的時候修改target index的設置,在settings裏就能夠設置target index的primary shard的數量。

    curl -XPOST 'http://elasticsearch02:9200/twitter/_shrink/twitter_shrinked?pretty' -d '
      {
        "settings": {
          "index.number_of_replicas": 1,
          "index.number_of_shards": 1, 
          "index.codec": "best_compression" 
        }
      }'
    複製代碼
  • 是須要監控整個shrink的過程的,用GET _cat/recovery?v便可。

1.7 rollover index建立新索引

  • rollover命令能夠將一個alias重置到一個新的索引上去,若是已經存在的index被認爲太大或者數據太舊了。這個命令能夠接收一個alias名稱,還有一系列的condition。

  • 若是索引知足了condition,那麼就會建立一個新的index,同時alias會指向那個新的index。好比下面的命令。舉例來講,有一個logs-0000001索引,給了一個別名是logs_write,接着發起了一個rollover的命令,若是logs_write別名以前指向的那個index,也就是logs-0000001,建立了超過7天,或者裏面的document已經超過了1000個了,而後就會建立一個logs-000002的索引,同時logs_write別名會指向新的索引。

  • 這個命令實際上是頗有用的,特別是針對這種用戶訪問行爲日誌的數據,或者是一些聯機事務系統的數據的進入,你能夠寫一個shell腳本,天天0:00的時候就執行如下rollover命令,此時就判斷,若是說以前的索引已經存在了超過1天了,那麼此時就建立一個新的索引出來,同時將別名指向新的索引。自動去滾動建立新的索引,保持每一個索引就只有一個小時,一天,七天,三天,一週,一個月。

  • 相似用es來作日誌平臺,就可能分佈式電商平臺,可能訂單系統的日誌,單獨的一個索引,要求的是保留最近3天的日誌就能夠了。交易系統的日誌,是單獨的一個索引,要求的是保留最近30天的日誌。

    curl -XPUT 'http://elasticsearch02:9200/logs-000001?pretty' -d ' 
      {
        "aliases": {
          "logs_write": {}
        }
      }'
      
      # Add > 1000 documents to logs-000001
      
      curl -XPUT 'http://elasticsearch02:9200/logs-000001/data/1?pretty' -d '
      {
      	"userid": 1,
      	"page": 1
      }'
      
      curl -XPUT 'http://elasticsearch02:9200/logs-000001/data/2?pretty' -d '
      {
      	"userid": 2,
      	"page": 2
      }'
      
      curl -XPUT 'http://elasticsearch02:9200/logs-000001/data/3?pretty' -d '
      {
      	"userid": 3,
      	"page": 3
      }'
      
      curl -XPOST 'http://elasticsearch02:9200/logs_write/_rollover?pretty' -d ' 
      {
        "conditions": {
          "max_age":   "1d",
          "max_docs":  3
        }
      }'
      
      {
        "acknowledged": true,
        "shards_acknowledged": true,
        "old_index": "logs-000001",
        "new_index": "logs-000002",
        "rolled_over": true, 
        "dry_run": false, 
        "conditions": { 
          "[max_age: 7d]": false,
          "[max_docs: 1000]": true
        }
      }
    複製代碼
  • 這個過程常見於網站用戶行爲日誌數據,好比按天來自動切分索引,寫個腳本定時去執行rollover,就會自動不斷建立新的索引,可是別名永遠是一個,對於外部的使用者來講,用的都是最新數據的索引。

  • 舉一個簡單的例子,這塊是怎麼玩兒的,好比說用es作網站的實時用戶行爲分析,要求的是一個索引只要保留當日的數據就能夠了,那麼就能夠用這個rollover的策略,確保每一個索引都是包含當日的最新數據的。老的數據,就變成別的索引了,此時能夠寫一個shell腳本,刪除舊的數據,這樣的話,es裏就保留當前最新的數據就能夠了。也能夠根據你的需求,就保留最近7天的數據,可是最新一天的數據在一個索引中,供分析查詢使用。

  • 默認狀況下,若是已經存在的那個索引是用-符號加上一個數字結尾的,好比說logs-000001,那麼新索引的名稱就會是自動給那個數字加1,好比logs-000002,自動就是給一個6位的數字,並且會自動補零。可是咱們也能夠本身指定要的新的索引名稱,好比下面這樣:

    POST /my_alias/_rollover/my_new_index_name
      {
        "conditions": {
          "max_age":   "7d",
          "max_docs":  1000
        }
      }
    複製代碼
  • 能夠將rollover命令和date日期結合起來使用,好比下面的例子,先建立了一個logs-2016.10.31-1格式的索引。接着每次若是成功rollover了,那麼若是是在當天rollover了屢次,那就是當天的日期,末尾的數字遞增。若是是隔天才rollover,會自動變動日期,同時維護末尾的數字序號。

    PUT /%3Clogs-%7Bnow%2Fd%7D-1%3E 
      {
        "aliases": {
          "logs_write": {}
        }
      }
      
      PUT logs_write/log/1
      {
        "message": "a dummy log"
      }
      
      POST logs_write/_refresh
      
      # Wait for a day to pass
      
      POST /logs_write/_rollover 
      {
        "conditions": {
          "max_docs":   "1"
        }
      }
    複製代碼
  • 固然,還能夠在rollover的時候,給新的index進行新的設置:

    POST /logs_write/_rollover
      {
        "conditions" : {
          "max_age": "7d",
          "max_docs": 1000
        },
        "settings": {
          "index.number_of_shards": 2
        }
      }
    複製代碼

1.8 mapping管理

  • put mapping命令可讓咱們給一個已有的索引添加一個新的type,或者修改一個type,好比給某個type加一些字段。

  • 下面這個命令是在建立索引的時候,直接跟着建立一個type:

    curl -XPUT 'http://elasticsearch02:9200/twitter?pretty' -d ' 
      {
        "mappings": {
          "tweet": {
            "properties": {
              "message": {
                "type": "text"
              }
            }
          }
        }
      }'
    複製代碼
  • 下面這個命令是給一個已有的索引添加一個type:

    curl -XPUT 'http://elasticsearch02:9200/twitter/_mapping/user?pretty' -d ' 
      {
        "properties": {
          "name": {
            "type": "text"
          }
        }
      }'
    複製代碼
  • 下面這個命令是給一個已有的type添加一個field:

    curl -XPUT 'http://elasticsearch02:9200/twitter/_mapping/tweet?pretty' -d '
      {
        "properties": {
          "user_name": {
            "type": "text"
          }
        }
      }'
    
      curl -XGET 'http://elasticsearch02:9200/twitter/_mapping/tweet?pretty',上面這行命令能夠查看某個type的
      mapping映射信息
      
      curl -XGET 'http://elasticsearch02:9200/twitter/_mapping/tweet/field/message?pretty',這行命令能夠看某個
      type的某個field的映射信息
    複製代碼

1.9 索引別名管理

curl -XPOST 'http://elasticsearch02:9200/_aliases?pretty' -d '
    {
        "actions" : [
            { "add" : { "index" : "twitter", "alias" : "twitter_prod" } }
        ]
    }'
    
    curl -XPOST 'http://elasticsearch02:9200/_aliases?pretty' -d '
    {
        "actions" : [
            { "remove" : { "index" : "twitter", "alias" : "twitter_prod" } }
        ]
    }'
    
    POST /_aliases
    {
        "actions" : [
            { "remove" : { "index" : "test1", "alias" : "alias1" } },
            { "add" : { "index" : "test2", "alias" : "alias1" } }
        ]
    }
    
    POST /_aliases
    {
        "actions" : [
            { "add" : { "indices" : ["test1", "test2"], "alias" : "alias1" } }
        ]
    }
複製代碼
  • 索引別名,仍是挺有用的,主要是什麼呢,就是說,能夠將一個索引別名底層掛載多個索引,好比說7天的數據

  • 索引別名經常和以前講解的那個rollover結合起來,咱們爲了性能和管理方便,天天的數據都rollover出來一個索引,可是在對數據分析的時候,多是這樣子的,有一個索引access-log,指向了當日最新的數據,用來計算實時數據的; 有一個索引access-log-7days,指向了7天的7個索引,可讓咱們進行一些週數據的統計和分析。

1.10 index settings管理

  • 常常可能要對index作一些settings的調整,經常和以前的index open和close結合起來

    curl -XPUT 'http://elasticsearch02:9200/twitter/_settings?pretty' -d '
      {
          "index" : {
              "number_of_replicas" : 1
          }
      }'
      
      curl -XGET 'http://elasticsearch02:9200/twitter/_settings?pretty'
    複製代碼

1.11 index template管理

  • 能夠定義一些index template,這樣template會自動應用到新建立的索引上去。template中能夠包含settings和mappings,還能夠包含一個pattern,決定了template會被應用到哪些index上。並且template僅僅在index建立的時候會被應用,修改template,是不會對已有的index產生影響的。

    curl -XPUT 'http://elasticsearch02:9200/_template/template_access_log?pretty' -d '
      {
        "template": "access-log-*",
        "settings": {
          "number_of_shards": 2
        },
        "mappings": {
          "log": {
            "_source": {
              "enabled": false
            },
            "properties": {
              "host_name": {
                "type": "keyword"
              },
              "created_at": {
                "type": "date",
                "format": "EEE MMM dd HH:mm:ss Z YYYY"
              }
            }
          }
        },
        "aliases" : {
            "access-log" : {}
        }
      }'
      
      curl -XDELETE 'http://elasticsearch02:9200/_template/template_access_log?pretty'
      curl -XGET 'http://elasticsearch02:9200/_template/template_access_log?pretty'
      curl -XPUT 'http://elasticsearch02:9200/access-log-01?pretty'
      curl -XGET 'http://elasticsearch02:9200/access-log-01?pretty'
    複製代碼
  • index template,多是這樣子的,就是你可能會常常建立不一樣的索引,好比說商品,分紅了多種,每一個商品種類的數據 都很大,可能就是說,一個商品種類一個索引,可是每一個商品索引的設置是差很少的,因此乾脆能夠搞一個商品索引模板 ,而後每次新建一個商品種類索引,直接綁定到模板,引用相關的設置

2 索引統計

  • indice stat對index上發生的不一樣類型的操做都提供了統計。這個api提供了index level的統計信息,不過大多數統計信息也能夠從node level獲取。這裏包括了doc數量,index size,segment的內存使用量,merge,flush,refresh,translog等底層機制的統計信息。

    curl -XGET 'http://elasticsearch02:9200/twitter/_stats?pretty'
    複製代碼

2.1 segment 統計

  • 查看low level的lucene的segment信息,能夠用來查看shard和index的更多的信息,包括一些優化信息,由於delete而浪費的數據空間等等。

    curl -XGET 'http://elasticsearch02:9200/twitter/_segments?pretty'
      
      {
          ...
              "_3": {
                  "generation": 3,
                  "num_docs": 1121,
                  "deleted_docs": 53,
                  "size_in_bytes": 228288,
                  "memory_in_bytes": 3211,
                  "committed": true,
                  "search": true,
                  "version": "4.6",
                  "compound": true
              }
          ...
      }
    複製代碼
  • _3,是segment的名稱,這個名稱跟這個segment files的文件名有關係,一個segment的全部文件都是用這個名稱開頭的

  • generation:每次新生成一個segment,就會遞增一個數值,segment名稱也就是這個數值

  • num_docs:在這個segment中存儲的沒有被刪除的document的數量 deleted_docs:在這個segment中存儲的被刪除的document數量,這個數值是無所謂的,由於每次segment merge的時候都會刪除這些document

  • size_in_bytes:這個segment佔用的磁盤空間

  • memory_in_bytes:segment須要將一些數據緩存在內存中,這樣搜索性能才能更高,這個數值就是segment佔用的內存的空間大小

  • committed:segment是否被sync到磁盤上去了,commit/sync的segment能夠確保數據不會丟失,可是即便這個值是false也沒關係,由於數據同時被存儲在了translog裏面,es進程重啓的時候,是能夠重放translog中的日誌來恢復數據的

  • search:這個segment能不被搜索,若是是false的話,可能這個segment已經被sync到磁盤上,可是尚未進行refresh,因此不能被搜索

  • version:lucene的版本號

  • compound:若是是true的話,意味着lucene將這個segment全部的文件都merge成了一個文件,進而能夠節省file descriptor的消耗

2.2 shard存儲信息統計

  • 查詢索引shard copy的存儲信息,能夠看到哪些節點上有哪些shard copy,shard copy的allocation id,每一個shard copy的惟一標識,包括打開索引的時候遇到的報錯。默認狀況下,會顯示至少有一個未分配的copy的shard,若是cluster health是yellow,會顯示至少有一個未分配的replica的shard,當cluster health是red,會顯示有未分配的primary的shard。可是用status=green能夠看到每一個shard的信息。

    curl -XGET 'http://elasticsearch02:9200/twitter/_shard_stores?pretty'
      curl -XGET 'http://elasticsearch02:9200/twitter/_shard_stores?status=green&pretty'
    
      {
          ...
         "0": { 
              "stores": [ 
                  {
                      "sPa3OgxLSYGvQ4oPs-Tajw": { 
                          "name": "node_t0",
                          "transport_address": "local[1]",
                          "attributes": {
                              "mode": "local"
                          }
                      },
                      "allocation_id": "2iNySv_OQVePRX-yaRH_lQ", 
                      "legacy_version": 42, 
                      "allocation" : "primary" | "replica" | "unused", 
                      "store_exception": ... 
                  },
                  ...
              ]
         },
          ...
      }
    複製代碼
  • 0:shard id

  • stores:shard的每一個copy的store信息

  • sPa3OgxLSYGvQ4oPs-Tajw:node id,持有一個copy的node信息

  • allocationi_id:copy的allocationid

  • allocation:shard copy的角色

2.4 clear cache

curl -XPOST 'http://elasticsearch02:9200/twitter/_cache/clear?pretty',這個命令能夠清空全部的緩存
複製代碼

2.5 flush

  • flush API可讓咱們去強制flush多個索引,索引flush之後,就會釋放掉這個索引佔用的內存,由於會將os cache裏的數據強制fsync到磁盤上去,同時還會清理掉translog中的日誌。默認狀況下,es會不定時自動觸發flush操做,以便於及時清理掉內存。POST twitter/_flush,這條命令便可。

  • flush命令能夠接受下面兩個參數,wait_if_going,若是設置爲true,那麼flush api會等到flush操做執行完之後再返回,即便須要等待其餘的flush操做先完成。默認的值是false,這樣的話,若是有其餘flush操做在執行,就會報錯;force,若是沒有必要flush的話,是不會強制一個flush

    curl -XPOST 'http://elasticsearch02:9200/twitter/_flush?pretty'
    複製代碼

2.6 refresh

  • refresh用來顯式的刷新一個index,這樣可讓這個refresh以前執行的全部操做,都處於可見的狀態。POST twitter/_refresh

    curl -XPOST 'http://elasticsearch02:9200/twitter/_refresh?pretty'
    複製代碼

2.7 force merge

  • force merge API能夠強制合併多個索引文件,能夠將一個shard對應的lucene index的多個segment file都合併起來,能夠減小segment file的數量。POST /twitter/_forcemerge。

    curl -XPOST 'http://elasticsearch02:9200/twitter/_forcemerge?pretty'
    複製代碼

3 短路器

es有不少的斷路器,也就是circuit breaker,能夠用來阻止各類操做致使OOM內存溢出。每一個斷路器都有一個限制,就是最多可使用多少內存。此外,還有一個父斷路器指定了全部斷路器最多可使用多少內存。

  • 父短路器

    indices.breaker.total.limit,能夠配置父短路器的最大內存限制,默認是jvm heap內存的70%

  • fielddata短路器

    field data短路器能夠估算每個field的全部數據被加載到內存中,須要耗費多大的內存。這個短路器能夠組織field data加載到jvm內存時發生OOM問題。默認的值是jvm heap的60%。indices.breaker.fielddata.limit,能夠用這個參數來配置。indices.breaker.fielddata.overhead,能夠配置估算因子,估算出來的值會乘以這個估算因子,留一些buffer,默認是1.03。

  • request circuit breaker

    request circuit breaker會阻止每一個請求對應的一些數據結構形成OOM,好比一個聚合請求可能會用jvm內存來作一些彙總計算。indices.breaker.request.limit,最大是jvm heap的60%。indices.breaker.request.overhead,估算因子,默認是1.

  • in flight request circuit breaker

    flight request circuit breaker能夠限制當前全部進來的transport或http層的請求超出一個節點的內存總量,這個內存的使用量就是請求本身自己的長度。network.breaker.inflight_requests.limit,默認是jvm heap的100%。network.breaker.inflight_requests.overhead,估算因子,默認是1.

  • script compilation circuit breaker

    這個短路器能夠阻止一段時間內的inline script編譯的數量。script.max_compilations_per_minute,默認是1分鐘編譯15個。

4 緩存優化

  • fielddata cache

  • 在對field進行排序或者聚合的時候,會用到這個cache。這個cache會將全部的field value加載到內存裏來,這樣能夠加速排序或者聚合的性能。可是每一個field的field data cache的構建是很成本很高昂的,所以建議給機器提供充足的內存來保持fielddata cache。

    indices.fielddata.cache.size,這個參數能夠控制這個cache的大小,能夠是30%這種相對大小,或者是12GB這種絕對大小,默認是沒有限制的。
    複製代碼
  • 實際上是對分詞後的field進行排序或者聚合的時候,纔會使用fielddata這種jvm內存數據結構。若是是對普通的未分詞的field進行排序或者聚合,其實默認是用的doc value數據結構,是在os cache中緩存的。

  • query cache

  • 用來緩存query的結果,每一個node都有一個query cache,使用的是LRU策略,會自動清理數據。可是query cache僅僅會對那些filter後的數據進行緩存,對search後的數據是不會進行緩存的。若是隻是要根據一些field進行等值的查詢或過濾,那麼用filter操做,性能會比較好,query cache

    indices.queries.cache.size,控制query cache的大小,默認是jvm heap的10%。
    複製代碼
  • index buffer

  • 用來存儲最新索引的的document。若是這個buffer滿了以後,document就會被寫入 一個segment file,可是此時實際上是寫入os cache中,沒有用fsync同步到磁盤,這就是refresh過程,寫入os cache中,就能夠被搜索到了。而後flush以後,就fsync到了磁盤上。

    indices.memory.index_buffer_size,控制index buffer的大小,默認是10%。
      indices.memory.min_index_buffer_size,buffer的最小大小,默認是48mb。
    複製代碼
  • index buffer,增刪改document,數據先寫入index buffer,寫到磁盤文件裏面去,不可見的,refresh刷入磁盤文件對應的os cache裏面,還有translog一份數據

  • 對於分佈式的搜索請求,相關的shard都會去執行搜索操做,而後返回一份結果集給一個coordinate node,由那個coordinate node來執行最終的結果合併與計算。shard request cache會緩存每一個shard的local result。那麼對於頻繁請求的數據,就能夠直接從cache中獲取了。與query cache不一樣的是,query cache只是針對filter的,可是shard request cache是針對全部search和聚合求的。

  • shard request cache

  • 默認狀況下,shard request cache僅僅會針對size=0的搜索來進行緩存,僅僅會緩存hits.total,聚合結果等等彙總結果,而不會緩存搜索出來的hits明細數據。cache是很智能的,若是cache對應的doc數據被refresh,也就是修改了,那麼cache就會自動失效。若是cache滿了的話,也會自動用LRU算法來清理掉cache中的數據。

  • 能夠手動來啓用和禁用cache:

    PUT /my_index
      {
        "settings": {
          "index.requests.cache.enable": false
        }
      }
      
      在每一個request中也能夠手動啓用或禁用cache:
      
      GET /my_index/_search?request_cache=true
      {
        "size": 0,
        "aggs": {
          "popular_colors": {
            "terms": {
              "field": "colors"
            }
          }
        }
      }
    複製代碼
  • 可是默認對於size>0的request的結果是不會被cache的,即便在index設置中啓用了request cache也不行。只有在請求的時候,手動加入reqeust cache參數,才能夠對size>0的請求進行result cache。緩存用的key,是完整的請求json,所以每次請求即便json中改變了一點點,那麼也沒法複用上次請求的request cache結果。

    indices.requests.cache.size,能夠設置request cache大小,默認是1%
      GET /_stats/request_cache?human,監控request cache的使用
      若是是search,默認是不緩存的,除非你手動打開request_cache=true,在發送請求的時候
      若是是aggr,默認是緩存的,不手動打開request_cache=true,也會緩存聚合的結果
    複製代碼
  • 索引恢復

    indices.recovery.max_bytes_per_sec,每秒能夠恢復的數據量,默認是40mb
    複製代碼

5 索引管理高級特性

5.1 merge

  • es裏的一個shard,就是一個lucene index,每一個lucene index都是由多個segment file組成的。segment file負責存儲全部的document數據,並且segment file是不可變的。一些小的segment file會被merge成一個大的segment file,這樣能夠保證segment file數量不會膨脹太多,並且能夠將刪除的數據實際上作物理刪除。merge過程會自動進行throttle限流,這樣可讓merge操做和節點上其餘的操做都均衡使用硬件資源。

  • merge scheduler會控制merge的操做何時執行,merge操做會在一些獨立的後臺線程中執行,若是達到了最大的線程數量的話,那麼merg操做就會等待有空閒的線程出來再去執行。

    index.merge.scheduler.max_thread_count,這個參數能夠控制每次merge操做的最大線程數量,
      默認的公式是Math.max(1, Math.min(4, Runtime.getRuntime().availableProcessors() / 2)),
      對於SSD來講,表現是很好的。可是若是咱們使用的是機械硬盤,建議將這個數量下降爲1。
    複製代碼

5.2 translog

  • 對lucene的磁盤持久化,能夠經過一次lucene commit來提交,是一個很重的過程,因此是不可能在每次插入或者刪除操做事後來執行的。因此在上一次提交和下一次提交之間的數據變動,都是在os cache中的,若是機器掛掉,可能致使數據丟失。爲了不這種數據丟失,每一個shard都有一個transaction log,也就是translog,來寫入write ahead log,預寫日誌。任何寫入數據都會同時被寫入translog。若是機器掛掉了,那麼就能夠重放translog中的日誌來恢復shard中的數據。

  • 一次es flush操做,都會執行一次lucene commit,將數據fsync到磁盤上去,同時清空translog文件。在後臺會自動進行這個操做,來確保translog日誌不會增加的太過於巨大,這樣的話重放translog數據來恢復,纔不會太慢。

    index.translog.flush_threshold_size,這個參數能夠設置os cache中數據達到多大的時候,要執行一次flush,默認是512mb。
    複製代碼
  • 此外,默認狀況下,es每隔5秒鐘會在每一個增刪改操做結束以後,對translog進行一次fsync操做,

    可是要求index.translog.durability設置爲async或者request(默認)。
      es只有在primary和每個replica shard的translog fsync以後,纔會對增刪改操做返回的狀態中顯示爲success。
    
      index.translog.sync_interval:設置index.translog.durability=fsync操做時,translog被fsync到磁盤的頻率,默認是5秒
      index.translog.durability:是否要在每次增刪改操做以後,fsync translog。
      
      默認是request,每次寫請求以後,都會fsync translog,這樣的話,即便機器宕機,可是隻要是返回success的操做,
      就意味着translog被fsync到磁盤了,就能夠保證數據不丟失。
      
      async,在後臺每隔必定時間來fsync translog,默認是5秒,機器宕機的時候,可能致使5秒的數據丟失,
      可能有5秒鐘的數據,數據自己是停留在os cache中的,數據對應的translog也停留在os cache中,
      5秒才能將translog從os cache輸入磁盤
    複製代碼

5.3 translog損壞怎麼辦

  • 若是硬盤損壞,可能致使translog出現損壞,es會自動經過checksum來捕獲到這個問題,此時es就會認爲這個shard故障了,並且禁止將shard分配給這個node,同時會嘗試從其餘replica shard來恢復數據。若是沒有replica數據的話,那麼用戶能夠手動經過工具來恢復,使用elasticsearch-translog便可。要注意的是,elasticsaerch-translog工具不能在elasticsearch運行的時候來使用,不然咱們可能丟失數據。

    bin/elasticsearch-translog truncate -d /var/lib/elasticsearchdata/nodes/0/indices/P45vf_YQRhqjfwLMUvSqDw/0/translog/
      
      Checking existing translog files
    複製代碼

6 總結

生產部署還有不少工做要作,本文從初級思路切入,進行了問題的整合。

本套技術專欄做者(秦凱新)專一於大數據及容器雲核心技術解密,具有5年工業級IOT大數據雲平臺建設經驗,可提供全棧的大數據+雲原平生臺諮詢方案,請持續關注本套博客。QQ郵箱地址:1120746959@qq.com,若有任何學術交流,可隨時聯繫

秦凱新

相關文章
相關標籤/搜索