NoSQL性能測試工具YCSB-Running a Workload

寫在前面

目前,在系統設計中引入了愈來愈多的NoSQL產品,例如Redis/ MongoDB/ HBase等,其中性能指標每每會成爲權衡不一樣NoSQL產品的關鍵因素。對這些產品在性能表現和產品選擇上的爭論,Ivan碰到不止一次。雖然經過對系統架構原理方面的分析能夠大體判斷出其在不一樣讀寫場景下的表現,但一是對受衆有較高的要求,也來的不那麼直接。這時候,沒有什麼比一次性能測試更有說服力。有什麼好的性能測試工具呢?這就是今天的主角YCSB。YCSB是Yahoo開源的一套分佈式性能測試工具,方便易用,拓展性強。Ivan最近研究HBase二級索引時用它來作性能測試,感受仍是很是順手的。雖然網上已經有不少YCSB的介紹文章,但用來指導實際操做仍是有些不便。Ivan會用兩三篇文章來介紹一下YCSB的實際使用。本文是官方文章的譯文,選擇這篇文章是由於其與具體操做的關係比較緊密,感興趣的同窗能夠了解一下。java

原文地址:https://github.com/brianfrankcooper/YCSB/wiki/Running-a-Workloadgit

正文

運行workload有六個步驟github

  1. 安裝待測試的數據庫系統
  2. 選擇適當的DB接口層
  3. 選擇適當的工做負載
  4. 選擇適當的運行參數(客戶端線程數量,目標吞吐等)
  5. 加載數據
  6. 執行工做負載(workload)

這些步驟描述都假定你運行一個單客戶端。這能夠知足中小規模集羣(10臺左右)的測試須要。對於更大規模的集羣,你必須在不一樣的服務器上運行多個客戶端來生成足夠的負載。相似地,在某些場景下,多客戶機加載數據庫可能更快。多客戶端並行運行的更多細節,能夠查看Running a Workload in Parallelshell

Setp 1.安裝待測試的數據庫

第一步是安裝你但願測試的數據庫。多是單機或者集羣,依賴於你要測試的配置。
你必須create 或 set up tables/keyspaces/storage buckkets用於存儲記錄。這些細節對於每一個數據庫都不一樣,依賴於但願運行的負載狀況。在YCSB客戶端運行前,數據表必須被建立,由於客戶端自身是不會請求建立數據庫表的。這是由於對於某些系統建立表一個手工操做,而對於其餘系統,表必須在集羣啓動前被建立。
workload所依賴的table必須被建立。對於核心負載,YCSB客戶端將假定存在一個名爲'usertable'的table,且具備靈活的schema:運行時能夠根據須要增長列。'usertable'能夠被映射爲適當的存儲容器。例如,在MySQL中,你能夠create table,在Cassandra你能夠在配置中定義keyspace。數據庫接口層(Step 2描述)會收到讀寫usertable的請求,將其轉換爲你所指定的實際存儲的請求。這意味着你必須提供數據庫接口層幫助它理解下層存儲的結構。例如,在Cassandra中,你必須定義在keyspace中定義列族column families。這樣,必須建立一個列族並命名(例如,你可使用values)。而後,數據庫訪問層須要理解指向values列族,或者將字符串「values」設置爲一個屬性,或者在數據庫接口層中硬編碼。數據庫

Step 2. 選擇適當的數據庫接口層

數據庫接口層是一個可執行的java類,實現read、write、update、delete和scan調用,它由YCSB客戶端生成,調用你的數據庫API。這個類是com.yahoo.ycsb包下抽象類DB的子類。在運行YCSB客戶端時,你要經過命令行指定類名,客戶端會動態加載你的接口類。命令行中指定的任何屬性或指定的參數文件,將會傳遞給數據庫接口層實例,用於配置該層(例如,告訴它你要測試的數據庫主機名hostname)服務器

YCSB客戶端自帶一個簡單的虛擬接口層,com.yahoo.ycsb.BasicDB。這層會把執行的操做經過System.out打印。這能夠用於確認客戶端在正常運行,用於debug 你的workload。網絡

如何使用YCSB客戶端的細節能夠查看 Using the Database Libraries。更多實現數據庫接口層的細節,能夠查看 Adding a Database架構

你可使用YCSB命令,直接運行數據庫命令。客戶端使用DB接口層發送命令給數據庫。你可使用客戶端肯定DB層運行正常,你的數據庫正確安裝,DB層能夠鏈接到數據庫等等。它爲大量的數據庫提供了命令行接口,能夠用於檢驗數據庫的數據。運行命令行:分佈式

$ ./bin/ycsb shell basic
help
Commands:
  read key [field1 field2 ...] - Read a record
  scan key recordcount [field1 field2 ...] - Scan starting at key
  insert key name1=value1 [name2=value2 ...] - Insert a new record
  update key name1=value1 [name2=value2 ...] - Update a record
  delete key - Delete a record
  table [tablename] - Get or [set] the name of the table
  quit - Quit

Step 3 選擇適當的工做負載

工做負載定義了在loading階段將被加載進數據庫的數據,在transaction階段在數據集上執行的操做。
典型的工做負載包括如下內容:工具

  • Workload java class(com.yahoo.ycsb.Workload的子類)

  • Parameter file(Java Properties格式)

由於數據集的參數屬性必須在兩個階段被得到,在loading階段用於構造和插入適當類型的記錄,在transaction階段用於指定正確的記錄id和field,因此參數文件在兩個階段都會使用。workload java class使用這些屬性插入記錄(loading phase)或操做那些記錄(transaction phase)。選擇哪一個階段要看你運行YCSB命令行時指定的參數。

在運行YCSB客戶端的命令行時,你能夠指定java class和參數文件。客戶端將動態加載你的workload class,從參數文件解析參數(和任何命令行的附加參數)並執行workload。在loading和transaction兩個階段,須要一樣的屬性和workload邏輯應用。例如,若是loading階段建立10個field的記錄,然後在transaction階段必須知道有10個field能夠被查詢和修改。

YCSB自帶的CoreWorkload 是標準workload包能夠直接使用。CoreWorkload定義了簡單的read/insert/update/scan操做組合。在參數文件中定義了每種操做的相應頻率,以及其餘workload屬性。這樣,修改參數文件能夠執行不一樣的workload。更多CoreWorkload的細節,能夠查看Core Workloads

若是CoreWorkload不能知足你的需求,你能夠基於com.yahoo.ycsb.Workload定義本身的workload子類。細節能夠查看 Implementing New Workloads

Step 4 選擇適當的運行參數

雖然workload class和參數文件定義了具體的workload,還有一些在運行特定測試時,你可能但願指定附加的設置。這些設置能夠經過YCSB客戶端命令行實現。設置包括

  • -threads: 客戶端線程數量。默認,YCSB客戶端使用一個worker線程,但能夠指定。這一般用來根據數據庫增長負載數量。
  • -target:每秒操做目標數量。默認,YCSB客戶端會嘗試儘量多的操做。例如,每一個操做平均花費100ms,客戶端將在每一個線程中每秒執行10個操做。然而,你能夠限流每秒操做的數量。例如,產生一個延遲與吞吐量的曲線,你能夠嘗試不一樣的目標吞吐量,衡量每次產生的延遲。
  • -s :status. 對於一個長時間運行的workload,它是有用的,能夠得到客戶端狀態報告,判斷他是否崩潰並給你一些過程當中的信息。經過命令行指定"-s",客戶端能夠每10秒報告狀態到stderr。

Step 5. 加載數據

Workload有兩個執行階段:loading階段(定義待插入的數據)和transaction階段(定義數據集上的操做)。爲了加載數據,你要運行YCSB客戶端並告訴它執行loading階段。
例如,考慮workload A的benchmark(更多標準workloads細節在Core Workloads)。加載標準數據集

$ ./bin/ycsb load basic -P workloads/workloada

這個命令的關注點

  • load 參數告訴客戶端執行loading 階段

  • basic 參數告訴客戶端使用BasicDB層。你能夠在參數文件中指定這個屬性,使用'db'屬性(例如db=com.yahoo.ycsb.BasicDB)
    -P參數用來加載property文件。這個例子中,咱們用來加載workload參數文件。

    加載HBase數據集:

$ ./bin/ycsb load hbase -P workloads/workloada -p columnfamily=family

這個命令的關注點

  • load 參數是告訴Client執行loading階段操做。
  • hbase 參數是告訴Client使用HBase layer
  • -P 參數是用來加載參數文件,例子中咱們用來加載workload參數文件
  • -p 參數用於設置參數,在這個HBase例子中,咱們用來設置數據庫的列。你數據庫中存在usertable帶有family列,以執行這個命令。然後全部數據被加載到數據庫 usertable 帶有family列。
  • 執行命令前,肯定你已經啓動了 Hadoop和 HBase

若是你使用BasicDB,你將看到數據庫的insert語句。若是是你用一個實際的DB接口層,記錄會被加載到數據庫中。

標準workload參數文件建立很小的數據庫,例如,workload僅建立1000條記錄。這用於調試你的安裝。然而,運行一個實際的benchmark你須要建立一個更大的數據庫。例如,想象你須要加載100百萬記錄。而後,你須要修改workload文件中默認的「recordcount」屬性。有兩個辦法實現。

指定一個新的屬性文件,包含recordcount的新值。在命令行中,若是這個文件在workload文件後被指定,它會覆蓋workload的任何屬性。例如建立"large.dat"文件,僅有一行內容

recordcount=100000000

而後,client執行如下內容

$ ./bin/ycsb load basic -P workloads/workloada -P large.dat

Client會加載全部的屬性文件,但使用最後加載的一個文件large.dat中的recordcount值,

經過命令行指定recordcount屬性的新值。在命令行指定的任何屬性都會覆蓋配置文件中的屬性。以下執行

$ ./bin/ycsb load basic -P workloads/workloada -p recordcount=100000000

通常來講,好的實踐是在新的參數文件中存儲任何重要的參數,代替經過命令行指定它們。這使得你的benchmark結果能夠被複現。不用必須重建你使用的命令行,你重用參數文件便可。注意,當它開始執行時,YCSB Client會打印處他的命令行,因此若是你將Client的輸出存儲到一個數據文件,你能夠很容易從新執行命令行。
由於一個大數據庫加載須要很長時間,你可能但願1.須要Client輸出狀態,2.直接將輸出寫入數據文件。這樣,你能夠執行如下命令加載數據庫。

$ ./bin/ycsb load basic -P workloads/workloada -P large.dat -s > load.dat

-s 參數將要求Client向stderr輸出狀態報告。這樣命令行的輸出多是這樣

$ ./bin/ycsb load basic -P workloads/workloada -P large.dat -s > load.dat
Loading workload... (might take a few minutes in some cases for large data sets)
Starting test.
0 sec: 0 operations
10 sec: 61731 operations; 6170.6317473010795 operations/sec
20 sec: 129054 operations; 6450.76477056883 operations/sec
...

這個狀態輸出會幫助你看到加載操做執行得多快(這樣你能夠估計加載的完成時間),確認load正在執行。當load完成時,Client會報告load的性能統計數據。這些統計與transaction階段同樣,因此看後續介紹

Step 6 執行workload

一旦數據被加載,你就能夠執行workload。告訴Client執行transaction操做。執行workload,可使用如下命令

$ ./bin/ycsb run basic -P workloads/workloada -P large.dat -s > transactions.dat

主要差異是咱們使用run參數時,告訴Client執行transaction階段而不是loading階段。若是你使用BasicDB,檢查結果文件 transactions.dat,你會看到一個read和update混合的請求,與統計數據一致。

典型狀況下,你會但願使用 -threads 和 -target 參數控制負荷量。例如,你可能但願10個線程每秒總數100個操做。平均操做延時不高於100ms,每一個線程可以攜帶每秒10此操做。通常來講,你須要足夠的線程由於沒有線程嘗試每秒更多的操做,不然你達到的吞吐量將小於指定的目標吞吐量。
這個例子,咱們能夠執行

$ ./bin/ycsb run basic -P workloads/workloada -P large.dat -s -threads 10 -target 100 > transactions.dat

注意這個例子,咱們使用 -threads 10 命令參數指定10個線程, -target 100 命令參數指定每秒100次操做。不然,兩個值能夠設置在你的參數文件中,使用threadcount 和 target 屬性代替。例如

threadcount=10
target=100

run的結尾,Client會向stdout報告性能統計數據。上面的例子,統計數據會寫入transaction.dat文件。默認包括每一個操做類型延時的average,min,max,95th,99th。每次操做返回代碼的統計,每類操做的直方圖。返回值被你的DB接口層定義,容許你看到workload過程當中的任何錯誤。上述例子中,咱們能夠獲得輸出:

[OVERALL],RunTime(ms), 10110
[OVERALL],Throughput(ops/sec), 98.91196834817013
[UPDATE], Operations, 491
[UPDATE], AverageLatency(ms), 0.054989816700611
[UPDATE], MinLatency(ms), 0
[UPDATE], MaxLatency(ms), 1
[UPDATE], 95thPercentileLatency(ms), 1
[UPDATE], 99thPercentileLatency(ms), 1
[UPDATE], Return=0, 491
[UPDATE], 0, 464
[UPDATE], 1, 27
[UPDATE], 2, 0
[UPDATE], 3, 0
[UPDATE], 4, 0
...

這個輸出指標

  • 整體執行時間爲10.11秒

  • 平均吞吐量98.9 ops(全部線程)
  • 491次修改操做,附帶average,min,max,95th,99th %延遲狀況
  • 全部491次修改操做都返回0(成功)
  • 464次操做在1ms內完成,27次在1至2ms內完成。

讀操做有與之接近的統計數值

延時信息的直方圖一般是有用的,時序圖的形式有時更有用。請求一個時序,須要在Client命令行或在屬性文件指定"measureenttype=timeseries"屬性。默認狀況下,Client會每間隔1000ms,報告一次平均延時。你能夠對報告指定不一樣的間隔粒度,使用 timeseries.granularity屬性,例如。

$ ./bin/ycsb run basic -P workloads/workloada -P large.dat -s -threads 10 -target 100 -p \measurementtype=timeseries -p timeseries.granularity=2000 > transactions.dat

將會報告一個時序,間隔2000ms讀一次,結果將是。

[OVERALL],RunTime(ms), 10077
[OVERALL],Throughput(ops/sec), 9923.58836955443
[UPDATE], Operations, 50396
[UPDATE], AverageLatency(ms), 0.04339630129375347
[UPDATE], MinLatency(ms), 0
[UPDATE], MaxLatency(ms), 338
[UPDATE], Return=0, 50396
[UPDATE], 0, 0.10264765784114054
[UPDATE], 2000, 0.026989343690867442
[UPDATE], 4000, 0.0352882703777336
[UPDATE], 6000, 0.004238958990536277
[UPDATE], 8000, 0.052813085033008175
[UPDATE], 10000, 0.0
[READ], Operations, 49604
[READ], AverageLatency(ms), 0.038242883638416256
[READ], MinLatency(ms), 0
[READ], MaxLatency(ms), 230
[READ], Return=0, 49604
[READ], 0, 0.08997245741099663
[READ], 2000, 0.02207505518763797
[READ], 4000, 0.03188493260913297
[READ], 6000, 0.004869141813755326
[READ], 8000, 0.04355329949238579
[READ], 10000, 0.005405405405405406

這個輸出分開顯示了update和read操做的時間序列,每2000ms的數據。數據報告的時點是僅包括前一個2000ms的均值。(這個例子,咱們作了100,000次操做,目標是每秒10,000次操做)。一個關於延時度量的關注點:Client度量,特定操做對數據庫的端到端的執行延時。那樣,它在調用DB接口層class適當方法前會啓動啓動一個時鐘,方法返回時會中止時鐘。延時包括:執行包括接口層,到數據庫服務器的網絡延遲,數據庫的執行時間。不包括用於控制吞吐量的延遲。就是說,若是你指定目標是每秒10次操做(單線程)Client會在每100ms僅執行1次操做。若是操做耗費了12ms,Client會在下一次操做前額外等待88ms。然而,報告延時不會包括這個等待時間,報告會顯示延遲是12ms而不是100.

相關文章
相關標籤/搜索