天天看點

如何通過火焰圖快速定位Cassandra性能瓶頸

運維大規模分布式系統的比較重要的一個挑戰是可以有能力指出關鍵問題所在。在沒有證據支援某種說法的情況下,當故障出現時,總是責怪元件(通常是資料庫)的偶然性問題是很常見的一件事。我們已經讨論過監控工具、圖形化輸出、以及報警metric的重要性,并使用分布式tracing系統(比如zikin)去正确的辨識複雜系統的根源問題。

一旦你把問題縮小到一個單一的系統上面,你會怎麼做?通常我們都會說這個會具體問題具體對待。有的問題是臨時的,比如壞盤。有的問題卻涉及到人為引入的變化,比如部署或者是錯誤的配置。這些都是有直接簡單的解決辦法:換盤或者是復原部署。

但是如果出現的問題超出簡單變化的範疇,那怎麼辦?到現在為止還沒有提到的是規模增長造成的問題。規模可以成為另一個困難的問題,因為複現這個問題一般情況下是很微妙且複雜的。這些挑戰有時是通過吞吐量(每秒請求數)、大小(兆位元組)或延遲(5ms p99)來衡量的。例如,如果資料庫伺服器能夠在記憶體不足的情況下為每個請求提供服務,那麼它可能獲得極好的吞吐量。随着資料集大小的增加,随機查找越來越可能進入磁盤,進而降低吞吐量。Time Window Compaction Strategy 是解決規模問題的一個很好的例子,除非有數字表明,否則還是很難了解的。除非遇到很大量的資料,否則你不會體會到compaction帶來的痛苦,下規模情況下,很難遇到什麼問題。

在失敗期間,我們經常會把機器以及他們的程式執行過程當做一個黑盒子。幾十億條指令每秒都在執行,但是我們卻沒有辦法看到内部的奧秘。很幸運的是,我們并沒有完全忽略機器在做什麼。多年來我們已經有了debugger以及profiler工具。 Oracle的JDK也為我們提供了Java Flight Recorder,我們可以使用它來分析本地或者生産中運作的流程。

如何通過火焰圖快速定位Cassandra性能瓶頸

通過 flight recorder 進行profile是簡單而直白的,但是想要翻譯這個結果卻需要一定的工作量。把上面的清單一一展開并查找需要的問題更消耗勞動力。 但是我們如果可以将資訊可視化展出的話那麼就更好了。 但是這卻需要商業的license且僅能在Oracle的JDK上運作。

這就引入了我們上面列出的标題:一種可以展示可視化資訊的方法,叫做火焰圖。火焰圖讓我們可以快速的找出系統中的性能瓶頸。 由

Brendan Gregg 發明。這也是一系列非常長的性能調整文章的第一部分,我們将在深入研究Cassandra的内部結構時再次提到它。

Swiss Java Knife

我們在本文中研究的方法将要用到

,通常叫做SJK,用它來擷取JVM的資料并生成火焰圖。SJK是一個很不錯的工具集,除了生成火焰圖以外,我們可以使用它收集統計資訊、監視線程以及執行各種其他診斷任務。它可以在MAC、Linux以及oracle JDK和Open JDK上工作。

我已經下載下傳了jar,把它放在$home/bin中,并設定了一個shell函數來輕松調用它:

sjk(){
    java -jar ~/bin/sjk-plus-0.8.jar "@"
}           

在我的電腦上,我使用cassandra-stress進行壓測,我已經部署好了我的資料庫,并開始使用下面的指令壓測:

cassandra-stress read n=1000000           

在分析的第一步中,我們需要使用SJK的stcap特性捕獲正在運作的java應用程式的堆棧幀。為此,我們需要傳入程序id和将資料轉儲到的檔案。轉儲是以二進制格式編寫的,我們稍後可以查詢:

sjk stcap -p 92541 -i 10ms -o dump.std           

然後我們可以分析資料。如果我們隻有一個終端,我們可以列印出分析的柱狀圖。如果有明顯的問題,這一點本身就非常有用。在這種情況下,我們可以看到很多時間都花在sun.misc.unsafe.park上,這意味着線程隻是在等待,停在:

$ sjk ssa -f dump.std --histo
Trc     (%)  Frm  N  Term    (%)  Frame
372447  96%  372447       0   0%  java.lang.Thread.run(Thread.java:745)
309251  80%  309251  309251  80%  sun.misc.Unsafe.park(Native Method)
259376  67%  259376       0   0%  java.util.concurrent.locks.LockSupport.park(LockSupport.java:304)
254388  66%  254388       0   0%  org.apache.cassandra.concurrent.SEPWorker.run(SEPWorker.java:87)
 55709  14%  55709        0   0%  java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
 52374  13%  52374        0   0%  org.apache.cassandra.concurrent.NamedThreadFactory$$Lambda$6/1758056825.run(Unknown Source)
 52374  13%  52374        0   0%  org.apache.cassandra.concurrent.NamedThreadFactory.lambda$threadLocalDeallocator$0(NamedThreadFactory.java:81)
 44892  11%  44892        0   0%  io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:138)
 44887  11%  44887        0   0%  java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
 42398  11%  42398        0   0%  io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:409)
 42398  11%  42398        0   0%  io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858)
 42398  11%  42398        0   0%  io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:753)
 42398  11%  42398        0   0%  sun.nio.ch.KQueueArrayWrapper.poll(KQueueArrayWrapper.java:198)
 42398  11%  42398        0   0%  sun.nio.ch.KQueueSelectorImpl.doSelect(KQueueSelectorImpl.java:117)
 42398  11%  42398    42398  11%  sun.nio.ch.KQueueArrayWrapper.kevent0(Native Method)
 42398  11%  42398        0   0%  sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
 42398  11%  42398        0   0%  sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)           

然後我們就有了我們的stcap的dump,通過下面的指令,可以生成我們的火焰圖:

sjk ssa --flame -f dump.std > flame-sjk.svg           

當你使用浏覽器打開svg的檔案的時候,你可以看到下面的圖:

如何通過火焰圖快速定位Cassandra性能瓶頸

如果打開機器上的flame圖,可以将滑鼠移到不同的部分上,檢視方法調用和所用時間的百分比。橫坐标長度越寬,在stack裡出現的頻率就越高。浏覽圖表很容易了解我們的程式在哪裡花費時間。

這并不是生成火焰圖的唯一技術。Brendan Gregg 有一長串的連結和參考資料,我建議詳細閱讀在他的火焰圖頁。我打算編寫一個實用程式,将SJK格式導出為brendan在他的部落格上使用的格式,因為它看起來更好一些,滑鼠懸停更好,支援向下鑽取,還有搜尋功能。它們還支援不同的flame圖,如果您要在不同的建構中進行性能比較,這是很好的方式。

我希望你喜歡這篇關于用火焰圖可視化Cassandra文章。我們已經與我們合作過的團隊多次使用這個工具來調整Cassandra的配置并優化性能。在本系列的下一篇文章中,我們将研究如何調整垃圾收集參數以最大化吞吐量,同時将延遲保持在最低限度。

譯者注:

1.生成火焰圖的方式很多,文章中說的是一種方式,可以參考

一系列文章;

2.上述是針對Cassandra生成的火焰圖,對于其他的java平台軟體也适用,比如HBase、Spark等;

3.可以生成c++ 等其他平台的軟體的火焰圖,不僅僅限于java程式,使用的profile工具不僅僅是SJK,也可以是perf、systemtap;

4.火焰圖不僅僅限于cpu(on-cpu、off-cpu),還可以繪制出記憶體、磁盤等的火焰圖。

翻譯自:

https://thelastpickle.com/blog/2018/01/16/cassandra-flame-graphs.html

入群邀約

為了營造一個開放的 Cassandra 技術交流環境,社群建立了微信群公衆号和釘釘群,為廣大使用者提供專業的技術分享及問答,定期開展專家技術直播,歡迎大家加入。另外阿裡雲提供免費Cassandra試用:

https://www.aliyun.com/product/cds
如何通過火焰圖快速定位Cassandra性能瓶頸