問題:
使用vdbench進行單層100w目錄,每個目錄30個文件,共3000w文件讀寫時,在創建文件得時候IO會出現斷斷續續得情況。
分析過程:
1、 nfs抓包分析
使用vdbench創建一個文件得流程eg: vdb_f0398.file:
Lookup call -> lookup reply ->create call ->create reply ->write call ->write reply
2、 當vdbench IO歸0時,觀察存儲端狀態
1) read IO特別大,write IO為0
看4標識
2) zfs arc到了limit點為,arc_prune數值增加,意味着頻繁得回收arc,但arc大小為變化
看上圖1是設定的arc_meta_limit,2是已經使用的arc_meta空間,一般觸發回收時會高出limit限制幾百M,3是回收次數。其在arc_meta使用觸發回收時短時間內多次回收調用,但是回收的arc空間很少,之后不再回收,導致arc一直是full的狀態。
3) arc相關參數變化
沒有釋放arc
看圖5標識,此處為有寫IO時,此時為readdir執行完了一次后,在對應的目錄下創建了30個文件(vdbech配置的)。
4) 使用perf分析進程變化情況
發現進程lz4_decompress_zfs 進程變化比較明顯
5) 通過dump_stack打印lz4的調用棧:
從打印情況看兩個可疑點,出問題的時候zfs_readdir 和 reconnect_path被不停的調用
6) 從這兩個地方分析是否存在問題
1》 zfs_readdir其dump_stack情況
分析內部代碼,打印事件發現:
會發現while執行的次數和時間會隨着目錄數的增加線性增長,100w目錄查詢一次一般會超過10s(8s-180s,當時應該受到arc回收影響,沒出現IO歸零時不會調用到此函數)
2》 reconnect_path情況
出現問題時,exportfs參數沒有收到期望的具體vdb.1_6795.dir目錄名,而是根目錄/(注意此處設置nfsd thread數為1,默認是32,會進行32次根目錄的調用,其造成阻塞的概率增大,並耗時非常長)
由此觸發了zfs_readdir
此處引出問題,為什么參數會是根目錄????
7) 當arc緩存開始執行回收操作時,出現問題
而多次回收內存並未釋放多少,前面圖示可以看出。
8) 由上聯合起來分析匯總:
當arc使用接近限制閾值的時候,觸發回收操作,而回收操作只回收一點,但將原來的目錄緩存破壞掉,使用新創建的文件元數據來填充arc,大量的arc緩存無法釋放。導致當服務器端nfs執行 lookup確定要創建的文件是否合法時,觸發了reconnect_path->zfs_readdir等操作,來進行所有目錄的重新匹配,而此時arc已經滿了無法緩存,導致接下來的每次lookup都要執行一遍readdir。
此處引出問題,為什么緩存釋放不了???
3、 由上分析,猜測服務器vdbench緩存了inode,dentry等信息
通過在跑vdbench IO時,觀察服務器內存使用情況發現,隨着創建文件夾和文件,內存使用明顯
嘗試在存儲端arc接近緩存閾值時,清除服務器的緩存,主要是dentry、inode信息。多次測試發現問題不再重現。Arc可以正常釋放,並且釋放速度較快。
4、 綜上確定問題出現vdbenc IO,在創建文件夾和文件的時候會影響zfs ARC緩存釋放,引出問題:
1) vdbench 在沒有創建完文件之前會維護這些link?
2) Nfs客戶端做的緩存?
3) 此現象對其他公司nas產品是否一樣?
4) 需要存儲端解決此問題?如何解決?
5、arc小於2G回收會出問題這個大概率是之前的因素影響,還在分析代碼並測試中~~。測試了一次1.5G的在服務器端正常釋放緩存后,沒啥問題。