Linux運維---1.Ceph分散式存儲架構及工作原理

来源:https://www.cnblogs.com/shiyw/archive/2020/02/27/12372990.html
-Advertisement-
Play Games

Ceph理論 1. Ceph 簡介 Ceph 是一個開源項目,它提供軟體定義的、統一的存儲解決方案 。Ceph 是一個具有高性能、高度可伸縮性、可大規模擴展並且無單點故障的分散式存儲系統 。 Ceph 是軟體定義存儲解決方案 Ceph 是統一存儲解決方案 Ceph 是雲存儲解決方案 Ceph 官方文 ...


Ceph理論

  1. Ceph 簡介

Ceph 是一個開源項目,它提供軟體定義的、統一的存儲解決方案 。Ceph 是一個具有高性能、高度可伸縮性、可大規模擴展並且無單點故障的分散式存儲系統 。

Ceph 是軟體定義存儲解決方案
Ceph 是統一存儲解決方案
Ceph 是雲存儲解決方案
Ceph 官方文檔:http://docs.ceph.com/docs/mimic/

  1. Ceph 的架構:分散式服務進程

2.1 Ceph Monitor(MON)

Ceph 監視器服務進程,簡稱 MON。負責監控集群的監控狀態,所有的集群節點都向 MON 節點報告狀態以及每個狀態變化的信息。MON 通過收集這些信息並維護一個 Cluster Map 來完成它的任務。Cluster Map 下屬包含每個組件的 Map,例如:MON Map、OSD Map、PG Map、CRUSH Map 和 MDS Map。一個典型的 Cepb 集群中通常存在多個 MON 節點,它們之間啟用了仲 裁(Quorum)這種分散式決策機制,應用 Paxos 演算法保持各節點 Cluster Map 的一致性。所以集群中 MON 節點數應該是一個奇數,開始仲裁操作時至少要保證有一半以上的 MON 處於可用狀態,這樣才可以防止傳統存儲系統中常見的腦裂問題。OSD 只有在一些特殊情況(e.g. 添加新的 OSD、OSD 發現自身或他人存在異常)才會上報自己的信息,平常只會簡單的發送心跳。MON 在收到這些上報信息時,則會更新 Cluster Map 並加以擴散。

MON Map:維護著 MON 節點間端到端的信息。包括 Ceph Cluster ID、MON hostname、IP:Port 以及當前 MON Map 的創建版本和最後一次修改信息,幫助確定集群應該遵循哪個版本。
OSD Map:維護著 Ceph Cluster ID、OSD 數目、狀態、權重、主機、以及 Pool 相關的信息(e.g. Pool name、Pool ID、Pool Type、副本數、PG ID),以及存儲了 OSD map 創建版本和最後一次修改信息。
PG Map :維護著 PG 的版本、時間戳、容量比例、最新的 OSD Map 版本、PG ID、對象數、OSD 的 Up Set、OSD 的 Acting Set、Clean 狀態等信息。
CRUSH Map:維護著集群的存儲設備信息、故障域層次結構以及在故障域中如何存儲數據的規則定義。
MDS Map:維護著元數據池 ID、MDS 數量、狀態、創建時間和當前的 MDS Map 版本等信息。

2.2 Ceph Object Storage Device Daemon(OSD)

Ceph 對象存儲設備服務進程,簡稱 OSD。一個 OSD 守護進程與集群中的一個物理磁碟綁定,OSD 負責將數據以 Object 的形式存儲在這些物理磁碟中,併在客戶端發起數據請求時提供相同的數據。一般來說,物理磁碟的 總數與 Ceph 集群中負責存儲用戶數據到每個物理磁碟的 OSD 守護進程數是相等的。OSD 同時還負責處理數據複製、數據恢復、數據再平衡以及通過心跳機制監測其它 OSD 狀況並報告給 MON。對於任何 R/W 操作,客戶端首先向 MON 請求集群的 Map,然後客戶端就可以直接與 OSD 進行 I/O 操作。正是因為客戶端能夠直接與 OSD 進行操作而不需要額外的數據處理層,才使得 Ceph 的數據事務處理速度如此的快。
2.3 Ceph Metadata Server(MDS)[可選]

Ceph 元數據伺服器服務進程,簡稱 MDS。只有在啟用了 Ceph 文件存儲(CephFS)的集群中才需要啟用 MDS,它負責跟蹤文件層次結構,存儲和管理 CephFS 的元數據。MDS 的元數據也是以 Obejct 的形式存儲在 OSD 上。除此之外,MDS 提供了一個帶智能緩存層的共用型連續文件系統,可以大大減少 OSD 讀寫操作頻率。

  1. Ceph 的架構:核心組件

3.1 Ceph RADOS(Reliable, Autonomic, Distributed Object Store)

可靠、自動、分散式對象存儲系統,簡稱 Ceph 存儲集群。Ceph 的所有優秀特性都是由 RADOS 提供的,包括分散式對象存儲的數據一致性、高可用性、高可靠性、沒有單點故障、向我修複以及自我管理等,Ceph 的數據訪問方式(e.g. RBD, CephFS, RADOSGW 和 librados)都建立在 RADOS 之上。Cepb 中的一切都以對象的形式存儲,而 RADOS 就負責存儲這些對象。對於分散式存儲的數據一致性,RADOS 通過執行數據複製、故障檢測與恢復,還包括數據在集群節點間的遷移與再平衡來實現。

3.2 LIBRADOS

是一個 C 語言庫,簡稱 Ceph 基礎庫。對 RADOS 的功能進行了抽象和封裝,並提供北向 API。通過 librados,應用程式可以直接訪問 RADOS 原生功能,以此來提高了應用程式的性能、可靠性和效率。因為 RADOS 本質是一個對象存儲系統,所以 librados 提供的 API 都是面向對象存儲的。librados 原生介面的優點是它直接與應用代碼集成,操作非常方便,但也不會主動對上傳的數據進行分片。

librados 支持具有非同步通信能力的對象存儲介面:

存儲池操作
快照
    讀、寫對象
    創建/刪除
    整個 Object 範圍或位元組範圍
    追加或截斷
創建/設置/獲取/刪除 XATTRs
創建/設置/獲取/刪除 K/V 對
複合操作和雙重 ACK 語義

3.3 Ceph Reliable Block Storage(RBD)

Ceph 塊存儲,簡稱 RBD,是基於 librados 之上的塊存儲服務介面。RBD 的驅動程式已經被集成到 Linux 內核(2.6.39 或更高版本)中,也已經被 QEMU/KVM Hypervisor 支持,它們都能夠無縫地訪問 Ceph 塊設備。Linux 內核 RBD(KRBD)通過 librados 映射 Ceph 塊設備,然後 RADOS 將 Ceph 塊設備的數據對象以分散式的方式存儲在集群節點中。

3.4 Ceph RADOS Gateway(RGW)

Ceph 對象網關,簡稱 RGW,是基於 librados 之上的對象存儲服務介面。本質是一個代理,可以將 HTTP 請求轉交給 RADOS,同時也可以把 RADOS 請求轉換為 HTTP 請求,以此來提供 RESTful 對象存儲服務介面,並相容 S3 和 Swift。

3.5 Ceph File System(CephFS)

Ceph 文件系統,簡稱 CephFS。在 RADOS 層之上提供了一個任意大小且相容 POSIX 的分散式文件系統。CephFS 依賴 MDS 來管理其元數據(文件層次結果),以此將元數據與原始數據分離,MDS 不直接向客戶端提供數據,因此可以避免單點故障,有助於降低軟體複雜性並提高可靠性。
  1. Ceph 的架構:內部構件

4.1 Ceph Client

Ceph 的客戶端是指使用 Ceph 存儲服務的一切實體對象。可能是一個 Client 軟體、一臺主機/虛擬機或者是一個 App。客戶端會根據 Ceph 提供的不同介面類型(服務介面、原生介面、C 庫)來連接並 Ceph 存儲伺服器並使用相應的 Ceph 存儲服務。

4.1.1 客戶端的數據條帶化(分片)

當用戶使用 RBD、RGW、CephFS 類型客戶端介面來儲存數據時,會經歷一個透明的、將數據轉化為 RADOS 統一處理對象的過程,這個過程就稱之為數據條帶化或分片處理。

熟悉存儲系統的你不會對條帶化感到陌生,它是一種提升存儲性能和吞吐能力的手段,通過將有序的數據分割成多個區段並分別儲存到多個存儲設備上,最常見的條帶化就是 RAID0。而 Ceph 的條帶化處理就類似於 RAID0,如果想發揮 Ceph 的並行 I/O 處理能力,就應該充分利用客戶端的條帶化功能。需要註意的是,librados 原生介面並不具有條帶化功能,比如:使用 librados 介面上傳 1G 的文件,那麼落到存儲磁碟上的就是 1G 大小的文件。存儲集群中的 Objects 也同樣不具備條帶化功能,實際上是由上述三種類型的客戶端將數據條帶化之後再儲存到集群 Objects 之中的。

條帶化處理過程:

將數據切分為條帶單元塊。
將條帶單元塊寫入到 Object 中,直到 Object 達到最大容量(預設為 4 M)。
再為額外的條帶單元塊創建新的 Object 並繼續寫入數據。
迴圈上述步驟知道數據完全寫入。

假設 Object 存儲上限為 4M,每一個條帶單元塊占 1M。此時我們儲存一個 8M 大小的文件,那麼前 4M 就儲存在 Object0 中,後 4M 就創建 Object1 來繼續儲存。

隨著儲存文件 Size 的增加,可以通過將客戶端數據條帶化分割儲存到多個 Objects 中,同時由於 Object 映射到不同的 PG 上進而會映射到不同的 OSD 上,這樣就能夠充分利用每個 OSD 對應的物理磁碟設備的 IO 性能,以此實現每個並行的寫操作都以最大化的速率進行。隨著條帶數的增加對寫性能的提升也是相當可觀的。如下圖,數據被分割儲存到兩個 Object Set 中,條帶單元塊儲存的順序為 stripe unit 0~31。

Ceph 有 3 個重要參數會對條帶化產生影響:

order:表示 Object Size。例如:order=22 即為 2**22,即 4M 大小。Object 的大小應該足夠大以便與條帶單元塊相匹配,而且 Object 的大小應該是條帶單元塊大小的倍數。RedHat 建議的 Object 大小是 16MB。
stripe_unit:表示條帶單元塊寬度。客戶端將寫入 Object 的數據切分為寬度相同的條帶單元塊(最後走一塊的寬度未必一致)。條帶寬度應該是 Object 大小的一個分數,比如:Object Size 為 4M,單元塊為 1M,那麼一個 Object 就能包含 4 個單元塊。以便充分利用 Object 的空間。
stripe_count:表示條帶數量。根據條帶數量,客戶端將一批條帶單元塊寫入到 Object Set 中。

NOTE:由於客戶端會指定單個 Pool 進行寫入,所以條帶化到 Objects 中的所有數據都會被映射在同一個 Pool 包含的 PGs 內。
4.1.2 客戶端對 Object 的監視和通知

客戶端可以向 Object 註冊持久的監聽,並保持與 Primary OSD 的會話,這就是客戶端對 Object 的監視與通知性。該特性使得監聽同一個 Object 的客戶端之間可以使用 Object 來作為通信的渠道。

4.1.3 客戶端的獨占鎖(exclusive-lock)

客戶端的獨占鎖特性提供一種可以對 RBD 塊設備進行 “排它性的” 鎖定,這有助於解決多個客戶端對同一個 RBD 塊設備進行操作時,多個客戶端嘗試同時向同一個 Object 寫入數據導致的衝突。獨占鎖特性需要依賴客戶端對 Object 的監視與通知特性,在數據寫入時,如果一個客戶端首先在 Object 上放置了獨占鎖,則能夠被其它客戶端在寫入數據前檢查到,並放棄數據寫入。設置了這一特性的話,同一時刻只有一個客戶端能夠對 RBD 塊設備進行修改,常被應用到快照創建、快照刪除這種改變塊設備內部結構的操作。強制的獨占鎖功能特性預設是不開啟的,需要在創建鏡象時顯式的通過選項 --image-features 啟用。

rbd -p mypool create myimage --size 102400 --image-features 5
# 5 = 4 +1 
# 1:啟用分層特性
# 4:啟用獨占鎖特性​

4.1.4 客戶端的 Object 映射索引

客戶端可以在數據寫入到 RBD Image 時會跟蹤這些 Object(建立映射索引),從而讓客戶端可以在數據讀寫時就能知道相應的 Objects 是否存在,省去了遍歷 OSD 以確定 Objects 是否存在的開銷。Object 的映射索引保存在 librbd 客戶端的記憶體中。該特性對一些 RBD Image 操作比較有利:

縮容:僅刪除存在的尾部 Objects。
導出操作:僅導出存在的 Objects。
複製操作:僅存在的 Objects。
扁平化:僅將存在的 Parent Objects 拷貝到 Clone Image。
刪除:僅刪除存在的 Objects。
讀取:僅讀取存在的 Objects。

Object 映射索引特性預設也是不開啟的,同樣需要在創建鏡象時顯式的通過選項 --image-features 啟用。

rbd -p mypool create myimage –size 102400 –image-features 13
# 13 = 1 + 4 + 8
# 1:啟用分層特性
# 4:啟用獨占鎖特性
# 8:啟用 Object 映射索引​

4.2 CRUSH(Controlled Replication Under Scalable Hashing)

可控的、可擴展的、分散式的副本數據放置演算法。本質是一種偽隨機數據分佈演算法,類似一致性哈希,是 Ceph 的智能數據分發機制,管理著 PG 在整個 OSD 集群的分佈。CRUSH 的目的很明確, 就是一個 PG 如何與 OSD 建立關係,它是 Ceph 皇冠上的寶石。

4.2.1 動態計算元數據

傳統物理存儲設備的存儲機制都涉及存儲原始數據及其元數據,元數據存儲了原始數據存儲在存儲節點和磁碟陣列的地址信息。每一次有新數據寫入存儲系統時,元數據最先更新,更新的內容就是原始數據將會存放的物理地址,在此之後才是原始數據的寫入。Ceph 則拋棄了這種存儲機制,使用 CRUSH 演算法動態計算用於存儲 Object 的 PG,同時也用於計算出 PG 的 OSD Acting Set(Acting Set 即為活躍的 OSD 集合,集合中首編號的 OSD 即為 Primary OSD)。CRUSH 按需計算元數據,而不是存儲元數據,所以 Ceph 消除了傳統的元數據存儲方法中的所有限制,具有更好的容量、高可用性和可擴展性。
4.2.2 基於 CRUSH bucke 的故障域/性能域劃分

除此之外,CRUSH 還具有獨特的基礎設施感知能力,可以識別整個基礎設施中的物理組件拓撲(故障域和性能域),包括磁碟、節點、機架(Rack)、行(Row)、開關 、電源電路、房間、數據中心以及存儲介質類型等多種 CRUSH bucke 類型,bucket 表明瞭設備的具體物理位置。這種感知能力使得 CRUSH 可以讓客戶端進行跨故障域寫入數據,以此來保證數據的安全性。CRUSH bucke 包含在 CRUSH Map 中,CRUSH Map 還保存了一系列可定義的規則(CRUSH Rules),告訴 CRUSH 如何為不同的 Pool 複製數據。CRUSH 使得 Ceph 能夠自我管理和自我療愈。當故障區域中的組件故障時,CRUSH 能夠感知哪個組件故障了,並自動執行相應的數據遷移、恢復等動作。使用 CRUSH,我們能夠設計一個沒有單點故障的高度可靠的存儲基礎設施。CRUSH 也可使客戶端能夠將數據寫入特定類型的存儲介質中,例如:SSD、SATA。CRUSH Rules 決定了故障域以及性能域的範圍。

4.3 Object

對象。是 Ceph 的最小存儲單元,每個 Object 都包含了在集群範圍內唯一的標識、二進位數據、以及由一組鍵值對組成的元數據。綁定在一起的原始數據與元數據,並且具有 RADOS 全局唯一的標識符 OID。無論上層應用的是 RBD、CephFS 還是 RADOSGW,最終都會以 Object 的方式存儲在 OSD 上。當 RADOS 接收到來向客戶端的數據寫請求時,它將接收到的數據轉換為 Object,然後 OSD 守護進程將數據寫入 OSD 文件系統上的一個文件中。

4.4 Placement Group(PG)

歸置組,簡稱 PG。PG 是一組 Objects 的邏輯集合。一個 Ceph 存儲池可能會存儲數百萬或更多的數據對象。因為 Ceph 必須處理數據持久化(副本或糾刪碼數據塊)、清理校驗、複製、再平衡以及數據恢復,因此以 Object 作為管理對象就會出現擴展性和性能上的瓶頸。Ceph 通過引入 PG 層來解決這個問題。CRUSH 分配每個 Object 到指定的 PG 中,每個 PG 再映射到一組 OSD 中。PG 是保障 Ceph 可伸縮性和性能必不可少的部分。當數據要寫入 Ceph 時,首先會將將數據分解成一組 Objects,然後根據 Object 名稱、複製級別和系統中的總 PG 數等信息執行散列操作並生成 PG ID,最後依據 PG ID 將 Objects 數據分散到各個 PG 中。沒有 PG,在成千上萬個 OSD 上管理和跟蹤數以百萬計的 Objects 的複製和傳播是相當困難的。將包含大量 Objects 的 PG 作為管理和複製的對象,可以有效縮減計算資源的損耗。每個 PG 都會消耗一定的計算資源(CPU、RAM),所以存儲管理員應該

精心計算集群中的 PG 數量。
4.4.1 計算 PG 數

上文中我們提到過,PG 數會在一定程度上影響存儲性能,一個 OSD 的 PG 數可以被動態修改,但建議在部署規劃時期就能夠對 PG 數有一定的把握。常見的,有以下幾種 PG 數計算方式:

計算集群 PG 總數

PG 總數 = (OSD 總數 x 100) / 最大副本數​

結果取最接近 2 的 N 次冪,比如:集群有 160 個 OSD 且副本數為 3,那麼根據公式計算得到的 PG 總數是 5333.3,再舍入這個值到最接近的 2 的 N 次幕,最終結果為 8192 個 PG。

計算 Pool 下屬的 PG 總數

PG 總數= ((OSD 總數 x 100) / 最大副本數) / 池數​

結果同樣取最接近 2 的 N 次冪。
4.4.2 PG 與 PGP

PG - Placement Group
PGP - Placement Group for Placement purpose
pg_num - number of placement groups mapped to an OSD
When pgnum is increased for any pool, every PG of this pool splits into half, but they all remain mapped to their parent OSD.Until this time, Ceph does not start rebalancing. Now, when you increase the pgpnum value for the same pool, PGs start to migrate from the parent to some other OSD, and cluster rebalancing starts. This is how PGP plays an important role.

顧名思義,PGP 是為了實現定位而設置的 PG。PGP 的數量應該與 PG 總數保持一致。對於一個 Pool 而言,當你增加了 PG 的數量,這個 Pool 的 PG 同時還應該修改 PGP 的數量,讓兩者保持一致,這樣集群才能夠觸發再平衡動作。

pg_num 的增加會使舊 PGs 中的 Objects 再平衡到新建 PG 中,舊 PGs 之間不會發現 Object 遷移並且依舊保存原有的 OSD 映射關係。
pgp_num 的增加會使新 PGs 在平衡到 OSDs 中,而舊 PGs 依舊保存原有的 OSD 映射關係.
PGP 決定了 PG 的分佈。

4.4.3 PG Peering 操作、Acting Set 與 Up Set

OSD 守護進程會為每個 PG 的副本執行 Peering 操作,確保 PG 對應的主從 OSDs 之間的 PG 副本是一致的。這些主從 OSDs 以 Acting Set 的形式組織起來,Acting Set 的第一個元素就是 Primary OSD,保存著 PG 的主副本。其餘為 Replica OSDs 中保存的是 PG 的第二/第三副本(假設副本數為 3)。Primary OSD 負責 Replica OSDs 之間的 PG 的 Peering 操作。當 Primary OSD 狀態為 down 時,首先會從 Up Set 中移除,然後由第二 OSD 晉升為 Primary OSD,故障 OSD 中的 PG 會以同步到其他 OSD 的方式還原,並將新的 OSD 加入到 Actin Set 和 Up Set 中,以確保整個集群的高可用性。

Pool

   存儲池。是一個面向管理員的、用來隔離 PGs 和 Objects 的邏輯分區。簡單來說,Pool 就是一個管理員自定義的命名空間,不同的 Pool 可以具有完全不同的數據處理方式,例如:Replica Szie(副本數)、PG Num、CRUSH Rules、快照、所屬者及其授權等。可以為特定類型的數據創建存儲池,比如:塊設備、對象網關,亦或僅僅是為了多用戶隔離而創建 Pool。

   管理員可以為 Pool 設置所有者和訪問許可權,還支持快照功能。當用戶通過 API 來存儲數據時,需要指定 Objects 要存儲到哪一個 Pool 中。管理員可以對不同的 Pool 設置相關的優化策略,比如 PG 副本數、數據清洗次數、數據塊及 Object 的 Size 等等。Pool 提供了一個有組織的存儲管理方式。每個 Pool 都會交叉分佈在集群節點的 OSDs 上,這樣能夠提供足夠的彈性。除了 PG 副本數,也可以通過指定糾刪碼的規則集來提供與副本數同等級別的可靠性,而且只消耗更少的空間。

當把數據寫人到一個 Pool 時,首先會在 CRUSH Map 找到與 Pool 對應的規則集,這個規則集描述了 Pool 的副本數信息。在部署 Ceph 集群時會創建一些預設的存儲池(e.g. data、metadata、rbd)。

    Pool 也存在容量的概念,但 Pool Size 只在限制最大容量或者 QoS 的場景中有用,並不是真實的容量,因為 Pools 與 OSDs 之間的隱射是交叉的,Pools 的總容量大於 Ceph Cluster GLOBAL Size。所以 Pools 的總容量是沒有意義的。

  1. Ceph 的設計思想

     此處不妨小結一下 Ceph 每個內部構件的設計含義及其存在的意義。以 Object 作為 Ceph 的最小存儲單元充分地展示了 Ceph 巨集大的野心 —— 要成為新一代(或者成為雲時代)的存儲架構。眾所周知,元數據是關於原始數據的信息,它決定了原始數據將往哪裡存儲,從哪裡讀取。傳統的存儲系統通過維護一張集中式的查找表來跟蹤它們的元數據,這直接導致了傳統存儲系統查找性能低(容量有限)、單點故障(可靠性低)、數據一致性(可擴展性低)等問題。為了實現這一目標,Ceph 就必須打破傳統存儲系統的桎梏,採用更加智能的元數據管理方法,以離散的方式來存儲原始數據及其元數據,再以動態計算的方式來定位數據的所在,這就是 Object + CRUSH。在此基礎之上,RADOS 的引入就是為瞭解決分散式運行環境中的數據一致性、高可用性和自我管理等問題;PG 的引入就是為了縮小 RADOS 的管理對象以及 Objects 的遍歷定址空間,進一步提升性能和降低內部實現複雜度,在進行數據遷移時,也是以 PG 作為遷移單位。有了 PG 之後 Ceph 會儘量避免直接操作 Objects;Pool 的引入就是為了抽象出更加友好的資源管理與操作模型,例如:PG 的數量以及 PG 的副本數都是以 Pool 為單位設定的,提供了良好的用戶操作體驗。在如此可靠、自動、分散式的對象存儲系統之上再構建 librados、RBD、RGW、CephFS 等多種更便於應用或客戶端使用的上層介面類型,真正實現了下層抽象統一、上層異構相容的統一存儲解決方案。回頭再看,Ceph 成功的原因很簡單,其 SDS(軟體定義存儲)基因所帶來的 “可編程性” 不正是雲時代所渴望的嗎?
  2. Ceph 的數據讀寫原理
    6.1 數據儲存的三個映射過程

Ceph 存儲系統中,數據存儲分三個映射過程:

Step 1. 將要存儲的 File 數據映射(切分)為 RADOS 可以處理的 Objects(1:N):(ino, ono) -> oid

ino:File 的元數據,File 的唯一標識
ono:File 切分產生的某個 Object 時的分片編號,預設以 4M 大小切分
oid:Object 唯一標識,存儲了 Obejcts 與 File 的從屬關係

Step 2. 將 Objects 映射到 PG(N:1):hash(oid) & mask -> pgid,Ceph 指定一個靜態 HASH 函數將 oid 映射成一個近似均勻分佈的偽隨機值,然後將這個值與 mask 按位相與,得到 PG ID。

mask:PG 總數 m - 1,m 為 2 的整數冪

Step 3. 將 PG 映射到 OSDs(N:M):CRUSH(pgid) -> (osd1,osd2,osd3),傳入 pgid 到 CRUSH 演算法計算得到一組 OSD 數組(長度與 PG 副本數相同)。

File 數據最終分散保存在這些 OSDs 中。

調度演算法的偽代碼:

locator = object_name
obj_hash = hash(locator)
pg = obj_hash % num_pg
osds_for_pg = crush(pg) # returns a list of osds
primary = osds_for_pg[0]
replicas = osds_for_pg[1:]​

6.2 客戶端的 I/O 定位

當客戶端讀寫數據時,首先需要與 MON 節點建立連接並下載最新的 Cluster Map。客戶端讀取 Cluster Map 中的 CRUSH Map(包含 CRUSH Rules、CRUSH bucke)和 OSD Map(包含所有 Pool 的狀態和所有 OSDs 的狀態),Crush Rules 就是數據映射的策略,決定了每個 Object 有多少個副本,這些副本應該如何存儲,當把數據寫入一個 Pool 時,可以通過 Pool name 匹配到一個 CRUSH Rules。客戶端通過這些信息在本地執行 CRUSH 演算法獲得數據讀寫的 Primary OSD 的 IP:Port,然後就可以與 OSD 節點直接建立連接來傳輸數據了。CRUSH 動態計算的動作發生在客戶端,不需要有集中式的主節點用於定址。客戶端分攤了這部分工作,進一步減輕了服務端的工作負載。


客戶端輸入 Pool name 以及 Object ID(例如:Pool=“pool1”, Object=”obj1”)。
CRUSH 獲取 Object ID 後對其進行 HASH 編碼。
CRUSH 根據上一步的 HASH 編碼與 PG 總數求模後得到 PG ID。(e.g. HASH 編碼後為 186,而 PG 總數為 128,則求模得 58,所以這個 Object 會存儲在 PG_58 中)。
CRUSH 計算對應 PG ID 的主 OSD。
客戶端根據 Pool name 稱得到 Pool ID(e.g. pool1=4)。
客戶端將 PG ID 與 Pool ID拼接(e.g. 4.58)
客戶端直接與 Activtin Set 集合中的主 OSD 通信,來執行對象的 IO 操作。

6.3 主從 OSD 的副本 I/O

首先我們需要瞭解到 Ceph 的讀寫操作採用了主從模型,當客戶端讀寫數據時,都只能向 Object 對應的 Primary OSD 發起請求。同時 Ceph 還是一個 強一致性 分散式存儲,也就是說保證分散式數據的一致性同步過程並非非同步操作。只有當所有的主從 OSD 都寫入數據之後才算是一次成功的寫入。客戶端使用 CRUSH 演算法計算 Object 映射的 PG ID 以及 Acting Set 列表。Acting Set 的首元素就是 Primary OSD,剩下的為 Replica OSD。

6.4 提升性能的日誌 I/O

強一致性的數據同步方式在帶來了高度的數據一致性的同時也存在一些缺點,比如:寫性能低。為了提高寫性能,Ceph 採用了一種普遍的應對方式 —— 日誌緩存的機制。

當有突發的寫入峰值時,Ceph 會先把一些零散的、隨機的 IO 請求保存到緩存中進行合併,然後再統一向內核發起 IO 請求。這種方式有效提升了執行效率,但一旦 OSD 節點崩潰,緩存中的數據也會隨之丟失。所以,Ceph OSD 包含兩個不同的部分:OSD 日誌部分(journal 文件)和 OSD 數據部分。每一個寫操作都包含兩個步驟:首先將 Object 寫入日誌部分,然後再將同一個 Object 從日誌部分寫人數據部分。當 OSD 崩潰後重新啟動時,會自動嘗試從 journal 恢復因崩潰而丟失的緩存數據。因此,journal 的 IO 是非常密集的,而且由於一個數據要 IO 兩次,很大程度上也損耗了硬體的性能。從性能的角度來看,在生產環節中建以使用 SSD 存儲來日誌。使用 SSD 可以通過減少訪問時間和讀取延遲實現吞吐量的顯著提升。

如果使用 SSD 來存儲日誌,我們可以在每一個物理 SSD 磁碟上創建一個邏輯分區來作為日誌分區,這樣每個 SSD 的日誌分區就可以映射到一個 OSD 的數據分區,journal 文件的大小預設為 5G。在這種部署方案中,切記不要在同一個 SSD 上存儲過多的日誌以避免超出它的上限而影響到整體性能。建議在每一個 SSD 磁碟上不應該存儲超過 4 個 OSD 的日誌。但需要註意的是,使用單一 SSD 磁碟來存儲多個日誌的另一個壞處是容易發生單點故障,所以也建議使用 RAID1 來避免這種情況。
6.5 數據寫入 OSD 的 UML 流程

Client 創建 Cluster Handler。
Client 讀取配置文件。
Client 連接上 MON,獲取 Cluster Map 的副本。
根據 CRUSH Map 記錄的故障域以及數據分發規則信息,找到 Client 讀寫 I/O 的目的 Primary OSD(主 OSD)。
根據 OSD Map 記錄的 Pool 副本數(這裡假設副本數為 3),首先將數據寫入 Primary OSD。Primary OSD 再複製相同的數據到兩個 Replica OSD 中,並等待它們確認寫入完成。
Replica OSD 完成數據寫人,它們就會發送一個應答信號給 Primary OSD。
最後,Primary OSD 再返問一個應答信號給客戶端,以確認完成整個寫人操作 。

6.6 數據寫入新 Primary OSD 的 UML 流程

Client 連接 MON,獲取 Cluster Map 的副本。
新 Primary OSD 由於不存在任何 PG,所以主動上報 MON 暫時由 Primary OSD 2 升級為臨時 Primary OSD。
臨時 Primary OSD 把 PG 全量同步給新 Primary OSD。
Client I/O 直接連接臨時 Primary OSD。
臨時 Primary OSD 接收到數據後同時複製另外兩個 OSD,並等待它們確認寫入完成。
三個 OSD 都同步寫入數據後返問一個應答信號給客戶端,以確認完成整個寫人操作 。
如果臨時 Primary OSD 與新 Primary OSD 的全量數據完成,則臨時 Primary OSD 再次降級為 Replica OSD。
  1. Ceph 的自管理
    7.1 OSD 的心跳機制

心跳機制是最常見的故障檢測機制,Ceph 使用心跳機制來檢測 OSD 是否正常運行,以便及時發現故障節點併進入相應的故障處理流程。OSD 的狀態(Up/Down)反映了其健康與否,OSD 加入到集群後會定期的上報心跳到 MON,但假如 OSD 已然故障的話就不會在繼續上報自己為 Down 的狀態了,所以具有關聯關係的 OSDs 之間也會互相評判對方的狀態,如果發現對方 Down 掉了,則會協助上報到 MON。當然了,MON 也會定期的 Ping 這些 OSD 以此來確定它們的運行情況。Ceph 通過伙伴 OSD 彙報失效節點以及 MON 統計來自 OSD 的心跳檢測兩種方式判定 OSD 節點是否失效。

OSD 服務進程會監聽 Public、Cluster、Front 和 Back 四個埠:

Public 埠:監聽來自 MON 和 Client 的連接。
Cluster 埠:監聽來自 OSD Peer 的連接。
Front 埠:監聽供客戶端連接到集群所使用的網卡。
Back 埠:監聽供集群內部使用的網卡。

OSD 心跳機制的特征:

及時:伙伴 OSD 可以在秒級發現失效節點彙報至 MON,併在幾分鐘內由 MON 將失效 OSD 下線。
適當的壓力:由於有伙伴 OSD 協同彙報,MON 與 OSD 之間的心跳檢測更像是一種保險措施,因此 OSD 向 MON 發送心跳的間隔可以長達 600 秒,MON 的檢測閾值也可以長達 900 秒。Ceph 將故障檢測過程中中心節點的壓力分散到所有的 OSD 上,以此提高了中心節點 MON 的可靠性,進而提高整個集群的可擴展性。
容忍網路抖動:MON 收到 OSD 對其伙伴 OSD 的彙報後,並沒有馬上將目標 OSD 下線,而是周期性的等待一下幾個條件:
    目標 OSD 的失效時間大於通過固定量 osd_heartbeat_grace 和歷史網路條件動態確定的閾值。
    來自不同主機的彙報達到 mon_osd_min_down_reporters。
    滿足前兩個條件前失效彙報沒有被源 OSD 取消。
擴散:作為中心節點的 MON 並沒有在更新 OSD Map 後嘗試廣播通知所有的 OSD 和 Client,而是惰性的等待 OSD 和 Client 來獲取。以此來減少 MON 的壓力並簡化交互邏輯。

7.2 OSD 之間相互的心跳檢測

同一個 PG 內 OSDs 之間互相發送 PING/PONG 信息。
每隔 6s 檢測一次。
20s 沒有檢測到心跳回覆,將對方加入 Failure 隊列。

7.3 OSD 與 MON 間的心跳機制

7.4 OSD 擴容時的 PG 遷移與再平衡

將一個新的 OSD 添加到 Ceph 集群時,Cluster Map 也會更新,這一變化會改變 CRUSH 計算時輸入的參數,也就間接的改變了 Object 放置的位置。CRUSH 演算法是偽隨機的,但會均勻的放置數據,所以 CRUSH 會開始執行再平衡操作,並且會讓儘量少的數據發生遷移。一般遷移的數據量是集群總數據量與 OSD 數量的比值,例如:在有 50 個 OSD 的集群中,當新增加一個 OSD 時,就只會有 1/50(2%)的數據會被遷移。並且所有舊 OSD 會並行地移動數據,使其能夠迅速的完成。在生產環境中對於利用率高(刷寫量大速快)的 Ceph 集群,建議先將新的 OSD 權重設為 0,再逐漸增加權重。通過這種方式,能夠減少再平衡操作對 Ceph 集群性能有較大的影響。再平衡機制保證了所有磁碟能能夠被均勻的使用,以此提升集群性能和保持集群健康。

擴容前:

擴容後:

上圖可見,虛線的 PGs 會自動遷移到新的 OSD 上。
7.5 數據擦除(Clean)

數據擦除是 Ceph 維護數據一致性以及整潔性的手段。OSD 守護進程會完成 PG 內的 Object 清理工作,它會比較副本間 PGs 內的 Object 元數據信息,捕獲異常或文件系統的一些錯誤,這類 Clean 是 Day 級別的調度策略。OSD 還只會更深層次的比較,對數據本身進行按位比較,這種深層次的比較可以發現驅動盤上壞的扇區,一般是 Week 級別的調度策略。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 實體映射時,遇到複雜類型,可選擇下述方法處理: NotMapped,跳過映射 在複雜類型上聲明 [Owned],但僅限該複雜類型是全部由簡單值類型組成的 自定義序列化方法 示例: IPInfo使用了owned,對IPEndPoint使用自定義序列化,對VersionInfo使用JSON序列化 @@@... ...
  • 首先我們使用最簡單的模板案例,裡面有一個Counter計數器,你可以在創建模板中找到。 首先需要設置運行調試方式為IIS Express。這意味著,MAC可能不能使用調試。 然後開啟運行而不調試(Ctrl+F5) 按Shift + Alt + D,會出現一個新的頁面。 如果你想用Chrome調試,復 ...
  • 一、前言 這方面的資料很多,重覆的寫沒必要,但是最近一直在學習身份驗證和授權相關東東,為了成體系還是寫一篇,主要是從概念上理解identity系統。 參考:https://www.cnblogs.com/r01cn/p/5179506.html 二、概述 幾乎所有系統都包含用戶、角色、許可權、登錄、註 ...
  • 冒泡排序原理:(升序)通過當前位置數和後一個位置數進行比較 如果當前數比後一個數大 則交換位置, 完成後 比較基數的位置變成下一個數。直到數組末尾,當程式運行完第一遍 最大的數已經排序到最後一個位置了。次數可以減少迴圈數不用管最後一個數 降序排序同理 不過是把比較方式變成判斷當前數是否小於下一個數 ...
  • 原來的C 程式都有Main的,現在用vs新建一個Wpf項目,啟動似乎變成App.xmal,前期項目中為了獲取啟動參數,很是折騰了一番: 1.先是修改App.xaml,添加StartUp事件 2.然後編輯Application_Startup,判斷e.Args數組 總感覺跟又臭又長的裹腳布一樣,不爽。 ...
  • dotnetcore3.1 WPF 中使用依賴註入 Intro 在 ASP.NET Core 中預設就已經集成了依賴註入,最近把 "DbTool" 遷移到了 WPF dotnetcore 3.1, 在 WPF 中我們也希望能夠使用依賴註入,下麵來介紹一下如何在 WPF dotnetcore3.1 中 ...
  • 該方式是直接對屏幕進行截圖操作UserControl chartContainPanel = new UserControl();Graphics graph = chartContainPanel.CreateGraphics();Size s = chartContainPanel.Size;B... ...
  • 3.github與git同步 3.1 配置公私鑰 3.2 github上建立個人倉庫 3.3 本地倉庫同步到github 往遠端推送叫做 push 從遠端拉取叫做 fetch 需要先git pull命令拉取下來 瞭解更多技術文章,歡迎關註我的個人公眾號 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...