點擊關注公眾號,實用技術文章及時了解
ClickHouse 是一個真正的列式數據庫管理系統(DBMS)。在 ClickHouse 中,數據始終是按列存儲的,包括矢量(向量或列塊)執行的過程。只要有可能,操作都是基於矢量進行分派的,而不是單個的值,這被稱為 « 矢量化查詢執行 »,它有利於降低實際的數據處理開銷。
Elasticsearch 是一個開源的分布式、RESTful 風格的搜索和數據分析引擎,它的底層是開源庫 Apache Lucene。 它可以被這樣準確地形容:
眾所周知,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 採集工具準備監控工具
Forcebot(http://forcebot.jd.com) 是專門為開發人員、測試人員提供的性能測試平台,通過編寫腳本、配置監控、設置場景、啟動任務、實時監控、日誌定位、導出報告一系列操作流程來完成性能測試,靈活的腳本配置滿足同步、異步、集合點等多種發壓模式。
幫助文檔(http://doc.jd.com/forcebot/helper/)
4.2 設計壓測數據4.2.1 前期壓測中名詞解釋每次壓測前,一定要觀察每個數據節點的 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 使用率:

指標 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 提高並發
2)在並發方面 Elasticsearch 比 clickhouse 支持的更好,但是相應的響應速度慢很多
綜合考量,我們認為 clickhouse 足以支撐我們的業務訴求
4.3.2 優化建議推薦
Java面試題寶典
技術內卷群,一起來學習!!
PS:因為公眾號平台更改了推送規則,如果不想錯過內容,記得讀完點一下「在看」,加個「星標」,這樣每次新文章推送才會第一時間出現在你的訂閱列表里。點「在看」支持我們吧!