配置引數
在工程實踐中,我們通常把一些需要測量才能確定最佳取值的引數以可配置的形式處理,但實際上大部分的引數可能只是乙個可行值,而不是乙個最佳值。
1. ds與ns之間的心跳間隔設定:ns通過心跳來確定ds的狀態,心跳間隔太短,ns容易出現誤判,有時短暫的網路斷開也會被ns認定為ds宕機;而心跳間隔過長,ns就不能及時發現宕機的ds,導致的問題是,ns複製丟失block的時間點會被延遲,影響系統的可靠性;同時很多請求仍然被引導到已經宕機的ds上,最終會導致客戶端的重試,影響系統的請求響應時間。線上這個值配置為2s,為什麼是2s,不是1s,3s,甚至5s、10s,或是根據系統負載狀態動態調整。
2. 塊大小:64m的block大小是業界的乙個經典配置,為什麼是64m我也不得而知,可能是因為開山鼻祖gfs是64m吧。後來由於「歷史原因」,tfs塊大小變成72m,72m的block執行起來也很好,block大小會影響到哪些點呢? block越大,block的元資料相對就越少,乙個block內能存放的檔案就越多,複製block的時間就會變長。
3. 擴充套件塊大小及數量:擴充套件block主要用於解決檔案更新問題,目前配置擴充套件塊大小為4m,數量是主塊的2倍,平均乙個主塊分配2個擴充套件塊,但實際上線上擴充套件塊使用很少,主要是因為業務更新需求很少,絕大部分的寫是新建,而不是更新,也就是說大部分的擴充套件塊都浪費了,是不是應該預留更少的擴充套件塊,萬一預留的塊太少,當業務需要更新時又滿足不了怎麼辦。 出現上述問題的主要還是設計不夠好的原因,如果任意block都能即當主塊又能當擴充套件塊使用,問題就迎仍而解了。
4. 集群平均檔案大小設定:這個配置決定block中平均能存多少個檔案,然後合理為index分配hash桶數,但我發現這個配置在所有集群中、都是40k,包括大檔案集群(實際平均檔案大小接近2m)。
5. 均衡因子: ns根據ds占用的儲存空間比例來做負載均衡,個人認為這樣是合理的,對於一台正常的server來說(不是計算密集型或是io密集型),其各個部件的配置應該是相互協調的,所以儲存空間從很大程度上反映了server的計算處理能力,那麼通過儲存來反映其服務能力也是合理的。目前線上的均衡因子為1%,當某一台server的儲存使用率與所有server平均儲存使用率之差超過1%時,就要進行block遷移,最終達到乙個高度平均的狀態,因為條件比較苛刻,所以資料遷移操作很頻繁,個人認為設定在5%-10%間更加合理。
集群同步
tfs採用主備集群的方式來實現異地機房容災,具體實現是在主集群所有的ds(dataserer)上配置備集群ns(nameserver)的資訊,主集群上的ds在寫、刪除、更新檔案的操作成功後會寫binlog,ds會在後台重放binlog,把這些操作應用到備集群上,從而實現主備集群的資料同步,由於binlog重放是非同步的,所以主備集群的資料不能保證實時一致。同步是線上經常出問題的點,而且經常需要人工介入處理。
1. 最初我們按操作重放,某個操作如果同步不成功,會一直重試,整個同步佇列會阻塞知道該操作同步成功,這樣設計的主要原因在於,很多失敗只是暫時性,比如備集群上的ns短暫性繁忙,或是系統公升級等,這些問題會在短時間內恢復,所以只要同步一直重試,大部分的操作最終是會成功的,不需要人工介入處理;但顯然這個設計存在很多不合理的地方, 比如某個同步操作阻塞後,後續的同步將一直累積,當某一時刻同步恢復後,累積的許多操作就會迅速壓到備集群上,影響到備集群的穩定性。
2. 針對上述問題,重試是為了避免臨時性失敗,那麼只要控制重試次數和時間即可,於是把同步的策略改成重試有限次數,並且在重試時把同步檔案操作改為同步檔案最終狀態,進一步提高了同步的成功率。
由於磁碟本身是不可靠的,如果在binlog重放前,存放binlog的磁碟壞了,那麼binlog就會丟失,所有未重放的操作也就丟失了;另外對於上面提到重試有限次數仍失敗的檔案,能否避免每次人工介入處理。為了應付這些異常情況,我們開發了一系列的輔助同步工具,包括集群全量同步工具,集群增量同步工具,block同步工具,檔案同步工具,分別在不同的場景運用。比如通過每日的增量同步任務,就能解決那些binlog丟失或是同步失敗的情況。
假設binlog不會丟失,有哪些原因會導致同步失敗?
1. 主或備集群本身出問題,對同步的影響千奇百怪,但出現的頻度不高。
2. 集群內副本不一致,比如某個檔案先後進行了寫、刪除操作,在寫操作時,備集群上只有乙個副本active,另乙個故障或是正在公升級等,這時寫操作只會應用到乙個副本上,當應用刪除操作時,另乙個副本已經啟動並成為主副本,那麼接下來應用刪除操作時,因為檔案在主副本上不存在,所以刪除會失敗。出現這個的主要原因是對於更新操作,為了提高成功率,即使副本數不足時,也允許更新。
一致性與負載均衡
tfs採用w=n, r=1的強一致性演算法,但實際實現的時候,使用了取巧的辦法,比如有3個副本,我們只寫成功了1個,這時返回給客戶端是失敗的,但系統不會對寫成功的那個副本就行回滾,但因為返回客戶端是失敗的,客戶端也就得不到檔名,也不會訪問到這個檔案,所以這裡的一致只是邏輯上的一致;另外,在刪除和更新時,也可能出現部分副本更新成功,部分副本更新失敗,最終檔案的多個副本是不一致的,但因為系統大部分的檔案都是寫一次就不會再更改,即更新操作很少,更新失敗就更少了,而且上層的業務能接受這種不一致,也沒有在這塊做更多的工作。後續為了減少不一致帶來的不確定性,將會在發現這種不一致時,複製最高版本的block,刪除低版本的副本,最終使得所有的副本處於一致的狀態。
當讀取時,客戶端會隨機選擇乙個副本讀取檔案資料,關於這點,有兩種不同意見,有人認為這樣是合理的,客戶端的讀請求會分散到多個副本;有人認為讀請求應該始終向主副本請求,首先主副本上的資料一定是最新的,同時又能充分利用linux os的page cache以減少磁碟io,因為block的主副本是均衡分布在各個ds上的,所以總體看來各個ds間的負載也是均衡的。
運維
個人認為在大的網際網路,運維規範化是至關重要的,最近線上問題中有跟運維相關的問題,因為發現比較及時,沒造成什麼影響。一是在ds公升級的過程中,有乙個機器的安裝新程式沒有成功,導致這台機器只是簡單的重啟了dataserver,而沒有公升級程式;另外乙個是在新增備集群時,遺漏了port資訊,導致上線後,往備集群的同步一直失敗。前者可通過在公升級時加強檢查避免,比如先計算待公升級的ds的md5sum,在公升級時檢查啟動的ds md5是否匹配,如果不匹配則給出告警資訊;後者則只能通過上線前進行充分的測試來避免。
監控
監控對系統更好的執行是必不可少的,通過監控發現問題,開發解決問題,公升級上線,如此往復,使系統不斷趨於乙個穩定執行的狀態。最開始為了滿足監控需求,我們開發了admin server,admin server會可以監控ns,ds的執行狀態,當發現ds程序crash時(通常是由於程式bug導致程序coredump或是磁碟壞掉等),會自動把程序重啟起來,因為如果不自動重啟,等人工介入處理,我們需要等待故障發現時間,處理時間,等ds恢復後,可能ns早已把該ds上的block都複製了乙份,這時ds再加入已經沒有任何意義了。使用這種方法,我們應該對線上的coredump檔案進行監控,因為程序coredump後會立即被admin server啟動起來工作,監控可能根本發現不了ds出過問題,於是要想開發盡快發現問題,對於新產生的core檔案,要能及時通知到開發人員進行除錯分析。最近由於不知名的原因,admin server都下線了,甚是懷念,很多重啟能解決的問題現在必須人工介入。
工程實現
系統設計和最終工程實現出來的產品,可能多少有些差距,最初的開發人員留下一堆todo就直接上線了,後面的開發人員不斷移除這些todo,加入自己的**,而開發經常遇到的乙個問題就是,由於之前實現遺留的歷史原因,自己不得不加入一些很ugly的**,這樣當下乙個開發人員接手時,情況就變得更糟,形成惡性迴圈;這種問題只能通過統一編碼風格,加強開發人員間code review等方式來適當緩解,很難做到完全避免。
TFS 解決TFS編譯中文亂碼問題
前言 tfs2018做程式整合非常方便,線上編譯然後直接生成docker映象,但是在使用過程中遇到編譯視窗中文亂碼的問題,這個問題找了好久沒人知道怎麼解決。如下 這個問題不解決,每次編譯失敗,研發都過來問什麼原因,這裡中文亂碼,自己還得去tfs伺服器自己編譯一次,檢視具體錯誤原因。這個問題解決完了,...
TFS 恢復備份若干問題
環境 tfs 2012 update 1 問題1 備份資料庫源存放於網路路徑,恢復資料庫遇到錯誤 network not found 原因 恢復操作最後一步需要寫入備份配置檔案,由於沒有許可權導致失敗 backups.xml configpt.xml 問題2 恢復資料庫後,配置報表失敗,開啟瀏覽器檢...
TFS新機器上線問題
昨天下午線上輔集群加機器擴容,擴容的機器在執行一段時間後線上有block lost的告警,從nameserver ns 的日誌上發現,擴容的新機器上有多次加入集群和退出集群的記錄,最初我懷疑是擴容後,集群做容量負載均衡,大量資料往新加入的節點遷移,導致新機器負載高,從而出現心跳資訊沒有及時到達ns的...