精品国产一级在线观看,国产成人综合久久精品亚洲,免费一级欧美大片在线观看

當前位置:存儲技術專區 → 正文

如何基于 Ceph 攻破海量小文件存儲難題

責任編輯:editor005 |來源:企業網D1Net  2015-10-21 14:31:16 本文摘自:博客園

海量小文件存儲(簡稱LOSF,lots of small files)出現后,就一直是業界的難題,眾多博文(如 [1] )對此問題進行了闡述與分析,許多互聯網公司也針對自己的具體場景研發了自己的存儲方案(如taobao開源的 TFS ,facebook自主研發的 Haystack ),還有一些公司在現有開源項目(如hbase,fastdfs,mfs等)基礎上做針對性改造優化以滿足業務存儲需求;

一. 海量小文件存儲側重于解決的問題

通過對若干分布式存儲系統的調研、測試與使用,與其它分布式系統相比,海量小文件存儲更側重于解決兩個問題:

1. 海量小文件的元數據信息組織與管理: 對于百億量級的數據,每個文件元信息按100B計算,元信息總數據量為1TB,遠超過目前單機服務器內存大小;若使用本地持久化設備存儲,須高效滿足每次 文件存取請求的元數據查詢尋址(對于上層有cdn的業務場景,可能不存在明顯的數據熱點),為了避免單點,還要有備用元數據節點;同時,單組元數據服務器 也成為整個集群規模擴展的瓶頸;或者使用獨立的存儲集群存儲管理元數據信息,當數據存儲節點的狀態發生變更時,應該及時通知相應元數據信息進行變更;

對此問題,tfs/fastdfs設計時,就在文件名中包含了部分元數據信息,減小了元數據規模,元數據節點只負責管理粒度更大的分片結構信息; 商用分布式文件系統龍存,通過升級優化硬件,使用分布式元數據架構——多組(每組2臺)高性能ssd服務器——存儲集群的元數據信息,滿足單次io元數據 查詢的同時,也實現了元數據存儲的擴展性;Haystack Directory模塊提供了圖片邏輯卷到物理卷軸的映射存儲與查詢功能,使用Replicated Database存儲,并通過cache集群來降低延時提高并發,其對外提供的讀qps在百萬量級;

2. 本地磁盤文件的存儲與管理(本地存儲引擎):對于常見的linux文件系統,讀取一個文件通常需要三次磁盤IO(讀取目錄元數據到內存,把文件的 inode節點裝載到內存,最后讀取實際的文件內容);按目前主流2TB~4TB的sata盤,可存儲2kw~4kw個100KB大小的文件,由于文件數 太多,無法將所有目錄及文件的inode信息緩存到內存,很難實現每個圖片讀取只需要一次磁盤IO的理想狀態,而長尾現象使得熱點緩存無明顯效果;當請求 尋址到具體的一塊磁盤,如何減少文件存取的io次數,高效地響應請求(尤其是讀)已成為需要解決的另一問題;

對此問題,有些系統(如tfs,Haystack)采用了小文件合并存儲+索引文件的優化方案,此方案有若干益處:a.合并后的合并大文件通常在 64MB,甚至更大,單盤所存存儲的合并大文件數量遠小于原小文件的數量,其inode等信息可以全部被cache到內存,減少了一次不必要的磁盤 IO;b.索引文件通常數據量(通常只存儲小文件所在的合并文件,及offset和size等關鍵信息)很小,可以全部加載到內存中,讀取時先訪問內存索 引數據,再根據合并文件、offset和size訪問實際文件數據,實現了一次磁盤IO的目的;c.單個小文件獨立存儲時,文件系統存儲了其guid、屬 主、大小、創建日期、訪問日期、訪問權限及其它結構信息,有些信息可能不是業務所必需的,在合并存儲時,可根據實際需要對文件元數據信息裁剪后在做合并, 減少空間占用。除了合并方法外,還可以使用性能更好的SSD等設備,來實現高效響應本地io請求的目標。

當然,在合并存儲優化方案中,刪除或修改文件操作可能無法立即回收存儲空間,對于存在大量刪除修改的業務場景,需要再做相應的考量。

二. 海量小文件存儲與Ceph實踐

Ceph 是近年越來越被廣泛使用的分布式存儲系統,其重要的創新之處是基于 CRUSH 算法的計算尋址,真正的分布式架構、無中心查詢節點,理論上無擴展上限(更詳細ceph介紹見網上相關文章);Ceph的基礎組件RADOS本身是對象存 儲系統,將其用于海量小文件存儲時,CRUSH算法直接解決了上面提到的第一個問題;不過Ceph OSD目前的存儲引擎( Filestore , KeyValuestore )對于上面描述的海量小文件第二個問題尚不能很好地解決;ceph社區曾對此問題做過描述并提出了基于rgw的一種 方案 (實際上,在實現本文所述方案過程中,發現了社區上的方案),不過在最新代碼中,一直未能找到方案的實現;

我們在Filestore存儲引擎基礎上對小文件存儲設計了優化方案并進行實現,方案主要思路如下:將若干小文件合并存儲在RADOS系統的一個 對象(object)中,<小文件的名字、小文件在對象中的offset及小文件size>組成kv對,作為相應對象的擴展屬性(或者 omap,本文以擴展屬性表述,ceph都使用kv數據庫實現,如leveldb)進行存儲,如下圖所示,對象的擴展屬性數據與對象數據存儲在同一塊盤上;

海量小文件存儲與Ceph實踐

使用本結構存儲后,write小文件file_a操作分解為: 1)對某個object調用append小文件file_a;2)將小文件file_a在相應object的offset和size,及小文件名字 file_a作為object的擴展屬性存儲kv數據庫。read小文件file_a操作分解為:1)讀取相應object的file_a對應的擴展屬性 值(及offset,size);2)讀取object的offset偏移開始的size長度的數據。對于刪除操作,直接將相應object的 file_a對應的擴展屬性鍵值刪除即可,file_a所占用的存儲空間延遲回收,回收以后討論。另外,Ceph本身是強一致存儲系統,其內在機制可以保 證object及其擴展屬性數據的可靠一致;

由于對象的擴展屬性數據與對象數據存儲在同一塊盤上,小文件的讀寫操作全部在本機本OSD進程內完成,避免了網絡交互機制潛在的問題。另一方面, 對于寫操作,一次小文件寫操作對應兩次本地磁盤隨機io(邏輯層面),且不能更少,某些kv數據庫(如leveldb)還存在write amplification問題,對于寫壓力大的業務場景,此方案不能很好地滿足;不過對于讀操作,我們可以通過配置參數,盡量將kv數據保留在內存中, 實現讀取操作一次磁盤io的預期目標;

如何選擇若干小文件進行合并,及合并存儲到哪個對象中呢?最簡單地方案是通過計算小文件key的hash值,將具有相同hash值的小文件合并存 儲到id為對應hash值的object中,這樣每次存取時,先根據key計算出hash值,再對id為hash值的object進行相應的操作;關于 hash函數的選擇,(1)可使用最簡單的hash取模,這種方法需要事先確定模數,即當前業務合并操作使用的object個數,且確定后不能改變,在業 務數據增長過程中,小文件被平均分散到各個object中,寫壓力被均勻分散到所有object(即所有物理磁盤,假設object均勻分布) 上;object文件大小在一直增長,但不能無限增長,上限與單塊磁盤容量及存儲的object數量有關,所以在部署前,應規劃好集群的容量和hash模 數。(2)對于某些帶目錄層次信息的數據,如/a/b/c/d/efghi.jpg,可以將文件的目錄信息作為相應object的id,及/a/b/c /d,這樣一個子目錄下的所有文件存儲在了一個object中,可以通過rados的listxattr命令查看一個目錄下的所有文件,方便運維使用;另 外,隨著業務數據的增加,可以動態增加object數量,并將之前的object設為只讀狀態(方便以后的其它處理操作),來避免object的無限增 長;此方法需要根據業務寫操作量及集群磁盤數來合理規劃當前可寫的object數量,在滿足寫壓力的前提下將object大小控制在一定范圍內。

本方案是為小文件(1MB及以下)設計的,對于稍大的文件存儲(幾十MB甚至更大),如何使用本方案存儲呢?我們將大文件 large_file_a切片分成若干大小一樣(如2MB,可配置,最后一塊大小可能不足2MB)的若干小塊文 件:large_file_a_0, large_file_a_1 ... large_file_a_N,并將每個小塊文件作為一個獨立的小文件使用上述方案存儲,分片信息(如總片數,當前第幾片,大文件大小,時間等) 附加在每個分片數據開頭一并進行存儲,以便在讀取時進行解析并根據操作類型做相應操作。

根據業務的需求,我們提供如下操作接口供業務使用(c++描述):

int WriteFullObj(const std::string& oid, bufferlist& bl, int create_time = GetCurrentTime());

int Write(const std::string& oid, bufferlist& bl, uint64_t off, int create_time = GetCurrentTime());

int WriteFinish(const std::string& oid, uint64_t total_size, int create_time = GetCurrentTime());

int Read(const std::string& oid, bufferlist& bl, size_t len, uint64_t off);

int ReadFullObj(const std::string& oid, bufferlist& bl, int* create_time = NULL);

int Stat(const std::string& oid, uint64_t *psize, time_t *pmtime, MetaInfo* meta = NULL);

int Remove(const std::string& oid);

int BatchWriteFullObj(const String2BufferlistHMap& oid2data, int create_time = GetCurrentTime());

對于寫小文件可直接使用WriteFullObj;對于寫大文件可使用帶offset的Write,寫完所有數據后,調用 WriteFinish;對于讀取整個文件可直接使用ReadFullObj;對于隨機讀取部分文件可使用帶offset的Read;Stat用于查看文 件狀態信息;Remove用于刪除文件;當使用第二種hash規則時,可使用BatchWriteFullObj提高寫操作的吞吐量。

關鍵字:存儲優化文件操作

本文摘自:博客園

x 如何基于 Ceph 攻破海量小文件存儲難題 掃一掃
分享本文到朋友圈
當前位置:存儲技術專區 → 正文

如何基于 Ceph 攻破海量小文件存儲難題

責任編輯:editor005 |來源:企業網D1Net  2015-10-21 14:31:16 本文摘自:博客園

海量小文件存儲(簡稱LOSF,lots of small files)出現后,就一直是業界的難題,眾多博文(如 [1] )對此問題進行了闡述與分析,許多互聯網公司也針對自己的具體場景研發了自己的存儲方案(如taobao開源的 TFS ,facebook自主研發的 Haystack ),還有一些公司在現有開源項目(如hbase,fastdfs,mfs等)基礎上做針對性改造優化以滿足業務存儲需求;

一. 海量小文件存儲側重于解決的問題

通過對若干分布式存儲系統的調研、測試與使用,與其它分布式系統相比,海量小文件存儲更側重于解決兩個問題:

1. 海量小文件的元數據信息組織與管理: 對于百億量級的數據,每個文件元信息按100B計算,元信息總數據量為1TB,遠超過目前單機服務器內存大小;若使用本地持久化設備存儲,須高效滿足每次 文件存取請求的元數據查詢尋址(對于上層有cdn的業務場景,可能不存在明顯的數據熱點),為了避免單點,還要有備用元數據節點;同時,單組元數據服務器 也成為整個集群規模擴展的瓶頸;或者使用獨立的存儲集群存儲管理元數據信息,當數據存儲節點的狀態發生變更時,應該及時通知相應元數據信息進行變更;

對此問題,tfs/fastdfs設計時,就在文件名中包含了部分元數據信息,減小了元數據規模,元數據節點只負責管理粒度更大的分片結構信息; 商用分布式文件系統龍存,通過升級優化硬件,使用分布式元數據架構——多組(每組2臺)高性能ssd服務器——存儲集群的元數據信息,滿足單次io元數據 查詢的同時,也實現了元數據存儲的擴展性;Haystack Directory模塊提供了圖片邏輯卷到物理卷軸的映射存儲與查詢功能,使用Replicated Database存儲,并通過cache集群來降低延時提高并發,其對外提供的讀qps在百萬量級;

2. 本地磁盤文件的存儲與管理(本地存儲引擎):對于常見的linux文件系統,讀取一個文件通常需要三次磁盤IO(讀取目錄元數據到內存,把文件的 inode節點裝載到內存,最后讀取實際的文件內容);按目前主流2TB~4TB的sata盤,可存儲2kw~4kw個100KB大小的文件,由于文件數 太多,無法將所有目錄及文件的inode信息緩存到內存,很難實現每個圖片讀取只需要一次磁盤IO的理想狀態,而長尾現象使得熱點緩存無明顯效果;當請求 尋址到具體的一塊磁盤,如何減少文件存取的io次數,高效地響應請求(尤其是讀)已成為需要解決的另一問題;

對此問題,有些系統(如tfs,Haystack)采用了小文件合并存儲+索引文件的優化方案,此方案有若干益處:a.合并后的合并大文件通常在 64MB,甚至更大,單盤所存存儲的合并大文件數量遠小于原小文件的數量,其inode等信息可以全部被cache到內存,減少了一次不必要的磁盤 IO;b.索引文件通常數據量(通常只存儲小文件所在的合并文件,及offset和size等關鍵信息)很小,可以全部加載到內存中,讀取時先訪問內存索 引數據,再根據合并文件、offset和size訪問實際文件數據,實現了一次磁盤IO的目的;c.單個小文件獨立存儲時,文件系統存儲了其guid、屬 主、大小、創建日期、訪問日期、訪問權限及其它結構信息,有些信息可能不是業務所必需的,在合并存儲時,可根據實際需要對文件元數據信息裁剪后在做合并, 減少空間占用。除了合并方法外,還可以使用性能更好的SSD等設備,來實現高效響應本地io請求的目標。

當然,在合并存儲優化方案中,刪除或修改文件操作可能無法立即回收存儲空間,對于存在大量刪除修改的業務場景,需要再做相應的考量。

二. 海量小文件存儲與Ceph實踐

Ceph 是近年越來越被廣泛使用的分布式存儲系統,其重要的創新之處是基于 CRUSH 算法的計算尋址,真正的分布式架構、無中心查詢節點,理論上無擴展上限(更詳細ceph介紹見網上相關文章);Ceph的基礎組件RADOS本身是對象存 儲系統,將其用于海量小文件存儲時,CRUSH算法直接解決了上面提到的第一個問題;不過Ceph OSD目前的存儲引擎( Filestore , KeyValuestore )對于上面描述的海量小文件第二個問題尚不能很好地解決;ceph社區曾對此問題做過描述并提出了基于rgw的一種 方案 (實際上,在實現本文所述方案過程中,發現了社區上的方案),不過在最新代碼中,一直未能找到方案的實現;

我們在Filestore存儲引擎基礎上對小文件存儲設計了優化方案并進行實現,方案主要思路如下:將若干小文件合并存儲在RADOS系統的一個 對象(object)中,<小文件的名字、小文件在對象中的offset及小文件size>組成kv對,作為相應對象的擴展屬性(或者 omap,本文以擴展屬性表述,ceph都使用kv數據庫實現,如leveldb)進行存儲,如下圖所示,對象的擴展屬性數據與對象數據存儲在同一塊盤上;

海量小文件存儲與Ceph實踐

使用本結構存儲后,write小文件file_a操作分解為: 1)對某個object調用append小文件file_a;2)將小文件file_a在相應object的offset和size,及小文件名字 file_a作為object的擴展屬性存儲kv數據庫。read小文件file_a操作分解為:1)讀取相應object的file_a對應的擴展屬性 值(及offset,size);2)讀取object的offset偏移開始的size長度的數據。對于刪除操作,直接將相應object的 file_a對應的擴展屬性鍵值刪除即可,file_a所占用的存儲空間延遲回收,回收以后討論。另外,Ceph本身是強一致存儲系統,其內在機制可以保 證object及其擴展屬性數據的可靠一致;

由于對象的擴展屬性數據與對象數據存儲在同一塊盤上,小文件的讀寫操作全部在本機本OSD進程內完成,避免了網絡交互機制潛在的問題。另一方面, 對于寫操作,一次小文件寫操作對應兩次本地磁盤隨機io(邏輯層面),且不能更少,某些kv數據庫(如leveldb)還存在write amplification問題,對于寫壓力大的業務場景,此方案不能很好地滿足;不過對于讀操作,我們可以通過配置參數,盡量將kv數據保留在內存中, 實現讀取操作一次磁盤io的預期目標;

如何選擇若干小文件進行合并,及合并存儲到哪個對象中呢?最簡單地方案是通過計算小文件key的hash值,將具有相同hash值的小文件合并存 儲到id為對應hash值的object中,這樣每次存取時,先根據key計算出hash值,再對id為hash值的object進行相應的操作;關于 hash函數的選擇,(1)可使用最簡單的hash取模,這種方法需要事先確定模數,即當前業務合并操作使用的object個數,且確定后不能改變,在業 務數據增長過程中,小文件被平均分散到各個object中,寫壓力被均勻分散到所有object(即所有物理磁盤,假設object均勻分布) 上;object文件大小在一直增長,但不能無限增長,上限與單塊磁盤容量及存儲的object數量有關,所以在部署前,應規劃好集群的容量和hash模 數。(2)對于某些帶目錄層次信息的數據,如/a/b/c/d/efghi.jpg,可以將文件的目錄信息作為相應object的id,及/a/b/c /d,這樣一個子目錄下的所有文件存儲在了一個object中,可以通過rados的listxattr命令查看一個目錄下的所有文件,方便運維使用;另 外,隨著業務數據的增加,可以動態增加object數量,并將之前的object設為只讀狀態(方便以后的其它處理操作),來避免object的無限增 長;此方法需要根據業務寫操作量及集群磁盤數來合理規劃當前可寫的object數量,在滿足寫壓力的前提下將object大小控制在一定范圍內。

本方案是為小文件(1MB及以下)設計的,對于稍大的文件存儲(幾十MB甚至更大),如何使用本方案存儲呢?我們將大文件 large_file_a切片分成若干大小一樣(如2MB,可配置,最后一塊大小可能不足2MB)的若干小塊文 件:large_file_a_0, large_file_a_1 ... large_file_a_N,并將每個小塊文件作為一個獨立的小文件使用上述方案存儲,分片信息(如總片數,當前第幾片,大文件大小,時間等) 附加在每個分片數據開頭一并進行存儲,以便在讀取時進行解析并根據操作類型做相應操作。

根據業務的需求,我們提供如下操作接口供業務使用(c++描述):

int WriteFullObj(const std::string& oid, bufferlist& bl, int create_time = GetCurrentTime());

int Write(const std::string& oid, bufferlist& bl, uint64_t off, int create_time = GetCurrentTime());

int WriteFinish(const std::string& oid, uint64_t total_size, int create_time = GetCurrentTime());

int Read(const std::string& oid, bufferlist& bl, size_t len, uint64_t off);

int ReadFullObj(const std::string& oid, bufferlist& bl, int* create_time = NULL);

int Stat(const std::string& oid, uint64_t *psize, time_t *pmtime, MetaInfo* meta = NULL);

int Remove(const std::string& oid);

int BatchWriteFullObj(const String2BufferlistHMap& oid2data, int create_time = GetCurrentTime());

對于寫小文件可直接使用WriteFullObj;對于寫大文件可使用帶offset的Write,寫完所有數據后,調用 WriteFinish;對于讀取整個文件可直接使用ReadFullObj;對于隨機讀取部分文件可使用帶offset的Read;Stat用于查看文 件狀態信息;Remove用于刪除文件;當使用第二種hash規則時,可使用BatchWriteFullObj提高寫操作的吞吐量。

關鍵字:存儲優化文件操作

本文摘自:博客園

電子周刊
回到頂部

關于我們聯系我們版權聲明隱私條款廣告服務友情鏈接投稿中心招賢納士

企業網版權所有 ©2010-2024 京ICP備09108050號-6 京公網安備 11010502049343號

^
  • <menuitem id="jw4sk"></menuitem>

    1. <form id="jw4sk"><tbody id="jw4sk"><dfn id="jw4sk"></dfn></tbody></form>
      主站蜘蛛池模板: 余姚市| 丹寨县| 龙川县| 盈江县| 丘北县| 宁波市| 桑日县| 嫩江县| 浦城县| 桑日县| 额敏县| 堆龙德庆县| 郑州市| 德庆县| 延安市| 柳州市| 宜昌市| 丽水市| 邯郸市| 永川市| 上高县| 康乐县| 邯郸市| 霞浦县| 吉木萨尔县| 金坛市| 余庆县| 台湾省| 双鸭山市| 资源县| 封丘县| 鄯善县| 靖州| 疏勒县| 阜康市| 苍山县| 家居| 桂林市| 文山县| 东乡| 台前县|