Ceph 後端IO提交異步化

前言

從15年3月接觸Ceph分佈式存儲系統,至今已經5年了;因爲工作的需要,對Ceph的主要模塊進行了較深入的學習,也在Ceph代碼層面做了些許改進,以滿足業務需要(我們主要使用M版本)。最近得閒,將過往的一些改進以及優化思路記錄下了,希望能對後來者有所幫助。

這是第二篇:Ceph 後端IO提交異步化

背景知識

Ceph的IO寫入包括寫Rocksdb元數據和寫Block數據兩部分,等各個副本寫完元數據即給客戶端返回應答。如果是小IO,會現將元數據和數據打包寫入Rocksdb,之後通過deferred IO的形式將數據寫入Block設備,如果是大IO,會將元數據寫入Rocksdb,數據以aio的方式寫入Block設備。在整個IO過程中,OSD拿着PG 鎖,直到元數據提交到Rocksdb才釋放鎖,在次過程中,該PG中後續的IO,都排隊等待

Ceph OSD 進行IO時,以PG爲粒度加鎖,來保證一致性;在PG內,通過爲每個IO事務分配一個OpSeqencer來保證IO的串行執行。

每個OSD 包含一個Rocksdb實例,BlueStore通過一個獨立的線程來完成元數據的提交以及Block設備的flush。

優化思路

  1. IO事務分段處理,提前是否PG鎖
    既然PG是通過OpSeqencer來保證IO的串行執行,那麼在BlueStore爲IO事務分配好了序列號,而不需要等到IO提交到Rocksdb就可以釋放PG 鎖。

處理思路:OSD通過線程池和data shard隊列來提供並行性,使得不同data shard中的IO可以併發的執行;我們可以在BlueStore中同樣啓動一個線程池和隊列,當IO事務分配好OpSeqencer後,將事務提交到隊列,並釋放PG鎖;通過將IO事務的提交分爲兩個階段,OSD可以繼續處理後續的IO,而IO提交的工作交給BlueStore來處理。

  1. 關閉Rocksdb WAL,自維護WAL
    BlueStore準備好IO事務後,將事務投遞到kv_queue中,通過一個線程來完成IO元數據的提交以及Block設備的flush:調用rocksdb的sync操作持久化WAL,調用block的flush操作刷新buffer cache。BlueStore只能通過一個線程來完成IO元數據的提交,是因爲一個rocksdb實例,因爲要寫WAL,需要串行執行。如果我們關閉rocksdb的WAL,而自己維護WAL(WAL使用來做故障恢復的,所以關閉rocksdb的wal後,需要自維護WAL來保證數據一致性),那麼通過多線程提交元數據應該會有更好的性能。

處理思路:配置rocksdb屬性,關閉WAL;使用獨立的SSD設備承載自維護WAL,將WAL磁盤劃分爲多個分區,每個WAL分區大小配置爲2*(write_buffer_size * max_write_buffer_number)。根據配置的OSD io線程數,配置WAL線程數。這樣調整後,不同線程處理的PG 可以同時提交,可以提高併發度。

Tips:上述修改有一定複雜度的,需要修改open_db中wal的處理邏輯,故障恢復下replay的邏輯,添加bluestore threadpool以及io隊列,另外,io中需要先寫wal,再寫db,才能返回。

通過上述修改後,寫IO性能有15%以上的提升。

本文只提供可行的實現思路,不提供具體的實現代碼及細節,如有不清楚的地方,歡迎留言。

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