一、背景
日志記錄了一個系統的行為,對于了解系統、診斷問題、輔助審計等都有極其重要的作用。通常最近一段時間的日志訪問頻率是最高的,我們通過聚合日志,分析日志、匯總數據,幫助開發、運維、DBA了解業務的狀態和行為。這次實踐是針對MySQL的抓包日志進行分析,當前系統不足以支持新的需求,需要重構一套日志分析系統。
現有抓包系統是將 MySQL 請求的所有 SQL 語句抓取并分析之后寫入到 Clickhouse 中,數據可以用來分析數據庫的操作。可以查找當前實例、庫、表有多少 AppCode 在訪問、數據庫資源是否可以回收、輔助審計等功能。
Sniffer 抓包之后將數據寫入到 Kafka 中,Clickhouse 直接消費 Kafka 的隊列中數據,并將數據 merge 到 Clickhouse 中。由 Server 程序按照天級別定時讀取 Clickhouse 中的數據,分析、匯總數據,并解析請求 IP 對應的服務信息等,最后將結果寫入到 MySQL 中。
當前數據為日志數據,允許少部分丟失或重復,Kafka 隊列中的數據約有 133w/s(單個隊列最多 33W),MySQL 中存儲的結果數據規模大約在 4.6T 左右。
二、名詞解釋
- AppCode
服務的名稱,是一個服務的基本屬性。
- Clickhouse
一個用于聯機分析(OLAP)的列式數據庫。
- Kafka
一個高性能的分布式隊列服務。
- Zookeeper
一個分布式的開源協調服務。
- 擴展性
在業務量上漲時,服務通過較低的代價就可以滿足對業務量上漲的需求。
- 聚合比
將 N 條數據按照同一緯度聚合為 M 條數據,M 一定小于等于 N。聚合比 = 聚合之后的數據條數/聚合之前的數據條數。
三、現狀分析
1、消費能力不足導致數據丟失
Clickhouse 消費 Kafka 隊列中的數據能力不足,延遲較高。并且 Kafka 中的數據只保留 3 個小時,根據測試四個節點 Clickhouse 消費的 Kafka 隊列中的數據,約有 80% 的數據丟失,導致數據不完整。
2、服務信息計算不準確
Server 是天級別計算請求的服務信息。由于服務已經上云部署,單個服務的 IP 變動非常頻繁,導致 Server 獲取到服務信息有延遲(最高延遲 24 小時),甚至很多計算的結果是錯誤的。這導致部分場景下分析出來的數據完全不可信。
3、匯總數據較少
當前只匯總了四個維度的請求數據,并且只有天級別的數據,粒度較大,無法下鉆查詢具體信息,展示的維度和明細信息較少。
4、服務監控&可用性
Server 節點目前只有一個,缺乏可用性并沒有詳細的監控信息。
四、需求
針對當前服務的不足,設計一套服務需要滿足當前日志計算性能和業務需求,并且具備較好的擴展性。
五、目標
1、高性能、高擴展性、高可用
服務需要具備以下特性:
1)高性能
在有限資源的情況下,盡可能提高數據消費、聚合能力,降低數據丟失的概率,降低數據入庫的延遲。
2)高可用
單個或多個節點出現問題時,不影響服務整體的可用性。
3)高擴展
在未來業務日志體量進一步增長時,僅通過增加部署節點或者修改配置,就可以滿足增長的需求,無需額外的工作。
2、降低計算請求業務信息的延遲
從請求 IP 到獲取服務信息的延遲降低在 1min 以內,確保 99.9% 的準確性。
3、更多維度匯總數據和下鉆查詢
支持更多維度的匯總信息查詢,以及支持部分場景下的下鉆查詢。
4、監控
提供多種監控數據,方便展示服務情況,根據監控即可以方便定位到問題。
六、分析
當前 Clickhouse 消費能力不足可以通過擴展節點和調優參數進一步解決,但是服務信息計算是 Clickhouse 做不到的,并且 OLAP 類型的數據庫對數據更新并不是太友好,尤其是大規模的更新。如果要解決【降低計算請求業務信息的延遲】這個問題可以有兩個解決方案:
如果采用方案一,會增加 Sniffer 端的不可控性,這與我們之前設計的盡可能減少 Sniffer 端資源消耗的初衷相違背,所以我們選擇方案二。
七、設計
1、整體流程
整體流程設計如下所示:
2、模塊劃分
所有模塊的目標:高性能、高可用、高擴展。
3、dubaiMeta
1)說明
由于基礎服務不能提供高性能的 IP-AppCode 映射信息的接口,需要自行實現這一功能。對接基礎服務的 IP-AppCode 映射信息提供的接口,實時從 Kafka-OPS 隊列中獲取 IP-AppCode 映射變更的信息流,Merge 到當前數據,并提供 IP-AppCode 信息的接口;
2)設計
由于 dubaiMeta 是提供基礎信息的接口,訪問量比較大,需要提供高性能、高可用、高擴展性,故 dubaiMeta 需要盡可能設計成為無狀態的服務。
將所有的 IP-AppCode 映射數據存儲在 MySQL,映射為最新版本。所有的 IP-AppCode 變更歷史也都會存儲在 MySQL。通過版本信息持續將 IP-AppCode 變更信息 Merge 到最新版本。目前 IP-AppCode 數據整體體量不大,可以在服務內部緩存,不使用其他緩存。這樣既可以減少網絡和緩存的請求,降低請求耗時,也會避免因對緩存的依賴而導致的性能和可用性問題。這樣 dubaiMeta 就可能成為一個接近無狀態的服務。
單個請求如果不能命中緩存則會請求基礎服務的 IP-AppCode 接口,并將變更數據 Merge 到緩存。但是單個 dubaiMeta 節點數據變更之后如何與其他 dubaiMeta 節點通訊最后達到所有節點數據一致?
有兩種方案:
盡可能保證單個節點的高性能的,并檢測單個節點的數據一致性延遲,將有問題的服務及時下掉,通過這個方法可以盡可能減低數據不一致帶來的問題。故選擇【變更通知】的方式;
3)啟動流程
服務啟動時首先從 Kafka-OPS 持續訂閱信息流,所有變更信息 Merge 到內部緩存,然后再從 Self-Kafka-OPS 中持續訂閱變更信息流,所有變更信息 Merge 到內部緩存,最后從 MySQL 中獲取全量的數據信息,將所有數據 Merge 到緩存,組合成全量的數據。等到所有數據 Merge 完成,并且兩個 Kafka 隊列無堆積時,再提供服務。
4)性能分析
目前基礎信息的數據量不大,可以在服務內部緩存,不使用其他緩存。既可以減少網絡和訪問緩存的耗時,大幅度降低請求的耗時,又可以避免因對緩存的依賴而導致的性能和可用性問題。
單節點 IP-AppCode 映射變更會發起變更通知,異步通知其他節點,無需感知其他節點存在,故性能可以得到保證。
5)可用性分析
dubaiMeta 目前所有數據存儲在本地緩存,在 MySQL 中存儲一份副本和變更信息流。
由于 dubaiMeta 是接近無狀態的,部署多個節點,通過負載均衡服務下發到不同的節點就可以保證整體服務的可用性。
MySQL 通過平臺已有的 HA,保證可用性;
6)擴展性分析
由于 dubaiMeta 是接近無狀態的,故可以橫向擴展,不對其他節點產生影響,只需要在負載均衡器上添加節點即可。
4、SnifferServer
1)說明
從 Kafka-Sniffer 隊列獲取日志數據,在日志中補充各種業務信息,并聚合數據。最后將聚合之后的結果批量寫入到 Clickhouse 中。
由于隊列中的數據量比較大,無法全量存儲所有數據,需要按照一定的維度聚合數據。通過降低聚合比(聚合之后的數據條數/聚合之前的數據條數)可以降低總體數據量,在保證性能的前提下盡可能縮短入庫的時間。
由于 Clickhouse 是 OLAP 分析類型的列式數據庫,更推薦批量寫入的方式提高數據庫的寫入性能(每次不少于 1000 條)。
2)設計
針對單個隊列,可以使用多個 SnifferServer 使用同一個 consumerGroup 消費數據,保證消費者的性能、可用性,同時 SnifferServer 也具備了一定的擴展性。
SnifferServer 是內存消耗和 cpu 消耗類型的服務。為了減少 gc 和內存消耗,通過復用對象,確保單個服務內部對象的數量不會有較大波動,可以大幅度降低 gc 以及內存的使用量,提高性能。
按照功能,將 SnifferServer 拆分成三個模塊:consumer 模塊、aggregator 模塊、writer 模塊。
consumer 模塊消費隊列中的數據,將數據傳遞給 aggregator 模塊;aggregator 模塊填充業務信息并聚合數據,將聚合之后的數據傳遞給 writer 模塊;writer 模塊將數據批量寫入到 Clickhouse 中。
① consumer 模塊
- 功能
從 Kafka-Sniffer 隊列中獲取數據,將數據組合之后批量傳輸給 aggregator 模塊。
- 分析
針對單個 Kafka 隊列,提升消費的速度途徑有:
經測試,在當前場景配置下,單個 SnifferServer 消費隊列速度可以達到 20W/s+。通過對 consumer 的調優已經能夠完全達到 33w/s (兩個 SnifferServer)的消費速度,已完全滿足業務的需求。
② aggregator 模塊
- 功能
從 consumer 接受數據,并獲取 IP-AppCode 映射信息和業務信息,將信息補充到日志數據中。等到一定數量的數據或者超時之后,將這一批次的數據按照指定的維度聚合。最后將聚合之后的結果傳輸給 writer 模塊
- 分析
- 如果每條數據都需要通過接口獲取 IP-AppCode 映射和業務信息,那樣會大大降低聚合的效率,故本地需要緩存 IP-AppCode 和業務信息。aggregator 模塊同樣也需要訂閱 Kafka-OPS 和 Self-Kafka-OPS 變更,Merge IP-AppCode 變更信息到本地緩存。
- 通過增加 aggregator 線程數量提升并發數,可以有效的提升聚合的效率。但線程數越多會在不同程度上提高聚合比(和業務行為相關),通過增加單個批次的數量可以降低聚合比,兩個指標需要根據需要測試調優;
經測試:針對同一個隊列中的數據,單個 SnifferServer 的聚合比約為 10%-20% 左右,兩個 SnifferServer 的平均聚合比約為 15%-30% 左右,三個 SnifferServer 的平均聚合比約為 30% 以上,故在同等配置的情況下增加 SnifferServer 則會增加聚合比,存儲端將增加數據量。
③ writer 模塊
- 功能
從 aggregator 模塊接受數據,緩存在內存中。當緩存數據超過 N 條或者緩存時間超過 M 秒之后再將緩存數據批量寫入到 Clickhouse 中;
- 分析
每個批次應該盡可能緩存足夠的的數據量再寫入數據,提升寫入的效率,降低寫入的次數,預設單個批次為 1w(最少,可配置)條數據;
3)分析
每個模塊均可以設置緩存大小和并行的線程數,通過設置緩存大小和并行的線程數可以提高效率。但是需要注意的是,緩存大小和并行線程越多,占用的資源也就越多。并且如果程序意外終止,那么丟失的數據也會變多,需要酌情考慮各個參數的配置。
對于各個模塊的啟動和關閉順序需要額外關注。
① 模塊啟動順序
先啟動 writer 模塊,初始化 writer 模塊的緩存和線程,再啟動 aggregator 模塊,初始化 aggregator 的緩存和線程,最后啟動 consumer 模塊,初始化 consumer 模塊的線程和緩存。
② 模塊關閉順序
為了減少數據丟失,在正常情況下關閉服務時需要按照以下順序關閉模塊
- 關閉所有的Kafka的連接;
- 將 consumer 模塊中所有緩存數據發送到 aggregator 模塊之后,再關閉所有 consumer 模塊的線程;
- 將 aggregator 中的緩存數據立即聚合(所有日志數據補完業務信息,并聚合完成)。聚合完成的數據全部發送給 writer 模塊之后,再關閉所有 aggregator 模塊的線程;
- 將 writer 模塊中的數據分批次,全部寫入到 Clickhouse 中,最后關閉所有 writer 模塊的線程。
4)擴展性分析
由于 SnifferServer 是偏計算類型的服務,并且從 Kafka 到 SnifferServer 到 Clickhouse,需要大量的數據傳輸,需要較好的 cpu 和網卡才可以充分發揮 SnifferServer 的性能;
① SnifferServer 內部擴展性
SnifferServer 的每個模塊都可以通過設置線程數和緩存大小提高性能;
② SnifferServer 級別的擴展性
對于單個隊列,受限于 Kafka 的 partition 數量,最多有于 partition 數量相等的 SnifferServer 運行,超過 partition 數量時節點不再參與隊列消費;
③ Kafka 的 Partition
單個 Kafka 集群的 partition 理論上沒有限制,受限于服務器資源、Zookeeper 和運維的方便性等,需要設置上限;
④ 整個服務
可以規劃針對不同的 IDC,向不同的 Kafka 寫入日志數據,這樣日志數據將被分區;
5)可用性分析
SnifferServer 之間通過 consumerGroup 消費 Kafka 隊列中的數據。對于單個隊列通過冗余 SnifferServer,即使單個 SnifferServer 掛掉,不會影響整體服務。
5、SnifferAnalyze
1)說明
按照天級別定時從 Clickhouse 中獲取聚合數據,分析、匯總,存儲分析之后的結果并提供接口和頁面展示結果。
2)設計
分析匯總之后的結果大概分為兩類數據,第一類是初步聚合的粗粒度數據,數據量比較大。數據一旦產生不會修改,只有大范圍的刪除,一般是溯源、分析、下鉆查詢使用,使用的頻率不是很高;第二類是匯總的報告數據。部分數據會存在大范圍的修改,較多的并發查詢。整體數據量相對于第一類數據量較少,一般是展示結果、接口查詢較多;
Clickhouse 在大規模存儲上的單表查詢和寫入效率較高,壓縮效率較高但不擅長做并發查詢和頻繁的修改數據,官網建議每秒最多查詢 100 次。相比較而言,MySQL 適合存儲小體量數據,以及數據的增刪改查,并擅長高并發查詢。
綜合考慮節省存儲成本以及各個存儲的特性,第一類數據適合存儲到 Clickhouse 中,第二類數據適合存儲到 MySQL 中。針對原始日志數據設置合適的過期時間,超過指定時間的數據都予以刪除,而匯總數據相較于原始數據量已經大幅度減少,可以保留較長的過期時間。
依托 Clickhouse 的分析能力,對于第一類數據直接將 Clickhouse 中的數據分析出來直接寫入到 Clickhouse 中,避免中間轉儲。第二類數據需要從 Clickhouse 中獲取出來,分析、計算、匯總之后再寫入到 MySQL 中。
每個任務執行前都需要獲取鎖,只有成功獲取到鎖的任務才可以執行該任務。SnifferAnalyze 多個節點在執行任務前會通過搶占的方式獲取任務鎖,僅當成功獲取了鎖的節點會執行任務,保證了單個節點掛掉不影響分析任務的執行。但是如果任務執行過成中被終端,目前需要人為介入處理。
3)擴展性分析
目前分析類型的任務節點擴展能力有限。
4)可用性分析
由于分析類型的任務擴展能力有限,故只能在節點之間保證高可用。并且一旦任務執行中斷需要人為介入處理。
6、Clickhouse
1)說明
Clickhouse 架構圖
例如圖示 Clickhouse 有兩個分片(A 和 B),每個分片有兩個副本([A1,A2],[B1,B2]),集群與三節點的 Zookeeper 通訊。
① 同步
Clickhouse 集群 Replication 引擎的副本是通過 Zookeeper 實現的,Zookeeper 存儲數據塊的元數據信息。分片 A 有 A1 和 A2 兩個節點,A1 和 A2 共同監聽 Zookeeper 執行目錄下節點的數據。當 A1 節點寫入數據塊之后,A1 在 Zookeeper 上變更元數據信息。A2 收到 Zookeeper 的元數據變更之后,向 A1 發起拉取指定數據塊的通知,A1 將指定的數據塊發送給 A2,完成數據傳輸。同理 A2 也可以寫入數據,通知 Zookeeper 變更數據,并向 A1 傳輸數據。數據同步是異步的,傳輸數據塊時會去重。更多副本相關的信息請見官網說明。
② 分片
分片依靠 Distribute 引擎實現。Distribute 引擎不存儲任何數據,Clickhouse 有 Distribute 引擎支持將數據按照指定的規則(random,hash,range,自定義)將數據分發到各個分片。
數據寫入 Distribute 引擎時,數據在本地寫入完成后立即返回。Clickhouse 會周期性的按照規則將數據分發的其他節點上。
③ 查詢
通過 Distribute 引擎查詢時,無論分片規則是什么樣的,Distribute 都會將 SQL 分發到所有的分片上查詢,并在當前節點匯總數據,最后返回給客戶端。如果查詢 Replication 引擎的表,那么只查詢本地數據。
2)可用性分析
Clickhouse 的 Replication 引擎和 Zookeeper 實現數據副本,保證了每個分片內可以允許一個副本宕機。Distribute 引擎可以保證在 Clickhouse 所有節點上都可以寫入和讀取。
但是通過數據同步是異步的。如果節點寫入成功并在數據尚未完成傳輸之前宕機,無法恢復,則尚未同步的數據塊將會丟失。
3)擴展性分析
由于 Distribute 查詢的時候會將 SQL 分發到所有的分片上,無論分片的數據狀態如何,故新增的節點可以直接加入到 Clickhouse 集群中,而無需擔心舊數據遷移的問題。但是需要考慮數據傾斜問題,通過提高新加入節點權重可以將新寫入的數據更多的發送到新加入分片上。
向 Distribute 引擎寫入數據時,Distribute 引擎首先會寫入本地,再依次轉發給其他節點,可能會導致本地網絡流量增加、服務 merge 數據塊時產生額外的 cpu 以及 IO 使用的問題。可以通過只寫入本地表,而不寫入 Distribute 表解決這個問題。但是需要通過一定的策略(比如輪詢)寫入不同的 Clickhouse 節點,解決數據傾斜的問題。
7、監控
1)說明
當前監控只是用于查看各個節點的狀態情況,展示性能問題,并未提供高級別的功能。監控告警接入公司現有的監控系統。
八、效果
1、SnifferServer
所有 SnifferServer 節點平均內存占用約為 12G 左右,最大 gc 平均約為 21ms,75 分位的 gc 平均約為 0.6ms。
兩節點 SnifferServer 合計 CPU(32核)利用率峰值約 70%,網卡峰值 上行約 330Mb/s 下行 400Mb/s。
單個隊列數據生成速度峰值約為 30w/s,平均堆積約 20k,消費者速度要快于生產者。
aggregator 平均每秒聚合 1.2 次,數據聚合比約為 40%,writer 每秒約寫入 6 次,業務信息和 appCode 命中率幾乎 100%。
2、頁面展示
展示某個業務的平均響應時間和查詢次數
展示某個慢查詢的平均響應時間和查詢次數
九、總結
SnifferServer 將隊列中的日志數據補全業務信息、聚合數據、將結果寫入到 Clickhouse 中,SnifferAnalyze 定期分析數據,將結果寫入到 Clickhouse 和 MySQL。整個系統具備高性能、高可用性、高擴展性的優點,內存和 CPU 使用率比較穩定。日志分析系統呈現出來的結果可以幫助開發更好的了解業務的行為,發現潛在的問題,評估業務在數據庫方面的風險。結合慢查詢風險指數系統可以更精確的評估慢查詢的風險。
>>>>
參考資料
- https://clickhouse.com/docs/zh/
- https://clickhouse.com/docs/zh/engines/table-engines/mergetree-family/replication/
- https://mp.weixin.qq.com/s/kFbW5K7txdijLOVkYLs40A
作者丨錢芳園
來源丨公眾號:Qunar技術沙龍(ID:QunarTL)
dbaplus社群歡迎廣大技術人員投稿,投稿郵箱:editor@dbaplus.cn
關注公眾號【dbaplus社群】,獲取更多原創技術文章和精選工具下載