溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

如何進(jìn)行Elasticsearch調(diào)優(yōu)實(shí)踐

發(fā)布時(shí)間:2022-01-12 13:41:53 來(lái)源:億速云 閱讀:144 作者:柒染 欄目:移動(dòng)開(kāi)發(fā)

今天給大家介紹一下如何進(jìn)行Elasticsearch調(diào)優(yōu)實(shí)踐。文章的內(nèi)容小編覺(jué)得不錯(cuò),現(xiàn)在給大家分享一下,覺(jué)得有需要的朋友可以了解一下,希望對(duì)大家有所幫助,下面跟著小編的思路一起來(lái)閱讀吧。

背景

Elasticsearch(ES)作為NOSQL+搜索引擎的有機(jī)結(jié)合體,不僅有近實(shí)時(shí)的查詢(xún)能力,還具有強(qiáng)大的聚合分析能力。因此在全文檢索、日志分析、監(jiān)控系統(tǒng)、數(shù)據(jù)分析等領(lǐng)域ES均有廣泛應(yīng)用。而完整的Elastic Stack體系(Elasticsearch、Logstash、Kibana、Beats),更是提供了數(shù)據(jù)采集、清洗、存儲(chǔ)、可視化的整套解決方案。 

本文基于ES 5.6.4,從性能和穩(wěn)定性?xún)煞矫?,從linux參數(shù)調(diào)優(yōu)、ES節(jié)點(diǎn)配置和ES使用方式三個(gè)角度入手,介紹ES調(diào)優(yōu)的基本方案。當(dāng)然,ES的調(diào)優(yōu)絕不能一概而論,需要根據(jù)實(shí)際業(yè)務(wù)場(chǎng)景做適當(dāng)?shù)娜∩岷驼{(diào)整,文中的疏漏之處也隨時(shí)歡迎批評(píng)指正。

性能調(diào)優(yōu)

一 Linux參數(shù)調(diào)優(yōu)

1. 關(guān)閉交換分區(qū),防止內(nèi)存置換降低性能。 將/etc/fstab 文件中包含swap的行注釋掉

sed -i '/swap/s/^/#/' /etc/fstab
swapoff -a


2. 磁盤(pán)掛載選項(xiàng)

  • noatime:禁止記錄訪問(wèn)時(shí)間戳,提高文件系統(tǒng)讀寫(xiě)性能

  • data=writeback: 不記錄data journal,提高文件系統(tǒng)寫(xiě)入性能

  • barrier=0:barrier保證journal先于data刷到磁盤(pán),上面關(guān)閉了journal,這里的barrier也就沒(méi)必要開(kāi)啟了

  • nobh:關(guān)閉buffer_head,防止內(nèi)核打斷大塊數(shù)據(jù)的IO操作

mount -o noatime,data=writeback,barrier=0,nobh /dev/sda /es_data

3. 對(duì)于SSD磁盤(pán),采用電梯調(diào)度算法,因?yàn)镾SD提供了更智能的請(qǐng)求調(diào)度算法,不需要內(nèi)核去做多余的調(diào)整 (僅供參考)

echo noop > /sys/block/sda/queue/scheduler

二 ES節(jié)點(diǎn)配置

conf/elasticsearch.yml文件:

 1. 適當(dāng)增大寫(xiě)入buffer和bulk隊(duì)列長(zhǎng)度,提高寫(xiě)入性能和穩(wěn)定性
indices.memory.index_buffer_size: 15%
thread_pool.bulk.queue_size: 1024

2. 計(jì)算disk使用量時(shí),不考慮正在搬遷的shard

在規(guī)模比較大的集群中,可以防止新建shard時(shí)掃描所有shard的元數(shù)據(jù),提升shard分配速度。

cluster.routing.allocation.disk.include_relocations: false

三 ES使用方式

1. 控制字段的存儲(chǔ)選項(xiàng)

ES底層使用Lucene存儲(chǔ)數(shù)據(jù),主要包括行存(StoreFiled)、列存(DocValues)和倒排索引(InvertIndex)三部分。 大多數(shù)使用場(chǎng)景中,沒(méi)有必要同時(shí)存儲(chǔ)這三個(gè)部分,可以通過(guò)下面的參數(shù)來(lái)做適當(dāng)調(diào)整:

  • StoreFiled: 行存,其中占比最大的是source字段,它控制doc原始數(shù)據(jù)的存儲(chǔ)。在寫(xiě)入數(shù)據(jù)時(shí),ES把doc原始數(shù)據(jù)的整個(gè)json結(jié)構(gòu)體當(dāng)做一個(gè)string,存儲(chǔ)為source字段。查詢(xún)時(shí),可以通過(guò)source字段拿到當(dāng)初寫(xiě)入時(shí)的整個(gè)json結(jié)構(gòu)體。 所以,如果沒(méi)有取出整個(gè)原始json結(jié)構(gòu)體的需求,可以通過(guò)下面的命令,在mapping中關(guān)閉source字段或者只在source中存儲(chǔ)部分字段,數(shù)據(jù)查詢(xún)時(shí)仍可通過(guò)ES的docvaluefields獲取所有字段的值。

    注意:關(guān)閉source后, update, updatebyquery, reindex等接口將無(wú)法正常使用,所以有update等需求的index不能關(guān)閉source。


# 關(guān)閉 _source
PUT my_index 
{
  "mappings": {
    "my_type": {
      "_source": {
        "enabled": false
      }
    }
  }
}
# _source只存儲(chǔ)部分字段,通過(guò)includes指定要存儲(chǔ)的字段或者通過(guò)excludes濾除不需要的字段
PUT my_index
{
  "mappings": {
    "_doc": {
      "_source": {
        "includes": [
          "*.count",
          "meta.*"
        ],
        "excludes": [
          "meta.description",
          "meta.other.*"
        ]
      }
    }
  }
}
  • docvalues:控制列存。

    ES主要使用列存來(lái)支持sorting, aggregations和scripts功能,對(duì)于沒(méi)有上述需求的字段,可以通過(guò)下面的命令關(guān)閉docvalues,降低存儲(chǔ)成本。

PUT my_index
{
  "mappings": {
    "my_type": {
      "properties": {
        "session_id": { 
          "type": "keyword",
          "doc_values": false
        }
      }
    }
  }
}
  • index:控制倒排索引。

    ES默認(rèn)對(duì)于所有字段都開(kāi)啟了倒排索引,用于查詢(xún)。對(duì)于沒(méi)有查詢(xún)需求的字段,可以通過(guò)下面的命令關(guān)閉倒排索引。

PUT my_index
{
  "mappings": {
    "my_type": {
      "properties": {
        "session_id": { 
          "type": "keyword",
          "index": false
        }
      }
    }
  }
}
  • all:ES的一個(gè)特殊的字段,ES把用戶(hù)寫(xiě)入json的所有字段值拼接成一個(gè)字符串后,做分詞,然后保存倒排索引,用于支持整個(gè)json的全文檢索。

    這種需求適用的場(chǎng)景較少,可以通過(guò)下面的命令將all字段關(guān)閉,節(jié)約存儲(chǔ)成本和cpu開(kāi)銷(xiāo)。(ES 6.0+以上的版本不再支持_all字段,不需要設(shè)置)

PUT /my_index
{
  "mapping": {
    "my_type": {
      "_all": {
        "enabled": false   
      }
    }
  }
}
  • fieldnames:該字段用于exists查詢(xún),來(lái)確認(rèn)某個(gè)doc里面有無(wú)一個(gè)字段存在。若沒(méi)有這種需求,可以將其關(guān)閉。


PUT /my_index
{
  "mapping": {
    "my_type": {
      "_field_names": {
        "enabled": false   
      }
    }
  }
}

2. 開(kāi)啟最佳壓縮

對(duì)于打開(kāi)了上述_source字段的index,可以通過(guò)下面的命令來(lái)把lucene適用的壓縮算法替換成 DEFLATE,提高數(shù)據(jù)壓縮率。

PUT /my_index/_settings
{
    "index.codec": "best_compression"
}

3. bulk批量寫(xiě)入

寫(xiě)入數(shù)據(jù)時(shí)盡量使用下面的bulk接口批量寫(xiě)入,提高寫(xiě)入效率。每個(gè)bulk請(qǐng)求的doc數(shù)量設(shè)定區(qū)間推薦為1k~1w,具體可根據(jù)業(yè)務(wù)場(chǎng)景選取一個(gè)適當(dāng)?shù)臄?shù)量。

POST _bulk
{ "index" : { "_index" : "test", "_type" : "type1" } }
{ "field1" : "value1" }
{ "index" : { "_index" : "test", "_type" : "type1" } }
{ "field1" : "value2" }

4. 調(diào)整translog同步策略

默認(rèn)情況下,translog的持久化策略是,對(duì)于每個(gè)寫(xiě)入請(qǐng)求都做一次flush,刷新translog數(shù)據(jù)到磁盤(pán)上。這種頻繁的磁盤(pán)IO操作是嚴(yán)重影響寫(xiě)入性能的,如果可以接受一定概率的數(shù)據(jù)丟失(這種硬件故障的概率很?。?,可以通過(guò)下面的命令調(diào)整 translog 持久化策略為異步周期性執(zhí)行,并適當(dāng)調(diào)整translog的刷盤(pán)周期。

PUT my_index
{
  "settings": {
    "index": {
      "translog": {
        "sync_interval": "5s",
        "durability": "async"
      }
    }
  }
}

5. 調(diào)整refresh_interval

寫(xiě)入Lucene的數(shù)據(jù),并不是實(shí)時(shí)可搜索的,ES必須通過(guò)refresh的過(guò)程把內(nèi)存中的數(shù)據(jù)轉(zhuǎn)換成Lucene的完整segment后,才可以被搜索。默認(rèn)情況下,ES每一秒會(huì)refresh一次,產(chǎn)生一個(gè)新的segment,這樣會(huì)導(dǎo)致產(chǎn)生的segment較多,從而segment merge較為頻繁,系統(tǒng)開(kāi)銷(xiāo)較大。如果對(duì)數(shù)據(jù)的實(shí)時(shí)可見(jiàn)性要求較低,可以通過(guò)下面的命令提高refresh的時(shí)間間隔,降低系統(tǒng)開(kāi)銷(xiāo)。

PUT my_index
{
  "settings": {
    "index": {
        "refresh_interval" : "30s"
    }
  }
}

6. merge并發(fā)控制

ES的一個(gè)index由多個(gè)shard組成,而一個(gè)shard其實(shí)就是一個(gè)Lucene的index,它又由多個(gè)segment組成,且Lucene會(huì)不斷地把一些小的segment合并成一個(gè)大的segment,這個(gè)過(guò)程被稱(chēng)為merge。默認(rèn)值是Math.max(1, Math.min(4, Runtime.getRuntime().availableProcessors() / 2)),當(dāng)節(jié)點(diǎn)配置的cpu核數(shù)較高時(shí),merge占用的資源可能會(huì)偏高,影響集群的性能,可以通過(guò)下面的命令調(diào)整某個(gè)index的merge過(guò)程的并發(fā)度:

PUT /my_index/_settings
{
    "index.merge.scheduler.max_thread_count": 2
}

7. 寫(xiě)入數(shù)據(jù)不指定_id,讓ES自動(dòng)產(chǎn)生

當(dāng)用戶(hù)顯示指定id寫(xiě)入數(shù)據(jù)時(shí),ES會(huì)先發(fā)起查詢(xún)來(lái)確定index中是否已經(jīng)有相同id的doc存在,若有則先刪除原有doc再寫(xiě)入新doc。這樣每次寫(xiě)入時(shí),ES都會(huì)耗費(fèi)一定的資源做查詢(xún)。如果用戶(hù)寫(xiě)入數(shù)據(jù)時(shí)不指定doc,ES則通過(guò)內(nèi)部算法產(chǎn)生一個(gè)隨機(jī)的id,并且保證id的唯一性,這樣就可以跳過(guò)前面查詢(xún)id的步驟,提高寫(xiě)入效率。 所以,在不需要通過(guò)id字段去重、update的使用場(chǎng)景中,寫(xiě)入不指定id可以提升寫(xiě)入速率?;A(chǔ)架構(gòu)部數(shù)據(jù)庫(kù)團(tuán)隊(duì)的測(cè)試結(jié)果顯示,無(wú)id的數(shù)據(jù)寫(xiě)入性能可能比有_id的高出近一倍,實(shí)際損耗和具體測(cè)試場(chǎng)景相關(guān)。

# 寫(xiě)入時(shí)指定_id
POST _bulk
{ "index" : { "_index" : "test", "_type" : "type1", "_id" : "1" } }
{ "field1" : "value1" }
# 寫(xiě)入時(shí)不指定_id
POST _bulk
{ "index" : { "_index" : "test", "_type" : "type1" } }
{ "field1" : "value1" }

8. 使用routing

對(duì)于數(shù)據(jù)量較大的index,一般會(huì)配置多個(gè)shard來(lái)分?jǐn)倝毫Α_@種場(chǎng)景下,一個(gè)查詢(xún)會(huì)同時(shí)搜索所有的shard,然后再將各個(gè)shard的結(jié)果合并后,返回給用戶(hù)。對(duì)于高并發(fā)的小查詢(xún)場(chǎng)景,每個(gè)分片通常僅抓取極少量數(shù)據(jù),此時(shí)查詢(xún)過(guò)程中的調(diào)度開(kāi)銷(xiāo)遠(yuǎn)大于實(shí)際讀取數(shù)據(jù)的開(kāi)銷(xiāo),且查詢(xún)速度取決于最慢的一個(gè)分片。開(kāi)啟routing功能后,ES會(huì)將routing相同的數(shù)據(jù)寫(xiě)入到同一個(gè)分片中(也可以是多個(gè),由index.routingpartitionsize參數(shù)控制)。如果查詢(xún)時(shí)指定routing,那么ES只會(huì)查詢(xún)r(jià)outing指向的那個(gè)分片,可顯著降低調(diào)度開(kāi)銷(xiāo),提升查詢(xún)效率。 routing的使用方式如下:

# 寫(xiě)入
PUT my_index/my_type/1?routing=user1
{
  "title": "This is a document"
}
# 查詢(xún)
GET my_index/_search?routing=user1,user2 
{
  "query": {
    "match": {
      "title": "document"
    }
  }
}

9. 為string類(lèi)型的字段選取合適的存儲(chǔ)方式

  • 存為text類(lèi)型的字段(string字段默認(rèn)類(lèi)型為text): 做分詞后存儲(chǔ)倒排索引,支持全文檢索,可以通過(guò)下面幾個(gè)參數(shù)優(yōu)化其存儲(chǔ)方式:

    • norms:用于在搜索時(shí)計(jì)算該doc的_score(代表這條數(shù)據(jù)與搜索條件的相關(guān)度),如果不需要評(píng)分,可以將其關(guān)閉。

    • indexoptions:控制倒排索引中包括哪些信息(docs、freqs、positions、offsets)。對(duì)于不太注重score/highlighting的使用場(chǎng)景,可以設(shè)為 docs來(lái)降低內(nèi)存/磁盤(pán)資源消耗。

    • fields: 用于添加子字段。對(duì)于有sort和聚合查詢(xún)需求的場(chǎng)景,可以添加一個(gè)keyword子字段以支持這兩種功能。

PUT my_index
{
  "mappings": {
    "my_type": {
      "properties": {
        "title": { 
          "type": "text",
          "norms": false,
          "index_options": "docs",
          "fields": {
            "raw": { 
              "type":  "keyword"
            }
          }
        }
      }
    }
  }
}
  • 存為keyword類(lèi)型的字段: 不做分詞,不支持全文檢索。text分詞消耗CPU資源,冗余存儲(chǔ)keyword子字段占用存儲(chǔ)空間。如果沒(méi)有全文索引需求,只是要通過(guò)整個(gè)字段做搜索,可以設(shè)置該字段的類(lèi)型為keyword,提升寫(xiě)入速率,降低存儲(chǔ)成本。 設(shè)置字段類(lèi)型的方法有兩種:一是創(chuàng)建一個(gè)具體的index時(shí),指定字段的類(lèi)型;二是通過(guò)創(chuàng)建template,控制某一類(lèi)index的字段類(lèi)型。

# 1. 通過(guò)mapping指定 tags 字段為keyword類(lèi)型
PUT my_index
{
  "mappings": {
    "my_type": {
      "properties": {
        "tags": {
          "type":  "keyword"
        }
      }
    }
  }
}
# 2. 通過(guò)template,指定my_index*類(lèi)的index,其所有string字段默認(rèn)為keyword類(lèi)型
PUT _template/my_template
{
    "order": 0,
    "template": "my_index*",
    "mappings": {
      "_default_": {
        "dynamic_templates": [
          {
            "strings": {
              "match_mapping_type": "string",
              "mapping": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          }
        ]
      }
    },
    "aliases": {}
  }

10. 查詢(xún)時(shí),使用query-bool-filter組合取代普通query

默認(rèn)情況下,ES通過(guò)一定的算法計(jì)算返回的每條數(shù)據(jù)與查詢(xún)語(yǔ)句的相關(guān)度,并通過(guò)score字段來(lái)表征。但對(duì)于非全文索引的使用場(chǎng)景,用戶(hù)并不care查詢(xún)結(jié)果與查詢(xún)條件的相關(guān)度,只是想精確的查找目標(biāo)數(shù)據(jù)。此時(shí),可以通過(guò)query-bool-filter組合來(lái)讓ES不計(jì)算score,并且盡可能的緩存filter的結(jié)果集,供后續(xù)包含相同filter的查詢(xún)使用,提高查詢(xún)效率。

# 普通查詢(xún)
POST my_index/_search
{
  "query": {
    "term" : { "user" : "Kimchy" } 
  }
}
# query-bool-filter 加速查詢(xún)
POST my_index/_search
{
  "query": {
    "bool": {
      "filter": {
        "term": { "user": "Kimchy" }
      }
    }
  }
}

11. index按日期滾動(dòng),便于管理

寫(xiě)入ES的數(shù)據(jù)最好通過(guò)某種方式做分割,存入不同的index。常見(jiàn)的做法是將數(shù)據(jù)按模塊/功能分類(lèi),寫(xiě)入不同的index,然后按照時(shí)間去滾動(dòng)生成index。這樣做的好處是各種數(shù)據(jù)分開(kāi)管理不會(huì)混淆,也易于提高查詢(xún)效率。同時(shí)index按時(shí)間滾動(dòng),數(shù)據(jù)過(guò)期時(shí)刪除整個(gè)index,要比一條條刪除數(shù)據(jù)或deletebyquery效率高很多,因?yàn)閯h除整個(gè)index是直接刪除底層文件,而deletebyquery是查詢(xún)-標(biāo)記-刪除。

舉例說(shuō)明,假如有[modulea,moduleb]兩個(gè)模塊產(chǎn)生的數(shù)據(jù),那么index規(guī)劃可以是這樣的:一類(lèi)index名稱(chēng)是modulea + {日期},另一類(lèi)index名稱(chēng)是module_b+ {日期}。對(duì)于名字中的日期,可以在寫(xiě)入數(shù)據(jù)時(shí)自己指定精確的日期,也可以通過(guò)ES的ingest pipeline中的index-name-processor實(shí)現(xiàn)(會(huì)有寫(xiě)入性能損耗)。

# module_a 類(lèi)index
- 創(chuàng)建index:
PUT module_a@2018_01_01
{
    "settings" : {
        "index" : {
            "number_of_shards" : 3, 
            "number_of_replicas" : 2 
        }
    }
}
PUT module_a@2018_01_02
{
    "settings" : {
        "index" : {
            "number_of_shards" : 3, 
            "number_of_replicas" : 2 
        }
    }
}
...
- 查詢(xún)數(shù)據(jù):
GET module_a@*/_search
#  module_b 類(lèi)index
- 創(chuàng)建index:
PUT module_b@2018_01_01
{
    "settings" : {
        "index" : {
            "number_of_shards" : 3, 
            "number_of_replicas" : 2 
        }
    }
}
PUT module_b@2018_01_02
{
    "settings" : {
        "index" : {
            "number_of_shards" : 3, 
            "number_of_replicas" : 2 
        }
    }
}
...
- 查詢(xún)數(shù)據(jù):
GET module_b@*/_search

12. 按需控制index的分片數(shù)和副本數(shù)

分片(shard):一個(gè)ES的index由多個(gè)shard組成,每個(gè)shard承載index的一部分?jǐn)?shù)據(jù)。

副本(replica):index也可以設(shè)定副本數(shù)(numberofreplicas),也就是同一個(gè)shard有多少個(gè)備份。對(duì)于查詢(xún)壓力較大的index,可以考慮提高副本數(shù)(numberofreplicas),通過(guò)多個(gè)副本均攤查詢(xún)壓力。

shard數(shù)量(numberofshards)設(shè)置過(guò)多或過(guò)低都會(huì)引發(fā)一些問(wèn)題:shard數(shù)量過(guò)多,則批量寫(xiě)入/查詢(xún)請(qǐng)求被分割為過(guò)多的子寫(xiě)入/查詢(xún),導(dǎo)致該index的寫(xiě)入、查詢(xún)拒絕率上升;對(duì)于數(shù)據(jù)量較大的inex,當(dāng)其shard數(shù)量過(guò)小時(shí),無(wú)法充分利用節(jié)點(diǎn)資源,造成機(jī)器資源利用率不高 或 不均衡,影響寫(xiě)入/查詢(xún)的效率。

對(duì)于每個(gè)index的shard數(shù)量,可以根據(jù)數(shù)據(jù)總量、寫(xiě)入壓力、節(jié)點(diǎn)數(shù)量等綜合考量后設(shè)定,然后根據(jù)數(shù)據(jù)增長(zhǎng)狀態(tài)定期檢測(cè)下shard數(shù)量是否合理?;A(chǔ)架構(gòu)部數(shù)據(jù)庫(kù)團(tuán)隊(duì)的推薦方案是:

  • 對(duì)于數(shù)據(jù)量較小(100GB以下)的index,往往寫(xiě)入壓力查詢(xún)壓力相對(duì)較低,一般設(shè)置3~5個(gè)shard,numberofreplicas設(shè)置為1即可(也就是一主一從,共兩副本) 。

  • 對(duì)于數(shù)據(jù)量較大(100GB以上)的index:

    • 一般把單個(gè)shard的數(shù)據(jù)量控制在(20GB~50GB)

    • 讓index壓力分?jǐn)傊炼鄠€(gè)節(jié)點(diǎn):可通過(guò)index.routing.allocation.totalshardsper_node參數(shù),強(qiáng)制限定一個(gè)節(jié)點(diǎn)上該index的shard數(shù)量,讓shard盡量分配到不同節(jié)點(diǎn)上

    • 綜合考慮整個(gè)index的shard數(shù)量,如果shard數(shù)量(不包括副本)超過(guò)50個(gè),就很可能引發(fā)拒絕率上升的問(wèn)題,此時(shí)可考慮把該index拆分為多個(gè)獨(dú)立的index,分?jǐn)倲?shù)據(jù)量,同時(shí)配合routing使用,降低每個(gè)查詢(xún)需要訪問(wèn)的shard數(shù)量。


穩(wěn)定性調(diào)優(yōu)

一 Linux參數(shù)調(diào)優(yōu)

  1. # 修改系統(tǒng)資源限制

  2. # 單用戶(hù)可以打開(kāi)的最大文件數(shù)量,可以設(shè)置為官方推薦的65536或更大些

  3. echo "* - nofile 655360" >>/etc/security/limits.conf

  4. # 單用戶(hù)內(nèi)存地址空間

  5. echo "* - as unlimited" >>/etc/security/limits.conf

  6. # 單用戶(hù)線程數(shù)

  7. echo "* - nproc 2056474" >>/etc/security/limits.conf

  8. # 單用戶(hù)文件大小

  9. echo "* - fsize unlimited" >>/etc/security/limits.conf

  10. # 單用戶(hù)鎖定內(nèi)存

  11. echo "* - memlock unlimited" >>/etc/security/limits.conf


  12. # 單進(jìn)程可以使用的最大map內(nèi)存區(qū)域數(shù)量

  13. echo "vm.max_map_count = 655300" >>/etc/sysctl.conf


  14. # TCP全連接隊(duì)列參數(shù)設(shè)置, 這樣設(shè)置的目的是防止節(jié)點(diǎn)數(shù)較多(比如超過(guò)100)的ES集群中,節(jié)點(diǎn)異常重啟時(shí)全連接隊(duì)列在啟動(dòng)瞬間打滿(mǎn),造成節(jié)點(diǎn)hang住,整個(gè)集群響應(yīng)遲滯的情況

  15. echo "net.ipv4.tcp_abort_on_overflow = 1" >>/etc/sysctl.conf

  16. echo "net.core.somaxconn = 2048" >>/etc/sysctl.conf


  17. # 降低tcp alive time,防止無(wú)效鏈接占用鏈接數(shù)

  18. echo 300 >/proc/sys/net/ipv4/tcp_keepalive_time


二 ES節(jié)點(diǎn)配置

1. jvm.options

-Xms和-Xmx設(shè)置為相同的值,推薦設(shè)置為機(jī)器內(nèi)存的一半左右,剩余一半留給系統(tǒng)cache使用。

  • jvm內(nèi)存建議不要低于2G,否則有可能因?yàn)閮?nèi)存不足導(dǎo)致ES無(wú)法正常啟動(dòng)或OOM

  • jvm建議不要超過(guò)32G,否則jvm會(huì)禁用內(nèi)存對(duì)象指針壓縮技術(shù),造成內(nèi)存浪費(fèi)

2. elasticsearch.yml


  • 設(shè)置內(nèi)存熔斷參數(shù),防止寫(xiě)入或查詢(xún)壓力過(guò)高導(dǎo)致OOM,具體數(shù)值可根據(jù)使用場(chǎng)景調(diào)整。 indices.breaker.total.limit: 30% indices.breaker.request.limit: 6% indices.breaker.fielddata.limit: 3%


  • 調(diào)小查詢(xún)使用的cache,避免cache占用過(guò)多的jvm內(nèi)存,具體數(shù)值可根據(jù)使用場(chǎng)景調(diào)整。 indices.queries.cache.count: 500 indices.queries.cache.size: 5%


  • 單機(jī)多節(jié)點(diǎn)時(shí),主從shard分配以ip為依據(jù),分配到不同的機(jī)器上,避免單機(jī)掛掉導(dǎo)致數(shù)據(jù)丟失。 cluster.routing.allocation.awareness.attributes: ip node.attr.ip: 1.1.1.1

三 ES使用方式

1. 節(jié)點(diǎn)數(shù)較多的集群,增加專(zhuān)有master,提升集群穩(wěn)定性

ES集群的元信息管理、index的增刪操作、節(jié)點(diǎn)的加入剔除等集群管理的任務(wù)都是由master節(jié)點(diǎn)來(lái)負(fù)責(zé)的,master節(jié)點(diǎn)定期將最新的集群狀態(tài)廣播至各個(gè)節(jié)點(diǎn)。所以,master的穩(wěn)定性對(duì)于集群整體的穩(wěn)定性是至關(guān)重要的。當(dāng)集群的節(jié)點(diǎn)數(shù)量較大時(shí)(比如超過(guò)30個(gè)節(jié)點(diǎn)),集群的管理工作會(huì)變得復(fù)雜很多。此時(shí)應(yīng)該創(chuàng)建專(zhuān)有master節(jié)點(diǎn),這些節(jié)點(diǎn)只負(fù)責(zé)集群管理,不存儲(chǔ)數(shù)據(jù),不承擔(dān)數(shù)據(jù)讀寫(xiě)壓力;其他節(jié)點(diǎn)則僅負(fù)責(zé)數(shù)據(jù)讀寫(xiě),不負(fù)責(zé)集群管理的工作。

這樣把集群管理和數(shù)據(jù)的寫(xiě)入/查詢(xún)分離,互不影響,防止因讀寫(xiě)壓力過(guò)大造成集群整體不穩(wěn)定。 將專(zhuān)有master節(jié)點(diǎn)和數(shù)據(jù)節(jié)點(diǎn)的分離,需要修改ES的配置文件,然后滾動(dòng)重啟各個(gè)節(jié)點(diǎn)。

# 專(zhuān)有master節(jié)點(diǎn)的配置文件(conf/elasticsearch.yml)增加如下屬性:
node.master: true 
node.data: false 
node.ingest: false 
# 數(shù)據(jù)節(jié)點(diǎn)的配置文件增加如下屬性(與上面的屬性相反):
node.master: false 
node.data: true 
node.ingest: true

2. 控制index、shard總數(shù)量

上面提到,ES的元信息由master節(jié)點(diǎn)管理,定期同步給各個(gè)節(jié)點(diǎn),也就是每個(gè)節(jié)點(diǎn)都會(huì)存儲(chǔ)一份。這個(gè)元信息主要存儲(chǔ)在clusterstate中,如所有node元信息(indices、節(jié)點(diǎn)各種統(tǒng)計(jì)參數(shù))、所有index/shard的元信息(mapping, location, size)、元數(shù)據(jù)ingest等。

ES在創(chuàng)建新分片時(shí),要根據(jù)現(xiàn)有的分片分布情況指定分片分配策略,從而使各個(gè)節(jié)點(diǎn)上的分片數(shù)基本一致,此過(guò)程中就需要深入遍歷clusterstate。當(dāng)集群中的index/shard過(guò)多時(shí),clusterstate結(jié)構(gòu)會(huì)變得過(guò)于復(fù)雜,導(dǎo)致遍歷clusterstate效率低下,集群響應(yīng)遲滯?;A(chǔ)架構(gòu)部數(shù)據(jù)庫(kù)團(tuán)隊(duì)曾經(jīng)在一個(gè)20個(gè)節(jié)點(diǎn)的集群里,創(chuàng)建了4w+個(gè)shard,導(dǎo)致新建一個(gè)index需要60s+才能完成。 當(dāng)index/shard數(shù)量過(guò)多時(shí),可以考慮從以下幾方面改進(jìn):

  • 降低數(shù)據(jù)量較小的index的shard數(shù)量

  • 把一些有關(guān)聯(lián)的index合并成一個(gè)index

  • 數(shù)據(jù)按某個(gè)維度做拆分,寫(xiě)入多個(gè)集群

3. Segment Memory優(yōu)化

前面提到,ES底層采用Lucene做存儲(chǔ),而Lucene的一個(gè)index又由若干segment組成,每個(gè)segment都會(huì)建立自己的倒排索引用于數(shù)據(jù)查詢(xún)。Lucene為了加速查詢(xún),為每個(gè)segment的倒排做了一層前綴索引,這個(gè)索引在Lucene4.0以后采用的數(shù)據(jù)結(jié)構(gòu)是FST (Finite State Transducer)。Lucene加載segment的時(shí)候?qū)⑵淙垦b載到內(nèi)存中,加快查詢(xún)速度。這部分內(nèi)存被稱(chēng)為SegmentMemory, 常駐內(nèi)存,占用heap,無(wú)法被GC。

前面提到,為利用JVM的對(duì)象指針壓縮技術(shù)來(lái)節(jié)約內(nèi)存,通常建議JVM內(nèi)存分配不要超過(guò)32G。當(dāng)集群的數(shù)據(jù)量過(guò)大時(shí),SegmentMemory會(huì)吃掉大量的堆內(nèi)存,而JVM內(nèi)存空間又有限,此時(shí)就需要想辦法降低SegmentMemory的使用量了,常用方法有下面幾個(gè):

  • 定期刪除不使用的index

  • 對(duì)于不常訪問(wèn)的index,可以通過(guò)close接口將其關(guān)閉,用到時(shí)再打開(kāi)

  • 通過(guò)force_merge接口強(qiáng)制合并segment,降低segment數(shù)量

基礎(chǔ)架構(gòu)部數(shù)據(jù)庫(kù)團(tuán)隊(duì)在此基礎(chǔ)上,對(duì)FST部分進(jìn)行了優(yōu)化,釋放高達(dá)40%的Segment Memory內(nèi)存空間。

以上就是如何進(jìn)行Elasticsearch調(diào)優(yōu)實(shí)踐的全部?jī)?nèi)容了,更多與如何進(jìn)行Elasticsearch調(diào)優(yōu)實(shí)踐相關(guān)的內(nèi)容可以搜索億速云之前的文章或者瀏覽下面的文章進(jìn)行學(xué)習(xí)哈!相信小編會(huì)給大家增添更多知識(shí),希望大家能夠支持一下億速云!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI