close

點擊關注公眾號,實用技術文章及時了解


1 需求分析1.1 分析壓測對象1)什麼是 ClickHouse 和 Elasticsearch

ClickHouse 是一個真正的列式數據庫管理系統(DBMS)。在 ClickHouse 中,數據始終是按列存儲的,包括矢量(向量或列塊)執行的過程。只要有可能,操作都是基於矢量進行分派的,而不是單個的值,這被稱為 « 矢量化查詢執行 »,它有利於降低實際的數據處理開銷。

Elasticsearch 是一個開源的分布式、RESTful 風格的搜索和數據分析引擎,它的底層是開源庫 Apache Lucene。 它可以被這樣準確地形容:

一個分布式的實時文檔存儲,每個字段可以被索引與搜索
一個分布式實時分析搜索引擎
能勝任上百個服務節點的擴展,並支持 PB 級別的結構化或者非結構化數據
2)為什麼要對他們進行壓測

眾所周知,ClickHouse 在基本場景表現非常優秀,性能優於 ES,但是我們實際的業務查詢中有很多是複雜的業務查詢場景,甚至是大數量的查詢,所以為了在雙十一業務峰值來到前,確保大促活動峰值業務穩定性,針對 ClickHouse 和 Elasticsearch 在我們實際業務場景中是否擁有優秀的抗壓能力,通過這次性能壓測,探測系統中的性能瓶頸點,進行針對性優化,從而提升系統性能。

1.2 制定壓測目標

為什麼會選擇這個(queryOBBacklogData)接口呢?

1)從複雜度來看,接口(queryOBBacklogData)查詢了 5 次,代碼如下:/***切ck-queryOBBacklogData*@paramqueryBO*@return*/publicOutboundBacklogRespBOqueryOBBacklogDataCKNew(OutboundBacklogQueryBOqueryBO){log.info("queryOBBacklogDataCK入參:{}",JSON.toJSONString(queryBO));//公共條件-卡最近十天時間StringcommonStartTime=DateUtils.getTime(DateUtil.format(newDate(),DateUtil.FORMAT_DATE),DateUtils.ELEVEN_AM,1,-10);StringcommonEndTime=DateUtils.getTime(DateUtil.format(newDate(),DateUtil.FORMAT_DATE),DateUtils.ELEVEN_AM,1,1);//越庫信息-待越庫件數&待越庫任務數WmsObCrossDockQueryBowmsObCrossDockQueryBo=wmsObCrossDockQueryBoBuilder(queryBO,commonStartTime,commonEndTime);log.info("queryOBBacklogDataCK-wmsObCrossDockQueryBo:{}",JSON.toJSONString(wmsObCrossDockQueryBo));CompletableFuture<OutboundBacklogRespBO>preCrossDockInfoCF=CompletableFuture.supplyAsync(()->wmsObCrossDockMapper.preCrossDockInfo(wmsObCrossDockQueryBo),executor);//集合任務信息-待分配訂單WmsObAssignOrderQueryBowmsObAssignOrderQueryBo=wmsObAssignOrderQueryBoBuilder(queryBO,commonStartTime,commonEndTime);log.info("queryOBBacklogDataCK-wmsObAssignOrderQueryBo:{}",JSON.toJSONString(wmsObAssignOrderQueryBo));CompletableFuture<Integer>preAssignOrderQtyCF=CompletableFuture.supplyAsync(()->wmsObAssignOrderMapper.preAssignOrderInfo(wmsObAssignOrderQueryBo),executor);//揀貨信息-待揀貨件數&待揀貨任務數WmsPickTaskQueryBowmsPickTaskQueryBo=wmsPickTaskQueryBoBuilder(queryBO,commonStartTime,commonEndTime);log.info("queryOBBacklogDataCK-wmsPickTaskQueryBo:{}",JSON.toJSONString(wmsPickTaskQueryBo));CompletableFuture<OutboundBacklogRespBO>prePickingInfoCF=CompletableFuture.supplyAsync(()->wmsPickTaskMapper.pickTaskInfo(wmsPickTaskQueryBo),executor);//分播信息-待分播件數&待分播任務WmsCheckTaskDetailQueryBowmsCheckTaskDetailQueryBo=wmsCheckTaskDetailQueryBoBuilder(queryBO,commonStartTime,commonEndTime);log.info("queryOBBacklogDataCK-wmsCheckTaskDetailQueryBo:{}",JSON.toJSONString(wmsCheckTaskDetailQueryBo));CompletableFuture<OutboundBacklogRespBO>preSowInfoCF=CompletableFuture.supplyAsync(()->wmsCheckTaskDetailMapper.checkTaskDetailInfo(wmsCheckTaskDetailQueryBo),executor);//發貨信息-待發貨件數WmsOrderSkuQueryBowmsOrderSkuQueryBo=wmsOrderSkuQueryBoBuilder(queryBO,commonStartTime,commonEndTime);log.info("queryOBBacklogDataCK-wmsOrderSkuQueryBo:{}",JSON.toJSONString(wmsOrderSkuQueryBo));CompletableFuture<Integer>preDispatchCF=CompletableFuture.supplyAsync(()->wmsOrderSkuMapper.preDispatchInfo(wmsOrderSkuQueryBo),executor);returnprocessResult(preCrossDockInfoCF,preAssignOrderQtyCF,prePickingInfoCF,preSowInfoCF,preDispatchCF);}2)接口(queryOBBacklogData),總共查詢了 5 個表,如下:wms.wms_ob_cross_dockwms.wms_ob_assign_orderwms.wms_picking_task.wms.wms_check_task_detailwms.wms_order_sku3)查詢的數據量,如下:select(ifnull(sum(m.shouldBeCrossedDockQty),0)-ifnull(sum(m.satisfiedCrossedDockQty),0))aspreCrossStockSkuQty,count(m.docId)aspreCrossStockTaskQtyfromwms.wms_ob_cross_dockmfinalprewherem.createTime>='2021-12-0311:00:00'andm.createTime<='2021-12-1411:00:00'andm.warehouseNo='279_1'andm.orderType='10'andtenantCode='TC90230202'wherem.deleted=0andm.deliveryDestination='2'andm.shipmentOrderDeleted=0andm.status=0

從上面 SQL 截圖可以看出,查詢待越庫件數 & 待越庫任務數,共讀了 720817 行數據

selectcount(distinctm.orderNo)aspreAssignedOrderQtyfromwms.wms_ob_assign_ordermfinalprewherem.createTime>='2021-12-0311:00:00'andm.createTime<='2021-12-1411:00:00'andm.warehouseNo='361_0'andtenantCode='TC90230202'wherem.taskassignStatus=0andm.deliveryDestination=2andm.stopProductionFlag=0andm.deleted=0andm.orderType=10

從上面 SQL 截圖可以看出,查詢集合任務信息 - 待分配訂單,共讀了 153118 行數據

selectminus(toInt32(ifnull(sum(m.locateQty),toDecimal64(0,4))),toInt32(ifnull(sum(m.pickedQty),toDecimal64(0,4))))asprePickingSkuQty,count(distinctm.taskNo)asprePickingTaskQtyfromwms.wms_picking_taskmfinalprewherem.shipmentOrderCreateTime>='2021-12-0311:00:00'andm.shipmentOrderCreateTime<='2021-12-1411:00:00'andm.warehouseNo='286_1'andtenantCode='TC90230202'wherem.pickingTaskDeleted=0andm.deliveryDestination=2andm.pickLocalDetailDeleted=0andm.shipmentOrderDeleted=0andm.orderType=10and(m.operateStatus=0orm.operateStatus=1)

從上面 SQL 截圖可以看出,查詢揀貨信息 - 待揀貨件數 & 待揀貨任務數,共讀了 2673536 行數據

selectminus(toInt32(ifnull(sum(m.locateQty),toDecimal64(0,4))),toInt32(ifnull(sum(m.pickedQty),toDecimal64(0,4))))asprePickingSkuQty,count(distinctm.taskNo)asprePickingTaskQtyfromwms.wms_picking_taskmfinalprewherem.shipmentOrderCreateTime>='2021-12-0311:00:00'andm.shipmentOrderCreateTime<='2021-12-1411:00:00'andm.warehouseNo='279_1'andtenantCode='TC90230202'wherem.pickingTaskDeleted=0andm.deliveryDestination=2andm.pickLocalDetailDeleted=0andm.shipmentOrderDeleted=0andm.orderType=10and(m.operateStatus=0orm.operateStatus=1)

從上面 SQL 截圖可以看出,查詢分播信息 - 待分播件數 & 待分播任務,共讀了 1448149 行數據

selectifnull(sum(m.unTrackQty),0)asunTrackQtyfromwms.wms_order_skumfinalprewherem.shipmentOrderCreateTime>='2021-12-0311:00:00'andm.shipmentOrderCreateTime<='2021-12-1411:00:00'andm.warehouseNo='280_1'andm.orderType='10'andm.deliveryDestination='2'andtenantCode='TC90230202'wherem.shipmentOrderDeleted<>'1'andm.ckDeliveryTaskDeleted<>'1'andm.ckDeliveryTaskDetailDeleted<>'1'andm.ckDeliveryTaskStatusin('1','0','2')

從上面 SQL 截圖可以看出,查詢發貨信息 - 待發貨件數,共讀了 99591 行數據

2 測試環境準備

為了儘可能發揮性能壓測作用,性能壓測環境應當儘可能同線上環境一致,所以我們使用了和線上一樣的環境

3 採集工具準備

監控工具

http://origin.jd.com/ :監控 JVM,方法級別監控(提供秒級支持)
http://console.jex.jd.com/ :提供異常堆棧監控,火焰圖監控、線程堆棧分析
http://x.devops.jdcloud.com/ :支持查看 clickhouse/Elasticsearch 數據庫服務每個節點的 cpu 使用率
http://dashboard.fireeye.jdl.cn/ :監測應用服務器 cpu 使用率、內存使用率
4 壓測執行及結果分析4.1 編寫壓測腳本工具

Forcebot(http://forcebot.jd.com) 是專門為開發人員、測試人員提供的性能測試平台,通過編寫腳本、配置監控、設置場景、啟動任務、實時監控、日誌定位、導出報告一系列操作流程來完成性能測試,靈活的腳本配置滿足同步、異步、集合點等多種發壓模式。

幫助文檔(http://doc.jd.com/forcebot/helper/)

4.2 設計壓測數據4.2.1 前期壓測中名詞解釋
DBCP:數據庫連接池,是 apache 上的一個 Java 連接池項目。DBCP 通過連接池預先同數據庫建立一些連接放在內存中 (即連接池中),應用程序需要建立數據庫連接時直接到從接池中申請一個連接使用,用完後由連接池回收該連接,從而達到連接復用,減少資源消耗的目的。
maxTotal:是連接池中總連接的最大數量,默認值 8
max_thread:clickhouse 中底層配置,處理 SQL 請求時使用的最大線程數。默認值是 clickhouse 服務器的核心數量。
coordinating:協調節點數,主要作用於請求轉發,請求響應處理等輕量級操作
數據節點:主要是存儲索引數據的節點,主要對文檔進行增刪改查操作,聚合操作等。數據節點對 cpu,內存,io 要求較高, 在優化的時候需要監控數據節點的狀態,當資源不夠的時候,需要在集群中添加新的節點
4.2.2 壓測數據
clickhouse 數據服務:32C128G6 節點 2 副本
應用服務器:4 核 8G 2
maxTotal=16

每次壓測前,一定要觀察每個數據節點的 cpu 使用率

註:從上面壓測過程中,序號 6-12 可以看出,並發用戶數在增加,但 tps 沒有幅度變化,檢查發現 bigdata dbcp 數據庫鏈接池最大線程數未配置,默認最大線程數是 8,並發用戶數增加至 8 以後,clickhouse cpu 穩定在 40%~50% 之間不再增加,應用服務器 CPU 穩定在 25% 左右。

之後我們調整 maxTotal=50,通過調整 max_thread 不同的值,數據庫節點 CPU 使用率保持在 50% 左右,來查看相應的監測數據指標:應用服務 CPU 使用率、TPS、TP99、並發用戶數。

clickhouse 數據節點,CPU 使用率:

Elasticsearch 數據服務:32C128G6 節點 2 副本
應用服務器:4 核 8G 2
Elasticsearch 同樣保持數據庫服務 CPU 使用率達到(50% 左右),再監控數據指標 tps、tp99
調整指標如下:coordinating 協調節點數、 數據節點、poolSize

指標 1:coordinating=2,數據節點 = 4,poolSize=400

註:在壓測的過程中發現,coordinating 節點的 cpu 使用率達到 51.69%,負載均衡的作用受限,所以協調節點需擴容 2 個節點

指標 2:coordinating=4,數據節點 = 5,poolSize=800

註:在壓測的過程中,發現 CPU 使用率(數據庫)ES 數據節點在 40% 左右的時候,一直上不去,查看日誌發現 activeCount 已經達到 797,需要增加 poolSize 值

指標 3:coordinating=4,數據節點 = 5,poolSize=1200

註:壓測過程中,發現 coordinating 協調節點還是需要擴容,不能支持現在數據節點 cpu 使用率達到 50%

Elasticsearch 數據節點及協調節點,CPU 使用率:

我們在壓測的過程中發現一些之前在開發過程中沒發現的問題,首先 bdcp 數 bigdata 應用服務器,使用的線程池最大線程數為 8 時,成為瓶頸,用戶數增加至 8 以後, clickhouse 的 cpu 穩定在 40%~50% 之間不在增加,應用服務器 CPU 穩定在 25% 左右,其次 warehouse 集群協調節點配置低,協調節點 CPU 使用率高,最後是 clickhouse-jdbc JavaCC 解析 sql 效率低。

4.3 結果分析4.3.1 測試結論

1)clickhouse 對並發有一定的支持,並不是不支持高並發,可以通過調整 max_thread 提高並發

max_thread=32 時,支持最大 TPS 是 37,相應 TP99 是 122
max_thread=2 時,支持最大 TPS 是 66,相應 TP99 是 155
max_thread=1 時,支持最大 TPS 是 86,相應 TP99 是 206

2)在並發方面 Elasticsearch 比 clickhouse 支持的更好,但是相應的響應速度慢很多

Elasticsearch:對應的 TPS 是 192,TP99 是 3050
clickhouse:對應的 TPS 是 86,TP99 是 206

綜合考量,我們認為 clickhouse 足以支撐我們的業務訴求

4.3.2 優化建議
對 ES 協調節點進行擴容
bigdata 應用線程池最大線程數調高至 200
bigdata 應用 dbcp 線程池 maxTotal 設置成 50
讀取配置文件工具類增加內存緩存
來源:my.oschina.net/u/4090830/blog/5570795

推薦

Java面試題寶典

技術內卷群,一起來學習!!

PS:因為公眾號平台更改了推送規則,如果不想錯過內容,記得讀完點一下「在看」,加個「星標」,這樣每次新文章推送才會第一時間出現在你的訂閱列表里。點「在看」支持我們吧!

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 鑽石舞台 的頭像
    鑽石舞台

    鑽石舞台

    鑽石舞台 發表在 痞客邦 留言(0) 人氣()