本文分析ceph的10.X版本的配額功能。主要以儲存池配額為例,分析一下配額功能的完備性。
現狀
功能和配置:
通過設定儲存池的最大物件數和最大位元組數,當達到限額時,則不允許寫入。
ceph osd pool set-quota <poolname> max_objects|max_bytes <val>
ceph osd pool get-quota <poolname>
原理和實現:
通過定時檢測,條件滿足時通過設定osdmap的CEPH_OSDMAP_FULL標誌來共享池空間滿的資訊。
在osd的prepare_transaction處判斷標誌,並根據需要返回錯誤碼。
對於配額功能一般返回-EDQUOT或-ENOSPC錯誤碼
對於暫時無法處理需要丟棄的操作,則返回-EAGAIN錯誤碼。
問題分析:
從實現上可以看出,由於客戶端和osd缺乏完備的通訊機制,對於儲存池滿的情況,ceph只是簡單的放在了服務後端osd層面進行處理並返回預期的EDQUOT錯誤碼。
但是這樣處理有一些問題。比如在ceph kclient中,存在使用頁面快取的情況,使用者的io先寫入快取,再非同步通過系統自動sync向osd發起同步請求。這時如果是pool full,osd如果返回eagain錯誤碼,則會造成不斷重試,並造成io阻塞。如果返回edquot,則資料實質上沒有寫入成功,但是使用者層面的操作卻是成功的,造成資料不一致和資料丟失。
優化
從問題分析得出,可以把判斷配額限制的處理前移到客戶端,由客戶端收集滿足配額條件,比如儲存池配額滿的情況,當配額條件觸發後,返回EDQUOT錯誤碼。
同時,對於一些不會造成系統重大影響的軟性配額,osd層面應該適當放開pool full的檢測,允許業務正常處理,這樣當一些客戶端的非同步io請求觸發時,不會被丟棄掉。這樣的錯誤會導致配額功能有一定的誤差,但是在檢測週期內,一般也是允許的,沒有什麼大影響。