FastDFS V3引入合併存儲(trunk file)特性後,有用戶反饋上傳文件提示trunk空間被佔用的問題。我在測試環境中通過一通測試,在極其偶然的狀況下也能重現這個問題。而後就開始排查這個問題。git
FastDFS一個group(存儲分組)內有一臺storage server被選舉爲trunk server,用於管理和分配該組的trunk可用空間。爲了高效管理trunk file的可用空間,咱們使用了平衡二叉樹 AVL。咱們很天然地懷疑trunk空間管理和分配出了bug。因而對管理和分配trunk空間的代碼前先後後作了不下10遍的代碼review,直到看花眼了,也沒有發現任何問題。也懷疑過AVL實現有bug,因而寫單元測試對AVL進行了大量測試,也沒有發現任何問題。微信
這個問題很難復現,嘗試經過代碼review解決,但屢次無功而返。合併存儲這個潛在bug一直存在,致使合併存儲存在風險,我內心很忐忑。
app
到了2017年初,我再次嘗試解決這個困擾多年的bug。既然代碼排查沒有任何效果,那就想辦法重現吧。因而我開始經過小規模壓力測試試圖復現這個問題,經過上傳和刪除文件並行,問題終於獲得復現,而且屢次壓測能夠大機率復現。此次我盯住trunk空間分配的binlog,寫腳本進行分析和排查,發現binlog記錄自己是正確的。但在發生trunk空間衝突的時間點,從binlog中發現一個trunk空間被回收後幾乎當即就被分配出去了,我憑直覺抓住了這條關鍵線索。異步
繼續review代碼,然並卵,依然一無所得。業界有個說法我比較承認:問題可以穩定復現,就等於解決了一大半。在這麼明顯的線索的指引下,我終於轉變了思路,開始思考這個成精的bug是不是多機環境致使的。而後。。。,通過反覆推敲,我終於終於想明白了這個bug是如何被觸發的了:單元測試
多機環境下操做時序問題。測試
之前的排查重心在trunk空間管理,經反覆驗證,這塊是沒問題的。問題在於一個group的多臺storage server都可執行文件上傳操做,而FastDFS對文件操做分發(複製)到其餘存儲節點採用異步方式,一個trunk空間的回收和再利用機制自己沒有問題,但storage server在其trunk file上存放用戶上傳的文件時,就可能會因時序問題而致使衝突(trunk server返回該空間可用,但因文件同步延遲致使實際還在被其餘文件佔用)。具體如何引發亂序和衝突的,留給各位讀者去思考。spa
問題的現象和緣由找到後,解決方法就很容易了:指定group中的一臺storage server上傳文件便可。FastDFS默認配置是輪流(round robin)上傳到各臺storage server的,經過tracker.conf配置文件中的store_server這個參數來設置。貼一下配置示例:.net
# which storage server to upload fileserver
# 0: round robin (default)ip
# 1: the first server order by ip address
# 2: the first server order by priority (the minimal)
# Note: if use_trunk_file set to true, must set store_server to 1 or 2
store_server=0
千萬不要小看Note這一句話,其背後是滿滿的辛酸和血淚啊!
補充說明一下,在開啓合併存儲,即use_trunk_file設置爲true的狀況下,爲了不上述亂序問題,若store_server設置爲0的話,程序將強制調整爲1。
V3最後一個版本是V3.11,經過查看HISTORY文件,其發佈日期爲 2012-08-04。直到2017-03-29,終於修復了trunk文件空間偶發衝突的問題。貼出HISTORY文件中的changelog爲證(git log也能夠查到):
Version 5.10 2017-03-29
* adjust parameter store_server when use_trunk_file is true
一個修復了約5年的bug,必須記錄在案。
本文分享自微信公衆號 - FastDFS分享與交流(fastdfs100)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。