解決TiKV節點JBD2進程I/O佔用高的問題

今天事情甚多,草草寫一篇,儘量趕在1點之前休息。

問題

我們的TiDB集羣上線以來,所有TiKV節點的所有磁盤I/O Util指標總是偏高,大多數時候在50%以上,極端情況下接近90%。集羣採用的阿里雲ECS配備的都是PL2級別的ESSD雲盤(標稱吞吐量峯值350MB/s、10w IOPs,且添加了掛載參數noatimenodelalloc),主要負載是通過DM同步與簡單查詢50+張業務庫大表,理論上不應該出現如此高的I/O佔用。Grafana反映出的監控數據如下,IOPs和寫延遲均正常。

思考

使用iotop命令觀察到名爲jbd2的進程I/O百分比很大,遠大於tikv-server,但是實際讀寫量又很小。(vdc、vdd、vde是單機3個TiKV實例專用的硬盤)

jbd2是什麼鬼?Wikipedia的簡介如下:

JBD, or journaling block device, is a generic block device journaling layer in the Linux kernel written by Stephen Tweedie from Red Hat. JBD is filesystem-independent. ext3, ext4 and OCFS2 are known to use JBD.
JBD exists in two versions, JBD and JBD2. JBD was created with ext3 in 1998. JBD2 was forked from JBD in 2006 with ext4, with the goal of supporting a 64-bit (as opposed to 32-bit-only in JBD) block number.

JBD是日誌塊設備(journaling block device)的簡稱,位於文件系統層和塊設備驅動層之間。它負責記錄塊設備的操作日誌,並提供原子性、事務性地將操作刷寫到設備的能力。也就是說,它能夠保證操作系統失敗時,文件系統的完整性和一致性不受到破壞(一批原子操作要麼全部flush,要麼全部不flush),作用有些類似於存儲引擎中的WAL或者redo log。ext4文件系統採用的是JBD的一個分支,即JBD2。

首先考慮是不是JBD2本身出了問題?通過查找資料,發現有可能是一個內核bug(參見https://bugzilla.kernel.org/show_bug.cgi?id=39072)。但是它的年代比較久遠了,我們所用的內核版本是3.10.0,早已修復,所以繼續懷疑是否真的有什麼操作導致JDB2頻繁進行刷寫。

再次觀察iotop的輸出,發現tikv-server中與raftstore相關的I/O佔了主要部分。梳理一下TiKV配置中raftstore的參數,注意到raftstore.sync-log的嫌疑較大。TiDB官方FAQ中的解讀如下。

由上述文字不難推測出,如果sync-log = false,那麼寫入Raft log時只會調用write()寫入到緩衝區,而不會調用fsync()立即強制持久化。反之,如果sync-log = true,就會調用fsync()了。StackOverflow上的一個答案可以佐證:

結合JBD2的作用,基本可以確定是sync-log開關打開導致頻繁fsync(),進而造成其I/O佔用居高不下。於是我們修改TiKV的配置關掉它,並滾動重啓所有TiKV實例,可以發現I/O Util回落到了相對正常的水平。

解決

關閉sync_log非常簡單直接,但卻是以犧牲數據可靠性作爲trade-off的(當然對於雲環境而言影響不算大)。如果不想在TiDB層面做改動,則需要調整磁盤掛載參數來變相降低JBD2的負載。例如:

  • 在掛載參數中添加data=writeback啓用ext4的寫回日誌模式(默認爲ordered),即只產生元數據日誌,不產生數據日誌,並且不保證數據與元數據落盤的順序;
  • 在掛載參數中添加commit=60來降低ext4主動提交事務的頻率,單位爲秒,默認爲5秒。

另外,可以用fio等工具對空盤(注意一定要是空盤)做個fsync IOPs的測試,如果此值過低,應考慮更換性能更高的盤。

The End

看官若不瞭解Raft Consensus,可以參見筆者很久之前寫過的一篇簡單總結

民那晚安晚安。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章