(9)異步Mongo驅動的性能測試——響應式Spring的道法術器

本系列文章索引《響應式Spring的道法術器》
前情提要 Spring WebFlux快速上手 | Spring WebFlux性能測試 | Spring WebClient性能測試
本文源碼react

1.4.4 同步與異步數據庫驅動的性能對比

許多數據庫已陸續推出官方的異步驅動,在Spring Data Reactive中,已經集成了Mongo、Casandra、Redis、CouchDB的異步驅動。git

在Spring WebFlux中使用 Reactive Mongo的示例見Spring WebFlux快速上手github

這一節咱們經過使用YSCB對MongoDB的同步和異步驅動的性能基準測試,來觀察異步驅動的優點。mongodb

YCSB(Yahoo! Cloud Serving Benchmark)是雅虎開源的一款用於測試各種雲服務/NoSQL/鍵值對存儲的性能基準測試工具。YCSB很贊,使用起來很簡單,咱們就按照wiki介紹來操做便可。shell

1)準備YCSB數據庫

若是使用Windows,請參考這裏來預先安裝必要的軟件和工具。bash

獲取YCSB有兩種方式,一種是直接下載壓縮包:網絡

curl -O --location https://github.com/brianfrankcooper/YCSB/releases/download/0.12.0/ycsb-0.12.0.tar.gz
tar xfvz ycsb-0.12.0.tar.gz
cd ycsb-0.12.0

另外一種是基於源碼構建:session

git clone git://github.com/brianfrankcooper/YCSB.git
cd YCSB
mvn clean package

此時就可使用bin/ycsb命令來進行性能測試了,運行一下:多線程

usage: bin/ycsb command databse [options]

Commands:
    load        Execute the load phase
    run         Execute the transaction phase
    shell       Interactive mode

...

從上邊的命令幫助能夠看到,咱們能夠運行三種命令:

  • load,執行數據加載,也就是向數據庫保存數據;
  • run,執行事務,好比更新、查詢等;
  • shell,能夠交互式地運行測試。

本節的測試主要用到load和run來進行數據的批量操做,先用load命令加載數據集,而後使用run命令測試數據操做。在YCSB中,測試的工做量由workload文件來定義。咱們看到在workloads下有workload[a-f]幾個配置文件,好比workloada:

# Yahoo! Cloud System Benchmark
# Workload A: Update heavy workload
#   Application example: Session store recording recent actions
#                        
#   Read/update ratio: 50/50
#   Default data size: 1 KB records (10 fields, 100 bytes each, plus key)
#   Request distribution: zipfian

recordcount=1000
operationcount=1000
workload=com.yahoo.ycsb.workloads.CoreWorkload

readallfields=true

readproportion=0.5
updateproportion=0.5
scanproportion=0
insertproportion=0

requestdistribution=zipfian

可見配置文件定義了記錄條數、操做次數、以及不一樣的操做所佔的百分比。好比上邊readproportionupdateproportion都是50%,從註釋也能夠看出來,這模擬的是一種更新操做比較頻繁的場景,能夠模擬Web應用中保存session的場景。

幾個workload的配置經過不一樣的read/update/scan/insert操做比例來模擬不一樣的場景。

咱們能夠經過以下命令對mongo運行基於workloada的load階段的性能測試:

bin/ycsb load mongodb -P workloads/workloada

默認是鏈接localhost:27017的mongodb數據庫,若是但願指定數據庫鏈接信息,能夠用-p參數指定:

bin/ycsb load mongodb -P workloads/workloada \
-p "mongodb.url=mongodb://192.168.0.101:27017/ycsb?w=1&maxPoolSize=32&waitQueueMultiple=20"

同時還指定了鏈接池最大數量和最多等待數量。

固然咱們也能夠經過命令參數覆蓋workloada文件中的數值,好比:

bin/ycsb load mongodb -P workloads/workloada \
-p "mongodb.url=mongodb://192.168.0.101/ycsb?w=1&maxPoolSize=32&waitQueueMultiple=20"  \
-p recordcount=10000 -p operationcount=10000 -threads 20

此外,還用-threads指定了併發線程數爲20。

以上這些是本次測試會用到的內容,其餘更多關於YCSB的使用請參考wiki吧。

2)準備測試

本次測試的目標是對比Mongodb同步和異步驅動的性能,簡單起見,從吞吐量平均操做時長兩個數據來衡量。縱向上,

  • 比較不一樣數量的併發線程對兩個數據的影響;
  • 觀察測試時的鏈接數變化。

鏈接數的變化能夠經過mongostat命令來觀察,以下圖所示:

title

上邊運行的mongo-benchmark.sh是基於bin/ycsb命令編寫的方便測試的腳本,並輸出一些彙總數據(包括吞吐量和平局操做時長)方便查看,同時也會將每次bin/ycsb命令輸出的詳細內容保存到output目錄下的文件中。
腳本能夠在代碼庫中找到,若是mongo運行於localhost:27017,可直接用以下命令執行(在與bin同目錄下):

curl https://raw.githubusercontent.com/get-set/get-reactive/master/ycsb-mongo-shell/mongo-benchmark.sh | bash

圖中上方是對同步驅動和異步驅動各自跑了一次基於workloada的load和run的測試,下方是mongostat的輸出(每秒輸出一行),從insertqueryupdate的數字能夠找出四個橘×××的框標出的4個階段。經過這些數據咱們能夠分析出:

  • load主要是加載數據集,所以會看到insert的數字增多,加起來是測試預設的30000條數據;相似的run主要是進行基於workload的操做測試,workloada是50/50的read/update,在mongostat的輸出中也有體現。
  • load階段同步和異步驅動的吞吐量分別爲19801和25554,run階段同步和異步的吞吐量分別爲25706和27675,同步驅動略遜一籌;再觀察insert、read和update操做的平均時長,能夠得出一樣的結論。
  • 此次測試設置了20個線程對mongo數據庫進行操做,在mongostat輸出的conn列能夠看到數據庫鏈接個數的變化,對於同步的驅動來講,鏈接個數會從4個增長到25個,而對於異步的驅動來講,鏈接個數會從4個增長到7個。

經過這種方式,針對不一樣的線程數,觀察兩種驅動的性能數據並經過mongostat的數據記錄鏈接數。

1、不限制鏈接數

爲了觀察鏈接數的變化,先不限制maxPoolSize(註釋腳本中MAX_POOL_SIZE=8那一行)。最終結果以下:

title

圖中,每種顏色的左列和右列分別是同步和異步的數據。直觀起見,咱們經過圖表來對比一下:

首先對比一下load階段和run階段的吞吐量(柱越高越好)

title

title

能夠發現,當線程數達到8個以後,吞吐量的增加趨勢基本消失了,尤爲是同步驅動的吞吐量還會隨線程數的繼續增長而略有降低。不知是否跟測試環境爲四核八線程的CPU有關係。

而後對比一下INSERT、READ和UPDATE操做的平均時長(柱越低越好)

title

title

title

相對來講,異步驅動能帶來更快的讀寫操做,尤爲是應對愈來愈多的線程的時候。

最後對比一下鏈接數

鏈接數的對比更加明顯:對於同步的狀況,鏈接數=線程數+5;而對於異步的狀況,鏈接數幾乎一直保持在7個。沒有對比就沒有傷害呀。

2、限制鏈接數

下面,將鏈接數限制爲32個,測試一下線程數從30-80的狀況下,同步驅動的性能數據:

title

經過圖表對比:

title

title

title

title

title

可見,限制鏈接數以後,略有改善,可是相比異步驅動來講,仍然有必定差距。

3)結論

首先,須要說明的是,以上並不是是以數據庫調優爲目的的測試,這裏咱們只測試了workloada(若是你感興趣能夠將腳本中的WORKLOAD變量修改一下,而後測試其餘場景),並且限制鏈接數爲32並無特別的依據,對測試的機器來講,32也並不是最優的鏈接數。

經過本節的測試,針對MongoDB驅動咱們能夠得出如下兩個結論:

  • 相對於同步驅動來講,異步驅動在性能方面略勝一籌;
  • 在應對大量客戶端線程的狀況下,異步驅動可以以少許而穩定的鏈接數應對,意味着更少的內存消耗(每一個鏈接消耗stack size的內存空間,默認狀況下stack size爲10M)。

1.4.4 總結

上邊咱們分別針對Http服務端Http客戶端以及數據庫進行了同步和異步的測試對比,綜上來看,基於異步非阻塞的響應式應用或驅動可以以少許且固定的線程應對高併發的請求或調用,對於存在阻塞的場景,可以比多線程的併發方案提供更高的性能。

響應式和非阻塞並非總能讓應用跑的更快,何況將代碼構建爲非阻塞的執行方式自己還會帶來少許的成本。可是在相似於WEB應用這樣的高併發、少計算且I/O密集的應用中,響應式和非阻塞每每可以發揮出價值。尤爲是微服務應用中,網絡I/O比較多的狀況下,效果會更加驚人。

相關文章
相關標籤/搜索