Ceph是一個分佈式存儲系統,誕生於2004年,最先致力於開發下一代高性能分佈式文件系統的項目。隨着雲計算的發展,ceph乘上了OpenStack的春風,進而成爲了開源社區受關注較高的項目之一。
Ceph有如下優點:mysql
Crush算法是ceph的兩大創新之一,簡單來講,ceph摒棄了傳統的集中式存儲元數據尋址的方案,轉而使用CRUSH算法完成數據的尋址操做。CRUSH在一致性哈希基礎上很好的考慮了容災域的隔離,可以實現各種負載的副本放置規則,例如跨機房、機架感知等。Crush算法有至關強大的擴展性,理論上支持數千個存儲節點。linux
Ceph中的數據副本數量能夠由管理員自行定義,並能夠經過CRUSH算法指定副本的物理存儲位置以分隔故障域,支持數據強一致性; ceph能夠忍受多種故障場景並自動嘗試並行修復。redis
Ceph不一樣於swift,客戶端全部的讀寫操做都要通過代理節點。一旦集羣併發量增大時,代理節點很容易成爲單點瓶頸。Ceph自己並無主控節點,擴展起來比較容易,而且理論上,它的性能會隨着磁盤數量的增長而線性增加。算法
Ceph支持三種調用接口:對象存儲
,塊存儲
,文件系統掛載
。三種方式能夠一同使用。在國內一些公司的雲環境中,一般會採用ceph做爲openstack的惟一後端存儲來提高數據轉發效率。sql
Ceph的底層是RADOS,RADOS自己也是分佈式存儲系統,CEPH全部的存儲功能都是基於RADOS實現。RADOS採用C++開發,所提供的原生Librados API包括C和C++兩種。Ceph的上層應用調用本機上的librados API,再由後者經過socket與RADOS集羣中的其餘節點通訊並完成各類操做。數據庫
RADOS GateWay、RBD其做用是在librados庫的基礎上提供抽象層次更高、更便於應用或客戶端使用的上層接口。其中,RADOS GW是一個提供與Amazon S3和Swift兼容的RESTful API的gateway,以供相應的對象存儲應用開發使用。RBD則提供了一個標準的塊設備接口,經常使用於在虛擬化的場景下爲虛擬機建立volume。目前,Red Hat已經將RBD驅動集成在KVM/QEMU中,以提升虛擬機訪問性能。這兩種方式目前在雲計算中應用的比較多。swift
CEPHFS則提供了POSIX接口,用戶可直接經過客戶端掛載使用。它是內核態的程序,因此無需調用用戶空間的librados庫。它經過內核中的net模塊來與Rados進行交互。用於集羣中全部數據與對象的存儲。處理集羣數據的複製、恢復、回填、再均衡。並向其餘osd守護進程發送心跳,而後向Mon提供一些監控信息。
當Ceph存儲集羣設定數據有兩個副本時(一共存兩份),則至少須要兩個OSD守護進程即兩個OSD節點,集羣才能達到active+clean狀態。後端
爲Ceph文件系統提供元數據計算、緩存與同步。在ceph中,元數據也是存儲在osd節點中的,mds相似於元數據的代理緩存服務器。MDS進程並非必須的進程,只有須要使用CEPHFS時,才須要配置MDS節點。緩存
不管使用哪一種存儲方式(對象、塊、掛載),存儲的數據都會被切分紅對象(Objects)。Objects size大小能夠由管理員調整,一般爲2M或4M。每一個對象都會有一個惟一的OID,由ino與ono生成,雖然這些名詞看上去很複雜,其實至關簡單。ino便是文件的File ID,用於在全局惟一標示每個文件,而ono則是分片的編號。好比:一個文件FileID爲A,它被切成了兩個對象,一個對象編號0,另外一個編號1,那麼這兩個文件的oid則爲A0與A1。Oid的好處是能夠惟一標示每一個不一樣的對象,而且存儲了對象與文件的從屬關係。因爲ceph的全部數據都虛擬成了整齊劃一的對象,因此在讀寫時效率都會比較高。服務器
可是對象並不會直接存儲進OSD中,由於對象的size很小,在一個大規模的集羣中可能有幾百到幾千萬個對象。這麼多對象光是遍歷尋址,速度都是很緩慢的;而且若是將對象直接經過某種固定映射的哈希算法映射到osd上,當這個osd損壞時,對象沒法自動遷移至其餘osd上面(由於映射函數不容許)。爲了解決這些問題,ceph引入了歸置組的概念,即PG。
PG是一個邏輯概念,咱們linux系統中能夠直接看到對象,可是沒法直接看到PG。它在數據尋址時相似於數據庫中的索引:每一個對象都會固定映射進一個PG中,因此當咱們要尋找一個對象時,只須要先找到對象所屬的PG,而後遍歷這個PG就能夠了,無需遍歷全部對象。並且在數據遷移時,也是以PG做爲基本單位進行遷移,ceph不會直接操做對象。
對象時如何映射進PG的?還記得OID麼?首先使用靜態hash函數對OID作hash取出特徵碼,用特徵碼與PG的數量去模,獲得的序號則是PGID。因爲這種設計方式,PG的數量多寡直接決定了數據分佈的均勻性,因此合理設置的PG數量能夠很好的提高CEPH集羣的性能並使數據均勻分佈。
最後PG會根據管理員設置的副本數量進行復制,而後經過crush算法存儲到不一樣的OSD節點上(實際上是把PG中的全部對象存儲到節點上),第一個osd節點即爲主節點,其他均爲從節點。
上圖中更好的詮釋了ceph數據流的存儲過程,數據不管是從三中接口哪種寫入的,最終都要切分紅對象存儲到底層的RADOS中。邏輯上經過算法先映射到PG上,最終存儲近OSD節點裏。圖中除了以前介紹過的概念以外多了一個pools的概念。
Pool是管理員自定義的命名空間,像其餘的命名空間同樣,用來隔離對象與PG。咱們在調用API存儲即便用對象存儲時,須要指定對象要存儲進哪個POOL中。除了隔離數據,咱們也能夠分別對不一樣的POOL設置不一樣的優化策略,好比副本數、數據清洗次數、數據塊及對象大小等。
Ceph的讀寫操做採用主從模型,客戶端要讀寫數據時,只能向對象所對應的主osd節點發起請求。主節點在接受到寫請求時,會同步的向從OSD中寫入數據。當全部的OSD節點都寫入完成後,主節點纔會向客戶端報告寫入完成的信息。所以保證了主從節點數據的高度一致性。而讀取的時候,客戶端也只會向主osd節點發起讀請求,並不會有相似於數據庫中的讀寫分離的狀況出現,這也是出於強一致性的考慮。因爲全部寫操做都要交給主osd節點來處理,因此在數據量很大時,性能可能會比較慢,爲了克服這個問題以及讓ceph能支持事物,每一個osd節點都包含了一個journal文件,稍後介紹。
數據流向介紹到這裏就告一段落了,如今終於回到正題:osd進程。在ceph中,每個osd進程均可稱做是一個osd節點,也就是說,每臺存儲服務器上可能包含了衆多的osd節點,每一個osd節點監聽不一樣的端口,相似於在同一臺服務器上跑多個mysql或redis。每一個osd節點能夠設置一個目錄做爲實際存儲區域,也能夠是一個分區,一整塊硬盤。以下圖,當前這臺機器上跑了兩個osd進程,每一個osd監聽4個端口,分別用於接收客戶請求、傳輸數據、發送心跳、同步數據等操做。
如上圖所示,osd節點默認監聽tcp的6800到6803端口,若是同一臺服務器上有多個osd節點,則依次日後排序。
在生產環境中的osd最少可能都有上百個,因此每一個osd都有一個全局的編號,相似osd0,osd1,osd2........序號根據osd誕生的順序排列,而且是全局惟一的。存儲了相同PG的osd節點除了向mon節點發送心跳外,還會互相發送心跳信息以檢測pg數據副本是否正常。
默認大小爲5G,也就說每建立一個osd節點,還沒使用就要被journal佔走5G的空間。這個值是能夠調整的,具體大小要依osd的總大小而定。
Journal的做用相似於mysql innodb引擎中的事物日誌系統。當有突發的大量寫入操做時,ceph能夠先把一些零散的,隨機的IO請求保存到緩存中進行合併,而後再統一貫內核發起IO請求。這樣作效率會比較高,可是一旦osd節點崩潰,緩存中的數據就會丟失,因此數據在還未寫進硬盤中時,都會記錄到journal中,當osd崩潰後從新啓動時,會自動嘗試從journal恢復因崩潰丟失的緩存數據。所以journal的io是很是密集的,並且因爲一個數據要io兩次,很大程度上也損耗了硬件的io性能,因此一般在生產環境中,使用ssd來單獨存儲journal文件以提升ceph讀寫性能。
Mon節點監控着整個ceph集羣的狀態信息,監聽於tcp的6789端口。每個ceph集羣中至少要有一個Mon節點,官方推薦每一個集羣至少部署三臺。Mon節點中保存了最新的版本集羣數據分佈圖(cluster map)的主副本。客戶端在使用時,須要掛載mon節點的6789端口,下載最新的cluster map,經過crush算法得到集羣中各osd的IP地址,而後再與osd節點直接創建鏈接來傳輸數據。因此對於ceph來講,並不須要有集中式的主節點用於計算與尋址,客戶端分攤了這部分工做。並且客戶端也能夠直接和osd通訊,省去了中間代理服務器的額外開銷。
Mon節點之間使用Paxos算法來保持各節點cluster map的一致性;各mon節點的功能整體上是同樣的,相互間的關係能夠被簡單理解爲主備關係。若是主mon節點損壞,其餘mon存活節點超過半數時,集羣還能夠正常運行。當故障mon節點恢復時,會主動向其餘mon節點拉取最新的cluster map。
Mon節點並不會主動輪詢各個osd的當前狀態,相反,osd只有在一些特殊狀況纔會上報本身的信息,日常只會簡單的發送心跳。特殊狀況包括:一、新的OSD被加入集羣;二、某個OSD發現自身或其餘OSD發生異常。Mon節點在收到這些上報信息時,則會更新cluster map信息並加以擴散。
cluster map信息是以異步且lazy的形式擴散的。monitor並不會在每一次cluster map版本更新後都將新版本廣播至全體OSD,而是在有OSD向本身上報信息時,將更新回覆給對方。相似的,各個OSD也是在和其餘OSD通訊時,若是發現對方的osd中持有的cluster map版本較低,則把本身更新的版本發送給對方。
Mds是ceph集羣中的元數據服務器,而一般它都不是必須的,由於只有在使用cephfs的時候才須要它,而目在雲計算中用的更普遍的是另外兩種存儲方式。
Mds雖然是元數據服務器,可是它不負責存儲元數據,元數據也是被切成對象存在各個osd節點中的,以下圖:
在建立CEPHFS時,要至少建立兩個POOL,一個用於存放數據,另外一個用於存放元數據。Mds只是負責接受用戶的元數據查詢請求,而後從osd中把數據取出來映射進本身的內存中供客戶訪問。因此mds其實相似一個代理緩存服務器,替osd分擔了用戶的訪問壓力,以下圖: