Elasticsearch 壓測方案之 esrally 簡介

由于 Elasticsearch(后文簡稱es) 的簡單易用及其在大數(shù)據(jù)處理方面的良好性能,越來越多的公司選用 es 作為自己的業(yè)務解決方案。然而在引入新的解決方案前,不免要做一番調(diào)研和測試,本文便是介紹官方的一個 es 壓測工具 esrally,希望能為大家?guī)韼椭?/p>

為什么要壓測?

關(guān)于壓測,我們先來看下百度百科上的一個定義。

壓測,即壓力測試,是確立系統(tǒng)穩(wěn)定性的一種測試方法,通常在系統(tǒng)正常運作范圍之外進行,以考察其功能極限和隱患。

從定義不難看出壓測的目的,是要測出一個系統(tǒng)的極限,提早發(fā)現(xiàn)隱患,早作打算。那么對于 es 來講,我認為壓測一般有以下幾個目的:

  1. 驗證 es 的性能,盡管網(wǎng)上把 es 的性能夸上天了,還是自己跑一下才放心。
  2. 針對 es 的某些配置做試驗性測試,比如關(guān)閉索引的 _all 特性,是否能提高寫性能,具體能提高多少。
  3. 對比 es 新版本和舊版本的性能差異。眾所周知,es 的版本升級非???,用著 2.x 的同學們還沒來得及升級 5.x ,眼看 6.x 都要發(fā)布了。此時,你到底要不要升級呢?答案雖然是肯定的,但是你怎么說服你的 leader 呢?很簡單:壓測新版本,和舊版本做對比,用表格、圖表指明新版本在寫性能、讀性能方面的改善等等,搞定。
  4. 對 es 集群做容量規(guī)劃。俗話說“人無遠慮,必有近憂”,容量規(guī)劃就是“遠慮”。簡單講就是你線上的 es 集群一共需要多少節(jié)點?每個節(jié)點的配置如何?這個集群的寫性能極限是多少?讀性能呢?如果你回答不了這些問題,那就說明你沒有做過容量規(guī)劃,只是兩眼一抹黑,說干就干,上了再說,好在有驚無險,沒有碰到性能問題。至于什么時候會遇到問題,你也說不準,感覺是個概率和人品問題……對面的老板已經(jīng)黑臉了…… 對于這個問題我們在最后再來詳細討論。

如何進行壓測?

現(xiàn)在我們知道壓測的目的了,接下來該如何進行壓測呢?一般有以下幾個方案:

  1. 自己寫代碼。無需多言,想怎么寫怎么寫,難點在于如果確保測試代碼的專業(yè)性。這里有一些開源項目,留給大家自己探索:esperfelasticsearch-stress-test
  2. http壓測工具。es 對外暴露了 Restful API,因此所有的針對 http 協(xié)議的壓測工具都可以用來測試 es,比如 JMeter、httpload等等。
  3. elastic 官方工具 esrally。

各個壓測方案各有優(yōu)劣,大家可以根據(jù)自己的需求和工具熟悉度來選擇自己的壓測工具。接下來我們就來具體了解下 esrally。

入門

簡介

esrally 是 elastic 官方開源的一款基于 python3 實現(xiàn)的針對 es 的壓測工具,源碼地址為https://github.com/elastic/rally,相關(guān)博客介紹在這里。esrally主要功能如下:

  • 自動創(chuàng)建、壓測和銷毀 es 集群
  • 可分 es 版本管理壓測數(shù)據(jù)和方案
  • 完善的壓測數(shù)據(jù)展示,支持不同壓測之間的數(shù)據(jù)對比分析,也可以將數(shù)據(jù)存儲到指定的es中進行二次分析
  • 支持收集 JVM 詳細信息,比如內(nèi)存、GC等數(shù)據(jù)來定位性能問題

elastic 官方也是基于 esrally 進行 es 的性能測試,并將結(jié)果實時發(fā)布到 https://elasticsearch-benchmarks.elastic.co/ ,大家可以從該網(wǎng)站上直接查看 es 的性能。官方使用兩臺服務器進行壓測,一臺運行 esrally ,一臺運行 es,服務器的配置如下:

CPU: Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz
RAM: 32 GB
SSD: Crucial MX200
OS: Linux Kernel version 4.8.0-53
JVM: Oracle JDK 1.8.0_131-b11

網(wǎng)站頂部的 Geonames、Geopoint、Percolator等都是針對不同的數(shù)據(jù)集做的壓測,比如下面這些圖展示了 logging 日志類數(shù)據(jù)的壓測結(jié)果。

寫性能
讀性能
其他系統(tǒng)指標

快速入門

esrally 的文檔在這里,這里簡單說下安裝與運行。
esrally 對于軟件環(huán)境的要求如下:

  • Python 3.4+ 和 pip3
  • JDK 8
  • git 1.9+

安裝方法為:

pip3 install esrally

Tips:
可以使用國內(nèi)的pip源,比如豆瓣或者阿里的,這樣安裝會快很多。

安裝完畢后執(zhí)行如下的配置命令,確認一些數(shù)據(jù)存放的路徑即可。

esrally configure

接下來就可以開跑了,比如下面這條命令是針對 es 5.0.0 版本進行壓力測試。

esrally --distribution-version=5.0.0

運行結(jié)束后,會得到如下的結(jié)果。

壓測結(jié)果

對于第一次見到壓測結(jié)果的同學來說可能有些暈,這么多數(shù)據(jù),該怎么看?!別急,一步步來!

Tips:
由于 esrally 的測試數(shù)據(jù)存儲在國外 aws 上,導致下載很慢甚至會超時失敗,從而導致整個壓測無法進行。后面我會把這些測試數(shù)據(jù)的壓縮包放到國內(nèi),大家可以下載后直接放到 esrally 的數(shù)據(jù)文件夾下面,保證壓測的正常進行。另外由于數(shù)據(jù)量過大,壓測的時間一般會很久,可能在1個小時左右,所以大家要有耐心哦~
如果你只是想體驗下,可以加上 --test-mode 的參數(shù),此時只會下載1000條文檔進行測試。

相關(guān)術(shù)語

rally 是汽車拉力賽的意思,也就是說 esrally 是將壓測比作了汽車拉力賽,因此其中的很多術(shù)語都是從汽車拉力賽中借鑒來的。

track

track 是賽道的意思,在這里是指壓測用的數(shù)據(jù)和測試策略,詳細文檔在這里。esrally 自帶的track都在 github 上,地址在這里 https://github.com/elastic/rally-tracks。在該 repository 中,有很多測試數(shù)據(jù),比如 geonames geopoint logging nested 等,每個數(shù)據(jù)文件夾中的 README.md 中有詳細的數(shù)據(jù)介紹,而 track.json 便是壓測策略的定義文件。
我們來看下 loggins/track.json 文件

{% import "rally.helpers" as rally with context %}

{
  "short-description": "Logging benchmark",
  "description": "This benchmark indexes HTTP server log data from the 1998 world cup.",
  "data-url": "http://benchmarks.elasticsearch.org.s3.amazonaws.com/corpora/logging",
  "indices": [
    {
      "name": "logs-181998",
      "types": [
        {
          "name": "type",
          "mapping": "mappings.json",
          "documents": "documents-181998.json.bz2",
          "document-count": 2708746,
          "compressed-bytes": 13815456,
          "uncompressed-bytes": 363512754
        }
      ]
    },
    {
      "name": "logs-191998",
      "types": [
        {
          "name": "type",
          "mapping": "mappings.json",
          "documents": "documents-191998.json.bz2",
          "document-count": 9697882,
          "compressed-bytes": 49439633,
          "uncompressed-bytes": 1301732149
        }
      ]
    }
  ],
  "operations": [
    {{ rally.collect(parts="operations/*.json") }}
  ],
  "challenges": [
    {{ rally.collect(parts="challenges/*.json") }}
  ]
}

該 json 文件主要包含下面幾個部分:

  • description 和 short-description: track 的描述文字
  • data-url: 一個url地址,指明測試數(shù)據(jù)的下載根路徑,與下方 indices 中的 documents 結(jié)合,可得到數(shù)據(jù)的下載地址。
  • indices: 指定該track可以操作的索引,包括創(chuàng)建、更新、刪除等操作。詳細信息可以參見這里
  • operations: 指定具體的操作,比如 index 索引數(shù)據(jù)的操作、force-merge 強制合并segment的操作、search 搜索的操作等等。具體例子可以看下面的示例。詳細信息可以參見這里。
  • challenges: 通過組合 operations 定義一系列 task ,再組合成一個壓測的流程,請參照下方的 例子。詳細信息可以參見這里

operations/default.json 中的一個定義如下:

{
      "name": "index-append",
      "operation-type": "index",
      "bulk-size": 5000
}

其中 operation-type 包含 index、force-merge、index-stats、node-stats、search等,每一個operation-type都有自己的可定義參數(shù),比如 index 中可以通過指定 bulk-size 來決定批量寫入的文檔數(shù)。

challenges/default.json 中的一個定義如下:

 {
      "name": "append-no-conflicts",
      "description": "",
      "default": true,
      "index-settings": {
        "index.number_of_replicas": 0
      },
      "schedule": [
        {
          "operation": "index-append",
          "warmup-time-period": 240,
          "clients": 8
        },
        {
          "operation": "force-merge",
          "clients": 1
        },
        {
          "operation": "index-stats",
          "clients": 1,
          "warmup-iterations": 100,
          "iterations": 100,
          "target-throughput": 50
        },
        {
          "operation": "node-stats",
          "clients": 1,
          "warmup-iterations": 100,
          "iterations": 100,
          "target-throughput": 50
        },
        {
          "operation": "default",
          "clients": 1,
          "warmup-iterations": 100,
          "iterations": 500,
          "target-throughput": 10
        },
        {
          "operation": "term",
          "clients": 1,
          "warmup-iterations": 100,
          "iterations": 500,
          "target-throughput": 60
        },
        {
          "operation": "range",
          "clients": 1,
          "warmup-iterations": 100,
          "iterations": 200,
          "target-throughput": 2
        },
        {
          "operation": "hourly_agg",
          "clients": 1,
          "warmup-iterations": 100,
          "iterations": 100,
          "target-throughput": 0.2
        },
        {
          "operation": "scroll",
          "clients": 1,
          "warmup-iterations": 100,
          "iterations": 200,
          "target-throughput": 10
        }
      ]
    }

這里定義了一個名為 append-no-conflicts 的 challenge。由于每次壓測只能運行一個challenge,這里的 default 參數(shù)是指當壓測未指定時默認運行的 challenge。schedule 中指定了該 challenge 中按順序執(zhí)行 index-append、force-merge、index-stats、node-stats、default、term、range、hourly_agg、scroll 等 9 個task,其中每個 task 都指定了 一個 operation,除此之外還可以設(shè)定 clients (并發(fā)客戶端數(shù))、warmup-iterations(預熱的循環(huán)次數(shù))、iterations(operation 執(zhí)行的循環(huán)次數(shù))等,詳情請參見此處。

通過下面的命令可以查看當前 esrally 可用使用的track。

esrally list tracks

esrally 的 track 數(shù)據(jù)位于 rally 目錄(mac默認是 ~/.rally)中 benchmarks/tracks/ 下面。

car

car 是賽車的意思,這里是指不同配置的 es 實例。通過下面的命令可以查看 esrally 當前可用的 car。

esrally list cars

Name
----------
16gheap
1gheap
2gheap
4gheap
8gheap
defaults
ea
verbose_iw

cars 的配置位于 rally 目錄(mac默認是 ~/.rally)中 benchmarks/teams/default/cars/ 下面。具體配置可以參見 cars 的文檔,除了 heap 的配置,所有的 es 配置都可以修改。

race

race 是一次比賽的意思,這里是指某一次壓測。要比賽,就要有賽道和賽車,如果不指定賽車,就用 default 配置,如果不指定賽道,則默認使用 geonames track。通過下面的命令來執(zhí)行一次 race。

esrally race --track=logging --challenge=append-no-conflicts --car="4gheap"

上面的命令便是執(zhí)行一次壓測,并指定使用 logging 的track,運行該 track 中的 append-no-conflicts 的 challenge,指定的 car 為 4gheap 的 es 實例。詳情可以查看 race 相關(guān)文檔。

Tournament

tournament 是錦標賽的意思,是由多個 race 組成的。通過下面的命令可以查看所有的 race。

esrally list races

Recent races:

Race Timestamp    Track    Challenge            Car       User Tag
----------------  -------  -------------------  --------  ------------------------------
20160518T122341Z  pmc      append-no-conflicts  defaults  intention:reduce_alloc_1234
20160518T112057Z  pmc      append-no-conflicts  defaults  intention:baseline_github_1234
20160518T101957Z  pmc      append-no-conflicts  defaults

當有了多個 race 后,可以通過下面的命令方便地比較不同 race 之間的數(shù)據(jù)。

esrally compare --baseline=20160518T112057Z --contender=20160518T112341Z

兩次 race 的數(shù)據(jù)比較

詳細信息可以參見 tournament 的文檔。

Pipeline

Pipeline 在這里是指壓測的一個流程,通過下面的命令可以查看已有的pipeline。

esrally list pipeline

Name                     Description
-----------------------  ---------------------------------------------------------------------------------------------
from-sources-complete    Builds and provisions Elasticsearch, runs a benchmark and reports results.
from-sources-skip-build  Provisions Elasticsearch (skips the build), runs a benchmark and reports results.
from-distribution        Downloads an Elasticsearch distribution, provisions it, runs a benchmark and reports results.
benchmark-only           Assumes an already running Elasticsearch instance, runs a benchmark and reports results

  • from-sources-complete 是從源代碼編譯 es 后再運行,可以通過 --revision 參數(shù)指明要編譯的commit hash ,這樣就可以針對某一個提交版本就行測試了。
  • from-sources-skip-build 如果已經(jīng)編譯好了,使用該 pipeline,可以跳過編譯的流程,節(jié)省測試時間
  • from-distribution 通過 --distribution-version 指定 es 版本,esrally 會從官網(wǎng)直接下載該版本的可執(zhí)行文件,然后進行測試。
  • benchmark-only 此 pipeline 將 es 集群的管理交由用戶來處理, esrally 只做壓測。如果你想針對已有集群進行測試,那么要將pipeline設(shè)定為該模式。

詳細信息請參見 pipeline 的文檔。

壓測流程

esrally 的壓測流程主要分為以下三個步驟:

  1. 根據(jù)參數(shù)設(shè)定自行編譯或者下載 es 可執(zhí)行實例,然后根據(jù) car 的約定,創(chuàng)建并啟動 es 集群。如果使用 benchmark-only 的pipeline,則該步驟省略。
  2. 根據(jù)指定 track 去下載數(shù)據(jù),然后按照指定的 challenge 進行操作。
  3. 記錄并輸出壓測結(jié)果數(shù)據(jù)。

壓測結(jié)果分析

壓測結(jié)束后,esrally 會將結(jié)果輸出到終端和結(jié)果文件(位于 esrally 目錄logsbenchmarks/races)中,如下圖所示:

壓測結(jié)果

在 Metric 一欄,有非常多的指標數(shù)據(jù),詳細的解釋可以參見該文檔。一般要關(guān)注的數(shù)據(jù)有:

  • throughput 每個操作的吞吐量,比如 index、search等
  • latency 每個操作的響應時長數(shù)據(jù)
  • Heap used for x 記錄堆棧的使用情況

先搞懂每個 metric 的含義,然后根據(jù)自己的需求去確認自己要關(guān)注的指標。

每一次壓測都會以壓測時的時間命名,比如 logs/rally_out_20170822T082858Z.log ,這個日志便是記錄的 2017年8月22日 8:28:58開始的壓測日志。而在 benchmarks/races/2017-08-22-08-28-58 中記錄著最終的結(jié)果和 es 的運行日志。

另外對于 benchmark-only 模式的測試,即針對已有集群的壓力測試,也可以通過安裝 X-Pack Basic 版本進行監(jiān)控(Monitoring),在壓測的過程中就能查看相關(guān)指標。

X-Pack Monitoring

esrally 可以在配置的時候指定將所有的 race 壓測結(jié)果數(shù)據(jù)存入一個指定的 es 實例中,配置如下(在 esrally 目錄中 rally.ini 文件中):

[reporting]
datastore.type = elasticsearch
datastore.host = localhost
datastore.port = 9200
datastore.secure = False
datastore.user =
datastore.password =

esrally 會將數(shù)據(jù)存儲在如下 3 個index中,下面 * 代指月份,即按月存儲結(jié)果數(shù)據(jù)。

  • rally-metrics-* 該索引分指標記錄每次 race 的結(jié)果,如下圖所示為某一次race的所有 metric 數(shù)據(jù)。
Metric 數(shù)據(jù)

第一列時間是指某一次壓測的時間,第二列時間是指標采集的時間,第三列 operation 指具體執(zhí)行的操作,operation 為空的指標都是總計類的,比如indexing total time 記錄的是總索引數(shù)據(jù)的時間、segments_count 是總段數(shù)等等。其他的 operation 都記錄了每一個操作的數(shù)據(jù)。需要注意的是,這里記錄的是 operation 的所有采樣數(shù)據(jù),不是一個最終的匯總數(shù)據(jù)。上面截圖中也可以看出同一個 hour_agg 的operation 有多項名為 service_time 的指標數(shù)據(jù),但他們的采集時間是不同的?;谶@些數(shù)據(jù),我們可以做出某一次 race 中某個指標的可視化圖表,比如你想觀察本次 race 中 index-log 這個 task 的 throughput 指標數(shù)據(jù),便可以通過如下圖的方式實現(xiàn)。

metric 數(shù)據(jù)展示
  • rally-result-* 該索引分指標記錄了每次 race 的最終匯總結(jié)果,比如下面這條數(shù)據(jù)。
{
   "user-tag": "shardSizeTest:size6",
   "distribution-major-version": 5,
   "environment": "local",
   "car": "external",
   "plugins": [
     "x-pack"
   ],
   "track": "logging",
   "active": true,
   "distribution-version": "5.5.2",
   "node-count": 1,
   "value": {
     "50_0": 19.147876358032228,
     "90_0": 21.03116340637207,
     "99_0": 41.644479789733886,
     "100_0": 47.20634460449219
   },
   "operation": "term",
   "challenge": "default-index",
   "trial-timestamp": "20170831T063724Z",
   "name": "latency"
 }

這個記錄了 term operation 的 latency 指標數(shù)據(jù),匯總值以 percentile(百分位數(shù)) 的形式展示?;谠摂?shù)據(jù),我們可以繪制針對某個指標的多race對比,比如下圖便是對比多 race 之間 hourly_agg(按小時做聚合)、default(match_all 查詢)、term(term查詢)、range(range查詢)的latency(延遲時間)對比。

多次 race 的 latency 對比
  • rally-races-* 該索引記錄了所有 race 的最終結(jié)果,即命令行執(zhí)行的輸出結(jié)果。

    除了es相關(guān)指標數(shù)據(jù)外,esrally 還會同時記錄測試的一些環(huán)境信息,比如操作系統(tǒng)、JVM等等,你可以方便的查看本次測試的軟硬件環(huán)境。

實戰(zhàn)

終于到了開賽的時候,下面我們采用問答的形式來進行,希望大家看到問題后先自己思考下再看答案。

問題一

提問:如何對比 5.5.0 相比 2.4.6 的性能改進?

回答:

分別針對 5.5.0 和 2.4.6 做一次壓測,然后比較兩者兩者的相關(guān)指標即可,這里我們的 track 和 challenge 如下:

  • track: nyc_taxis
  • challenge: append-no-conflicts

測試步驟如下:

  1. 測試 2.4.6 的性能

esrally race --distribution-version=2.4.6 --track=nyc_taxis --challenge=append-no-conflicts --user-tag="version:2.4.6"

  1. 測試 5.5.0 的性能

esrally race --distribution-version=5.5.0 --track=nyc_taxis --challenge=append-no-conflicts --user-tag="version:5.5.0"

  1. 對比兩次 race 的結(jié)果

esrally list races

esrally compare --baseline=[2.4.6 race] --contender=[5.5.0 race]

Tips:
--user-tag 用于為 race 打標簽,方便后續(xù)查找
如果只是試一下,可以加上 --test-mode ,用測試數(shù)據(jù)來跑,很快。

問題二

提問:如何測試 _all 關(guān)閉后對于寫性能的影響?

回答:

針對 5.5.0 版本的 es 做兩次測試,第一次開啟 _all,第二次關(guān)閉 _all,對比兩次的結(jié)果,由于只測試寫性能,所以我們只需要 index 類型的 operation執(zhí)行。這里我們的 track 和 challenge 如下:

  • track: nyc_taxis
  • challenge: append-no-conflicts

測試步驟如下:

  1. 默認 nyc_taxis 的 mapping 設(shè)置是將 _all 關(guān)閉的,直接測試 _all 關(guān)閉時的性能。

esrally race --distribution-version=5.5.0 --track=nyc_taxis --challenge=append-no-conflicts --user-tag="enableAll:false" --include-tasks="type:index"

  1. 修改 nyc_taxis 的 mapping 設(shè)置,打開 _all。mapping 文件位于 rally 主目錄 benchmarks/tracks/default/nyc_taxis/mappings.json,修改 _all.enabled 為 true。

esrally race --distribution-version=5.5.0 --track=nyc_taxis --challenge=append-no-conflicts --user-tag="enableAll:true" --include-tasks="type:index"

  1. 對比兩次 race 的結(jié)果

esrally list races

esrally compare --baseline=[enableAll race] --contender=[disableAll race]

下圖是我在 --test-mode 模式下運行的對比結(jié)果,也可以看出關(guān)閉 _all 可以提升寫性能。

測試結(jié)果

Tips:
--include-tasks 用于只運行 challenge 中的部分 task

問題三

提問:如何測試已有集群的性能?

回答:

使用 benchmark-only 的 pipeline 即可,這里我們的 track 和 challenge 如下:

  • track: nyc_taxis
  • challenge: append-no-conflicts

測試步驟如下:

  1. 執(zhí)行下方命令即可測試已有集群

esrally race --pipeline=benchmark-only --target-hosts=127.0.0.1:9200 --cluster-health=yellow --track=nyc_taxis --challenge=append-no-conflicts

Tips:
--cluster-health=yellow 默認 esrally 會檢查集群狀態(tài),非 green 狀態(tài)會直接退出。添加該參數(shù)可以避免該情況

希望這三個問答可以幫助到大家快速掌握 esrally 的用法。

進階

自定義 car

前面講解 car 的時候,我們提到 esrally 已經(jīng)自帶了一些可用的 es 配置,但是如果這些還不能滿足你的時候,可以通過下面兩個方案解決。

  1. 定制自己的car
    car 的配置文件位于 esrally 目錄 benchmarks/teams/default/cars,在這里新增一個自己的 car 配置文件就可以了。這里就不贅述了,感興趣的可以查閱 car 的文檔。

  2. 自己搭建集群
    最簡單的方式是脫離 esrally 的管理,自行搭建集群,這樣想怎么配置就怎么配置了。

自定義 track

雖然 esrally 自帶了很多 track,而且這些數(shù)據(jù)本身也不小,簡單列在下面:

Track 壓縮數(shù)據(jù)大小 解壓數(shù)據(jù)大小 文檔數(shù)
geonames 252 MB 3.3 GB 11396505
geopoint 482 MB 2.3 GB 60844404
logging 1.2 GB 31 GB 247249096
nested 663 MB 3.3 GB 11203029
noaa 947 MB 9 GB 33659481
nyc_taxis 4.5 GB 74 GB 165346692
percolator 103KB 105 MB 2000000
pmc 5.5 GB 22 GB 574199

這些數(shù)據(jù)文件位于 esrally 目錄 benchmarks/data 下面。不同的 Track 有不同的測試目的,詳情可以去該 github repo 下面去查看。

當我們做定向測試的時候,還是希望針對自己的數(shù)據(jù)進行壓測,此時可以自定義 track。操作也很簡單,詳情可以參考官方文檔。這里簡單列一下操作步驟。

  1. 在 上文提到的 data 目錄中創(chuàng)建自己的數(shù)據(jù)目錄。
  2. 準備壓測數(shù)據(jù)文件。 esrally 使用的是一個json文件,其實是一個一個 json object。
  3. 將準備好的數(shù)據(jù)文件壓縮成 bz2 格式,然后復制到步驟 1 創(chuàng)建的目錄中去。
  4. 新增自定義的track??梢灾苯訌椭?geoname 目錄,然后修改相關(guān)的配置文件,將測試數(shù)據(jù)與 track 綁定。
  5. 添加完后,通過 esrally list rack 就可以看到自定義的 track。

分布式壓測

esrally 還支持分布式壓測,即如果一個節(jié)點的 esrally 無法達到要求的并發(fā)數(shù)、請求數(shù),那么可以將 esrally 分布到多臺機器上去同時執(zhí)行。分布式壓測文檔在這里,此處用到了 esrally dameon,對應命令是 esrallyd 。簡單講就是 esrally 通過 esrallyd 將多臺機器組合成一個集群,然后 esrally 在執(zhí)行測試任務的時候通過制定 --load-driver-hosts 便可以將測試任務分發(fā)到對應的機器上執(zhí)行。這里便不贅述了,感興趣的去看前面提到的文檔。

最后一個問題

讓我們回到開頭提到的容量規(guī)劃的問題吧!

提問:一個 index 的 shard 數(shù)該如何確認?

回答:

其實針對這個提問,還可以再問下面兩個問題。

  1. shard 設(shè)置過少是否有問題?比如一直都采用默認的 5個分片
  2. shard 設(shè)置過多是否有問題?比如直接設(shè)置為100個分片

要回到這兩個問題,我們得先知道 shard 的作用。shard 是 es 實現(xiàn)分布式特性的基石,文檔在索引進 es 時,es 會根據(jù)一個路由算法,將每一個文檔分配到對應的 shard 上。每個 shard 實際對應一個 lucene index。那么每個 shard 能存儲的文檔數(shù)是否有上限呢?答案是有!每個shard最多存儲 2^31 個文檔,即 20億。這是 lucene 設(shè)計決定的。那是不是只要我的文檔數(shù)沒有超過20億,就可以只用一個或者很少的shard 呢?不盡然。因為隨著 shard 體積的增大,其查詢效率會下降,而且數(shù)據(jù)遷移和恢復的成本也會增高。官方建議單個 shard 大小不要超過 50GB,可以參見討論一討論二

現(xiàn)在回答上面的兩個問題。
shard數(shù)過小不一定好,如果數(shù)據(jù)量很大,導致每個 shard 體積過大,會影響查詢性能。
shard數(shù)過大也不一定好,因為 es 的每次查詢是要分發(fā)給所有的 shard 來查詢,然后再對結(jié)果做聚合處理,如果 shard 數(shù)過多也會影響查詢性能。因此 shard 的數(shù)量需要根據(jù)自己的情況測出來。

官方文檔有一節(jié)關(guān)于容量規(guī)劃的章節(jié),建議大家去看一下,鏈接在這里,其給出的步驟如下:

  1. 使用生產(chǎn)環(huán)境的硬件配置創(chuàng)建單節(jié)點集群
  2. 創(chuàng)建一個只有一個主分片無副本的索引,設(shè)置相關(guān)的mapping信息
  3. 將真實的文檔導入到步驟 2 的索引中
  4. 測試實際會用到的查詢語句

測試的過程中,關(guān)注相關(guān)指標數(shù)據(jù),比如索引性能、查詢性能,如果在某一個點相關(guān)性能數(shù)據(jù)超出了你的預期值,那么此時的 shard size大小便是符合你預期的單個 shard size的大小。接下來通過下面這個簡單的計算公式便大致能確定一個 index 需要設(shè)定的 shard 數(shù)了。

shard數(shù) = index 的數(shù)據(jù)總大小/單個shard size的極限值

比如你測出單個 shard size 最大為 20 GB,而你預測該索引數(shù)據(jù)最大量在1年或者2年內(nèi)不會超過 200GB,那么你的 shard 數(shù)就可以設(shè)置為10。

接下來要做的事情也很明確,我們要用 esrally 完成上面的壓測步驟:

  1. 自行維護 es 節(jié)點的創(chuàng)建和運行,esrally 運行的時候采用 benchmark-only 模式.

  2. 自定義 track,這里有以下兩個重點:

    • 生成真實數(shù)據(jù)。如果你的數(shù)據(jù)無法生成很多,那么可以在 track 的 schedule 中設(shè)置 iterations 參數(shù),即循環(huán)進行同一個操作,這樣也可以測試大數(shù)據(jù)量的寫性能。
    • 定義自己的查詢?nèi)蝿?。?track 的 operations 中是可以定義自己的查詢語句的,比如下面這個
    {
      "name": "hourly_agg",
      "operation-type": "search",
      "index": "logs-*",
      "type": "type",
      "body": {
        "size": 0,
        "aggs": {
          "by_hour": {
            "date_histogram": {
              "field": "@timestamp",
              "interval": "hour"
            }
          }
        }
      }
    }
    

    其中的 body 便是自定義的查詢語句,所以你可以通過自己的需求來設(shè)定查詢語句,以貼近實際使用的情況。

  1. 還要記得設(shè)置索引的 mapping 與線上一致,比如是否啟用 _all 等設(shè)置。
  2. 基于自定義的track來進行壓測即可。要注意的是運行 esrally 的機器要和 es 機器分開,防止對 es 性能產(chǎn)生干擾。

Tips:
esrally 默認在每次壓測是會刪除已有的索引后再重新創(chuàng)建索引,如果你不想這樣,可以在每個 index 的配置中設(shè)置 auto-managed 為 false,具體文檔在這里。
通過這個參數(shù),你就可以單獨壓測查詢性能了,而不用每次都要先經(jīng)過漫長的導入數(shù)據(jù)的過程。

總結(jié)

esrally 針對 es 的壓測設(shè)計了一套完備的基于配置文件的測試流程,極大地簡化了操作難度,并且提供了可重復驗證的方式。對國內(nèi)用戶來講,我認為最大的難處還是在于 esrally 自帶的 track 文件太大,從 國外 aws 下載很慢。好在可以自定義 track,不必完全依賴自帶的 track。

其他沒啥好說的,esrally 棒棒噠,大家趕緊去試試吧,如果有問題歡迎來討論!

參考資料

  1. esrally 官方文檔
  2. Using Rally to benchmark Elasticsearch queries
  3. esrally 作者的演講視頻
  4. Benchmarking Elasticsearch for your use case with Rally
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容