OpenStack Yoga版安裝筆記(22)Swift筆記20250418

一、官方文檔

https://docs.openstack.org/swift/yoga/admin/objectstorage-components.html#https://docs.openstack.org/swift/yoga/admin/objectstorage-components.html#

二、對象存儲簡介(Introduction to Object Storage)

OpenStack 對象存儲(Swift)用于構建冗余、可擴展的數據存儲系統,通過一組標準化服務器集群來存儲 PB 級(百萬 GB)數據,并保證數據可訪問。它是一個面向長期存儲的大規模靜態數據系統,支持數據的檢索和更新。

Swift 使用一種分布式架構,沒有集中式控制點,因此擁有更好的擴展性、冗余能力和持久性。對象數據會被寫入多個硬件設備中,OpenStack 軟件則負責在整個集群中確保數據的副本一致性和完整性

存儲集群支持橫向擴展(scale out),也就是說,只需添加新的節點,就可以提升存儲能力。如果某個節點失效,OpenStack 會自動從其他活躍節點復制內容以進行修復。

由于 Swift 使用的是軟件邏輯來保證數據復制和分布,因此可以使用廉價的普通硬盤和服務器來代替昂貴的高端設備。

對象存儲非常適合低成本、彈性擴展的存儲需求。它提供了一個完全分布式、可通過 API 訪問的存儲平臺,可以直接集成到應用程序中,或用于備份、歸檔和數據保留等場景。

什么是對象存儲(Object Storage)?

對象存儲是一種不同于傳統文件系統或塊存儲的方式,它將數據作為**對象(Object)**進行管理:

  • 每個對象包含數據本體、元數據和唯一標識(如 URL)

  • 不依賴于傳統的“文件夾/路徑”結構

  • 通常用于存儲圖片、視頻、日志、備份、靜態網頁、容器鏡像等靜態數據

Swift 是 OpenStack 的對象存儲組件,具備以下特點👇


🔁 1. 冗余性(Redundancy)

  • 每個對象都會存儲多份副本(通常是 3 份),分布在不同的服務器上

  • 即使一臺設備或整個機架損壞,也不會丟失數據


📈 2. 可擴展性(Scalability)

  • Swift 使用無中心節點的分布式結構

  • 不存在性能瓶頸或單點故障

  • 只需添加新服務器即可擴容,無需重新設計架構


💾 3. 廉價硬件支持(Commodity Hardware)

  • 不需要使用昂貴的 SAN、NAS 或高端企業級磁盤

  • 可以使用普通服務器和硬盤,成本更低,靈活性更高


🔧 4. 自動修復機制(Self-healing)

  • 節點宕機時,系統會自動將丟失的數據從其他副本中復制回來

  • 配合 replication 或 erasure code,保障數據完整性


🧩 5. API 驅動

  • 對象存儲完全通過 HTTP REST API 訪問

  • 可輕松集成到 Web、云原生應用、容器等系統中

  • 與 Amazon S3 使用方式非常類似


📦 6. 應用場景

場景描述
應用集成可以作為圖床、視頻源、文檔托管服務嵌入業務系統
數據備份保存 VM 鏡像、數據庫備份文件等
日志歸檔存儲日志、監控記錄等長期歸檔數據
靜態網站托管用作前端網頁/圖片/CDN 源站

? 總結一句話:

Swift 是 OpenStack 提供的一個去中心化、高冗余、可水平擴展的對象存儲系統,適用于低成本、大規模的靜態數據存儲需求。

三、對象存儲的關鍵特性(Object Storage characteristics)

對象存儲的關鍵特性如下:

  • 所有存儲在對象存儲中的對象都有一個 URL(統一資源定位符)。

  • 可以使用“存儲策略(Storage Policies)”來定義對象在集群中的不同持久性等級。這些策略不僅支持完整副本,也支持糾刪碼(Erasure Coding)分片。

  • 對于每一個對象,其所有副本或分片都會盡可能存儲在**不同的可用區域(zone)**中,以提高持久性和可用性。

  • 每個對象都擁有自己的元數據(metadata)

  • 開發者通過RESTful HTTP API與對象存儲系統進行交互。

  • 對象數據可以存儲在整個集群中的任意位置

  • 通過添加新節點進行橫向擴展,不會犧牲性能,因此相比“整套替換(fork-lift upgrade)”,對象存儲能夠以更低成本實現線性擴展

  • 無需將數據遷移到全新的存儲系統。

  • 可在不中斷服務的前提下添加新節點。

  • 故障節點和硬盤也可以在不中斷服務的情況下替換。

  • 運行在通用的標準硬件上,例如 Dell、HP、Supermicro 等廠商的設備。

逐條解析一下這些特性在實際場景中的意義👇


🔗 1. 每個對象都有一個 URL

  • 對象存儲是基于 HTTP 協議的,每個對象上傳之后,都會獲得一個可通過 REST API 訪問的唯一地址。

  • 舉個例子,某張圖片上傳后就可以通過 http://swift.example.com/v1/account/container/image.jpg 直接訪問。


📐 2. 存儲策略(Storage Policies)

  • 通過策略控制數據副本的類型與數量,提供靈活的存儲級別。

    • 比如:

      • 默認策略使用 3 副本

      • 冷數據策略使用糾刪碼(如 10+4)減少存儲開銷

      • 快速訪問策略使用 SSD 節點

  • 不同容器可以使用不同的策略,方便按業務需求定制。


🗂? 3. 副本/分片盡可能分布在不同的 Zone

  • Zone 是一種“故障域”,比如不同的:

    • 物理機架

    • 機房

    • 數據中心

  • Swift 會盡量讓對象的多個副本/碎片分布到不同的 zone 上,提高數據的可用性與容災能力


📝 4. 每個對象擁有獨立元數據

  • 可以為每個對象添加自定義的屬性(metadata):

    • 文件作者、內容類型、加密信息等

  • 元數據通過擴展屬性或數據庫記錄實現,不需要額外的元數據服務器。


🌐 5. RESTful API 訪問

  • 所有操作(上傳、下載、刪除、列出對象)都通過 HTTP 請求完成。

  • 這意味著:

    • 可直接從網頁、移動應用、Python 腳本、Java 程序等使用

    • 也可以兼容 S3 API 等常見協議(使用適配器)


🌍 6. 對象可以存在于集群的任何位置

  • 對象的實際位置由 ring(環)系統管理

  • 不需要知道具體在哪臺機器上,只要通過 Proxy Server 就能訪問

  • 實現了完全的位置透明性


🧱 7. 橫向擴展能力強,成本低

  • 通過添加新的普通服務器節點就可以擴容,不影響已有服務

  • 不像傳統 SAN/NAS 需要統一的大規模升級

  • 適合云時代的大數據、持續增長的存儲需求


🔄 8. 無需整體遷移數據

  • 系統支持熱擴容,不需要“把舊系統數據遷走”,這避免了停機或數據遷移成本

  • 數據分布自動通過 rebalance 完成


🚫 9. 新增/替換節點無需停機

  • 無論是增加節點還是替換硬盤/壞掉的服務器,都可以在線完成

  • 系統通過復制、重建等機制自動補齊丟失的數據,保障業務連續性


💻 10. 支持通用標準硬件

  • 不依賴昂貴的專用設備(不像某些傳統存儲系統)

  • 可使用 Dell、HP、Supermicro 等品牌的 x86 服務器,甚至可以自己組裝服務器

  • 降低成本,維護更靈活


? 總結一句話:

Swift 對象存儲通過 REST API、橫向擴展、高可用冗余設計和標準硬件支持,打造了一個穩定、靈活、低成本的云原生數據存儲平臺。

?四、對象存儲組件(Components)

4.1 組件概述

OpenStack 對象存儲使用以下組件來實現高可用性、高持久性和高并發性:

  • 代理服務器(Proxy servers) - 處理所有傳入的 API 請求。

  • 環(Rings) - 將數據的邏輯名稱映射到特定磁盤上的物理位置。

  • 可用區(Zones) - 實現數據隔離。一個 Zone 故障不會影響整個集群,因為數據會跨 Zone 復制。

  • 賬戶與容器(Accounts and Containers) - 每個賬戶和容器都是分布在整個集群中的獨立數據庫。賬戶數據庫包含該賬戶下的所有容器清單;容器數據庫包含該容器中的所有對象清單。

  • 對象(Objects) - 實際存儲的數據內容。

  • 分區(Partitions) - 存儲對象、賬戶數據庫和容器數據庫的邏輯單元,幫助管理數據在集群中的存放位置。

詳細講解:


1?? Proxy Servers(代理服務器)

  • 這是 Swift 的入口點

  • 所有客戶端(如 Web 前端、APP、API 調用)發送的請求都會先到 Proxy Server。

  • 它的職責是:

    • 根據 ring 查找數據位置

    • 路由請求到對應的存儲節點

    • 對 Erasure Code 數據進行編碼/解碼(如啟用 EC 策略)

  • 本身不存儲數據,只負責請求調度與轉發


2?? Rings(環)

  • ring 是一個邏輯映射表,用于查找某個對象/容器/賬戶在集群中的存儲位置。

  • 它會基于對象名的 hash 值找到“分區號”,再根據分區號找到在哪些設備上存儲。

  • Swift 中有三個主要 ring:

    • account ring

    • container ring

    • object ring(每個 Storage Policy 有一個)


3?? Zones(可用區)

  • 可用區類似于故障域,代表物理隔離的單位,例如:

    • 不同的機架

    • 不同的服務器組

    • 不同的數據中心

  • 數據會被跨 Zone 存儲,從而實現:

    • 一個 Zone 掛了,數據不會丟

    • 剩下的 Zone 還能提供服務

  • 它是實現高可用性和容災的核心設計。


4?? Accounts and Containers(賬戶和容器)

  • 賬戶:類似于用戶空間,一個賬戶下可以有多個容器。

  • 容器:類似于文件夾,一個容器中可以存多個對象。

  • 它們的元數據是存儲在 SQLite 數據庫中的,且這些數據庫也會被復制。

    • 賬戶數據庫:記錄這個賬戶下有哪些容器

    • 容器數據庫:記錄這個容器下有哪些對象

  • 這些數據庫也是分布式的,并有多副本,保障查詢元數據的穩定性。


5?? Objects(對象)

  • 對象就是我們真正上傳的內容,比如:

    • 圖片、視頻、備份文件、日志等

  • Swift 將對象以二進制文件形式存儲在文件系統中,并附帶有 xattr 元數據

  • 對象的數據是通過 hash 值和分區規則分散地存放在多個磁盤上的。


6?? Partitions(分區)

  • 分區是 Swift 中的最小數據管理單元

  • 它不代表磁盤分區,而是 Swift 內部對數據的邏輯劃分。

  • 每個對象、容器或賬戶會被分配到某個“分區號”中。

  • 分區會被復制(通常 3 副本),分布在不同設備和 Zone 上。

  • ring 會告訴 Proxy 某個分區對應在哪些設備上,這樣 Proxy 就知道數據的位置。


? 總結一句話:

通過 Proxy Server 協調訪問,Ring 映射數據位置,Zone 實現容災隔離,Account/Container/Partition 管理元數據與數據分布,Swift 構建了一個高度可擴展、高可用的對象存儲系統。

4.2 總體架構

這張圖展示了 OpenStack Object Storage(Swift) 的核心架構組件和數據流轉過程,是理解 Swift 的高可用性、分布式和可擴展性的關鍵圖示。下面是對這張圖的詳細講解:


總體結構

圖中展示了 Swift 的各個組成部分之間的邏輯關系,從上到下依次是:

🔼 API Calls

  • 外部客戶端通過 RESTful API 發起請求,比如上傳對象、列出容器內容等。

  • 這些 API 請求會首先到達 Swift 的 Proxy Server(代理服務器)


🟪 Proxy Servers(代理服務器)

  • 這是 Swift 的網關組件,負責:

    • 接收來自用戶的 API 請求

    • 通過 Ring 找到對象/容器/賬戶應該被路由到的物理節點

    • 將請求轉發到對應的存儲節點

    • 返回操作結果給客戶端

  • Proxy 本身不存儲對象,只做請求分發與協調


🔄 The Ring(環)

  • Ring 是 Swift 中最核心的數據結構之一,用于映射數據到存儲設備

  • 包含三種 ring:

    • account.ring.gz

    • container.ring.gz

    • object.ring.gz(每個 storage policy 一個)

  • ring 負責以下映射邏輯:

    • 客戶端發來的 API 請求(如 PUT object)會通過 proxy 查詢 ring

    • 根據對象的 hash 值找到其所屬的分區(partition)

    • 查出這個分區被分配給哪些 zone 和 device(device就是指磁盤)

  • ring 是靜態文件,可以部署在 proxy 和 storage 節點上,無需實時通訊。


🏗 Nodes 和 Zones(節點和可用區)

底部展示了多個存儲節點(Node),并標明它們所在的 Zone。Zone 是一個邏輯上的“容災單元”,每個 Zone 內可以包含多個 Node 和磁盤。下面是對它們的說明:

區域顏色Zone 編號描述
🟧 橙色zone 1一組節點,例如一個機架或數據中心
🟩 淺綠zone 2另一組節點,物理隔離于 zone 1
? 深灰zone 3又一個隔離區域
🟨 米色zone 4繼續物理隔離
🟦 藍色zone 5第五個 zone,增強高可用性
  • 這 5 個 Zone 分布在不同的節點中,數據會跨 Zone 存儲(如副本、EC 分片),確保某個 Zone 故障時數據不會丟失。

  • 每個 Node 下的“Physical Storage”表示服務器上的硬盤或文件系統。

    • (補充)選擇數據存放位置

      • Swift 保存每個對象為多分拷貝,它按照物理位置的特點,盡量將這些拷貝放在不同的物理位置上,來保證數據的地理位置上的可靠性。它主要考慮以下幾種位置屬性:

        • Region:地理位置上的區域,比如不同城市甚至不同國家的機房,這主要是從災備方面考慮的。

        • Zone:一個數據中心根據物理網絡、供電、空調等基礎設施分開的獨立的域,往往將一個機架(Rack)內的服務器分在一個 Zone 內。

        • Node (節點):物理服務器

        • Disk (磁盤):物理服務器上的磁盤

      • Swift 在確定對象的放置位置時,會盡量將對象及其拷貝放在不會同時損失的物理位置上。


💡 數據存儲與容災邏輯:

舉個例子,如果你上傳了一個對象:

  1. 請求到達 Proxy Server。

  2. Proxy 查詢 ring,確定這個對象屬于哪一個分區。

  3. ring 會告訴 proxy,這個分區要分布在哪幾個 Zone 的哪些 Node 上(通常是 3 個副本或 EC 分片)。

  4. Proxy 將這個對象分別寫入這些節點。

  5. 如果其中一個 Zone 掛掉了,其他 Zone 的副本仍可正常服務。


? 總結

這張圖完整展現了 Swift 的工作流程和架構設計理念:

  • Proxy Server 接收并調度請求;

  • Ring 負責對象定位;

  • Zones 和 Nodes 實現了數據分布和容災;

  • 支持橫向擴展,只需添加節點即可增加容量和吞吐;

  • 典型的 分布式對象存儲系統設計,穩定且高效。

4.3 Proxy servers

Proxy servers 是對象存儲系統對外公開的接口,負責處理所有進入的 API 請求。
一旦代理服務器接收到請求,它會根據對象的 URL(例如:
https://swift.example.com/v1/account/container/object)來確定應訪問哪個存儲節點。
代理服務器還負責協調響應、處理故障以及協調時間戳。

代理服務器采用的是“無共享架構”(shared-nothing architecture),并且可以根據預計的工作負載隨需擴展。
建議至少部署兩個代理服務器,并將它們置于一個獨立管理的負載均衡器之后。
如果其中一個代理服務器發生故障,其它的代理服務器可以接管任務,確保服務不中斷。

詳細講解:


💡 什么是 Proxy Server?

在 OpenStack Swift 中,Proxy Server 是客戶端和后端存儲節點之間的“中介者”或“門面”,所有對象存儲的操作請求(如上傳、下載、刪除對象等)都必須先經過它。

🌐 如何處理請求?

舉個例子:
當用戶通過瀏覽器或 API 訪問如下 URL:

https://swift.example.com/v1/myaccount/mycontainer/myphoto.jpg

這個請求會首先到達 Proxy Server,然后由它去解析:

  • 是哪個賬號(account)

  • 哪個容器(container)

  • 哪個對象(object) 再根據 Ring 文件(存儲映射表)查出這些數據位于哪個后端節點(服務器、磁盤),并將請求轉發過去。

🔄 Proxy Server 的主要職責:

職責說明
路由請求根據 URL 識別資源,并查找對應的數據位置
調用 Ring查詢 account、container 或 object 所在的物理節點
處理錯誤若某個節點不可達,會自動重試其他副本或記錄失敗
時間戳管理Swift 使用“最后寫入優先”策略,依賴統一的時間戳協調
響應聚合將后端多個節點的響應結果聚合成一個最終響應

🧱 Shared-nothing 架構:

  • 每個 Proxy Server 都是獨立的,沒有共享內存或硬盤;

  • 無需集中協調,擴展簡單,增加新的 Proxy 節點不會影響現有系統;

  • 沒有單點故障,避免一個 Proxy 崩潰導致整個系統癱瘓。

📊 高可用部署建議:

  • 至少部署兩個 Proxy Server

  • 放在**負載均衡器(如 HAProxy、NGINX、F5)**后

  • 這樣當一個 Proxy 節點故障時,請求會被路由到其他健康的 Proxy 節點


? 總結:

Proxy Server 是 Swift 架構中處理客戶端請求的“前臺”,負責將 REST API 請求分發到正確的后端存儲節點,并聚合響應。
它是無狀態的、可擴展的、冗余的,是系統高可用性和性能擴展的關鍵組件。

4.4 Ring(環)

Ring(環) 表示集群中實體名稱與其物理磁盤位置之間的映射關系。Swift 中有三個獨立的 ring,分別用于:

  • 賬戶(accounts)

  • 容器(containers)

  • 對象(objects)

當系統中的某個組件需要對某個對象、容器或賬戶執行操作時,它會查詢相應的 ring,來確定該數據在集群中的實際存儲位置。

Ring 使用 zone(區域)device(設備)partition(分區)replica(副本) 來維護這個映射關系。
默認情況下,ring 中的每個 partition 會在集群中有三個副本,并且這些副本的位置也由 ring 中的映射關系來管理。
ring 同時也負責在發生故障時決定使用哪些設備作為“臨時接管設備(handoff)”。

數據可以被隔離到 ring 中的不同 zone 中。每個 partition 的副本會盡可能地分布在不同的 zone 中。
一個 zone 可以是一個磁盤、一個服務器、一組機架、一個交換機,甚至一個數據中心。

ring 中的 partitions 會分布在對象存儲系統的所有設備上。
當需要移動 partition(例如新增設備時),ring 會確保每次移動的數據量最小,并且每次只會移動一個副本。

你可以使用權重(weight)來平衡不同設備上的 partition 分布。
這在集群中包含不同容量磁盤的情況下特別有用。

ring 被代理服務器(proxy server)和多個后臺進程(如 replication)使用。

詳細講解:


🌀 什么是 Ring?

在 Swift 中,ring 是一個非常核心的概念。它是一個數據結構,用于告訴系統 “某個數據(account/container/object)存在哪臺服務器的哪個硬盤上”。

📦 Ring 管理哪些內容?

每一個 ring 都包含如下信息:

  • Zones(區域):用于故障隔離,比如機柜、服務器或數據中心

  • Devices(設備):每臺存儲服務器上的硬盤

  • Partitions(分區):邏輯上的存儲單位,用于將數據平均分散到整個集群中

  • Replicas(副本):每個 partition 通常有多個副本,默認是 3 個

這些信息被 ring 工具封裝為 .ring.gz 文件(壓縮后的 ring 映射文件),供 Swift 各個組件加載使用。


🗺? Ring 如何工作?

當你訪問一個對象,例如:

https://swift.example.com/v1/account1/photos/cat.jpg

Proxy Server 會:

  1. 調用 Object Ring

  2. 使用 account/container/object 的名字進行哈希

  3. 查出這個對象屬于哪個 partition

  4. 查出這個 partition 分布在哪幾個設備上(主副本和備用副本)

  5. 發起請求到對應的節點執行操作


?? Ring 的特性:

特性說明
多副本容災每個 partition 默認有 3 個副本,分布在不同 zone 提高可靠性
動態擴展添加設備時只會遷移少量 partition,避免大規模數據搬遷
權重調整大硬盤可以分配更多 partition,確保磁盤利用率均衡
隔離設計zone 可代表交換機/機柜/IDC,實現物理隔離,提高系統魯棒性
handoff 支持如果副本丟失,ring 知道哪些設備可以臨時接管存儲任務

誰使用 ring?

使用者用途
Proxy Server解析對象位置并轉發請求
Replicator確定副本在哪臺機器上進行同步
Updater更新容器或賬戶元數據時查找目標節點
Auditor檢查 partition 內容正確性時查找設備位置

? 總結:

  • Ring 是 Swift 的“大腦”,提供數據位置的查詢服務;

  • 你可以理解它是一張分布式的“導航地圖”;

  • 它設計得非常高效:自動副本管理、故障轉移、負載均衡;

  • 有 3 個獨立的 Ring:account.ring.gz、container.ring.gz、object.ring.gz;

  • 修改 Ring(如添加節點、調整權重)后要重新生成并同步到各節點。

* The ring

這些 Ring 文件是由外部工具進行管理的。服務器進程(Server processes)自身不會修改 ring,而是通過其他工具生成或修改后,將新的 ring 文件提供給服務使用。

Ring 使用的是對象路徑MD5 哈希值中的一部分比特位,將其作為一個 分區(partition)索引,這個索引用于標識該對象應存儲在哪個設備上。使用的比特位數量是一個可以配置的值,稱為 partition power(分區冪)。2 的這個冪次方就代表了總共的分區數量。例如 partition power 是 10,就有 21? = 1024 個分區。

將整個MD5 哈希空間進行分區,讓集群的其他部分可以批量處理數據項,這比一個個地處理所有對象,或一次性處理整個集群,要更高效或更簡單。

另一個可配置的值是 replica count(副本數),表示每個分區要分配到多少個設備上,也就是說,一個Ring 中有多少份副本。對于同一個分區,每個副本所對應的設備會被安排在 不同的 zone(區域)。zone 可以根據物理位置、供電分區、網絡隔離,或其他能提高副本可用性的屬性進行劃分。

詳細講解:

🧠 1. 為什么叫 "Ring"?

“Ring” 是 OpenStack Swift 用來映射對象路徑到存儲設備的一個機制,名字來源于它使用了 一致性哈希環(Consistent Hash Ring) 的設計思想。


🧩 2. 分區與 Partition Power

👉 哈希路徑 → 分區:

每一個對象路徑(例如 /account/container/object)都會被轉換成一個 MD5 哈希值,而系統從中取若干比特位來決定該對象屬于哪個分區。

  • partition_power = 10 → 表示系統有 2^10 = 1024 個分區;

  • 越多的分區,系統的分布精度越高,但 ring 文件越大;

  • 分區的作用是讓系統可以按塊管理,而不是每個對象單獨管理,提升效率。


🧾 3. 副本數(replica count)

這表示每個對象的分區會復制到多個設備上,默認是 3 個副本好處:

  • 容錯能力強:某個設備宕機,其他副本還在;

  • 性能更好:可以從最近的副本讀取,提高吞吐量。


🏘? 4. Zones 的意義

副本之間盡量分散在 不同的 Zone。Zone 可以是:

  • 一個硬盤;

  • 一臺服務器;

  • 一個機柜;

  • 一個數據中心。

這樣做的目的就是為了 防止單點故障,比如:

  • 如果 Zone 1 宕機了,其他 Zone 還能提供副本;

  • 比如一個容器里有多個副本,它們分別在上海、北京、廣州機房,即使北京斷電,服務仍可用。


?? 小結要點

概念意義
ring映射路徑到物理設備的核心結構
partition power控制分區數量:2^n 個分區
replica count每個分區存幾份(不是每個object存幾份)
zone控制副本之間的物理隔離,提高高可用性

4.5 Zone

對象存儲允許配置“區域(Zones)”,以便隔離故障邊界。如果條件允許,每一個數據副本都會被存放在不同的Zone中。從最小層面來看,一個 zone 可以是一個硬盤,或者一組硬盤。如果系統中有五個對象存儲服務器,那么每臺服務器可以分別作為一個 zone。在更大型的部署中,一個完整的機架(甚至多個機架)的存儲服務器,可以被視為一個 zone。zones 的目標是讓集群在面對嚴重存儲服務器故障時,不會導致數據的所有副本丟失

詳細講解:


? 什么是 Zone?

在 OpenStack Swift 中,Zone 是一個邏輯上的故障隔離單元(failure domain)

  • 它可以是:一個硬盤、一個服務器、一個機架、一個機房、甚至是一個數據中心。

  • Zone 是用來隔離故障的:如果一個 zone 掛了,其他 zone 的數據還在,就能繼續服務。


🔄 為什么副本要分布在不同的 Zone?

Swift 默認把每個對象保存 3 份(副本數為 3),為了保障高可用性,這 3 個副本必須盡量放在不同的 zone,比如:

副本編號放置位置(Zone)
副本1Zone A(比如服務器A)
副本2Zone B(比如服務器B)
副本3Zone C(比如服務器C)

這樣即使 Zone A 整臺服務器故障,系統還能從 B 或 C 中讀出數據,數據不會丟失


🧱 Zone 的粒度可以多大?

Zone 的定義是靈活的,取決于你部署 Swift 的規模:

部署規模Zone 通常對應的對象
小型部署一個硬盤、一個服務器
中型部署一臺服務器(常見)
大型部署一整排機架、一個數據中心

📌 總結一句話:

Zone 就像是存儲集群的“防火墻隔間”,副本放在不同的 zone 能讓系統即使部分故障也能保證數據不丟,高可用、高可靠。

4.6 Accounts and containers?

每個賬戶(account)和容器(container)都是一個獨立的 SQLite 數據庫,并分布在整個集群中。一個賬戶數據庫中保存著該賬戶下所有容器的列表。一個容器數據庫中保存著該容器中所有**對象(object)**的列表。為了追蹤對象數據(Object data)的位置,系統中的每個賬戶都有一個數據庫來記錄其所有容器,而每個容器的數據庫又會記錄其所包含的每個對象。

詳細講解:


🔹 什么是 account 和 container?

在 Swift 中:

  • Account:相當于用戶的存儲空間。

  • Container:相當于文件夾,用于組織對象。

  • Object:是最終存儲的數據單元(比如文件、圖片等)。

🔹 為什么用 SQLite?

Swift 采用 SQLite 來管理賬戶和容器的元數據,是因為:

  • SQLite 是輕量級的嵌入式數據庫,適合頻繁讀寫。

  • 單個 .db 文件易于復制、備份與同步。

  • 它不需要專門的數據庫服務進程,便于部署。

🔹 數據結構示意:

  • 每個 Account 擁有一個 .db 文件,列出了該賬戶下有哪些 Containers

  • 每個 Container 也有一個 .db 文件,列出了該容器里有哪些 Objects

這是一種分布式、去中心化的元數據管理方式,不需要一個中央數據庫,系統能更好地橫向擴展。

🔹 數據一致性與復制:

  • 這些 SQLite 數據庫文件也和對象數據一樣是多副本的(默認 3 副本),通過 replication 或 EC 策略保持一致性。

  • 這樣即使某個節點或數據庫文件損壞,也可以通過復制機制從其他副本恢復。

4.7 Partitions

**分區(Partition)**是存儲數據的集合,包含賬戶數據庫(account databases)、容器數據庫(container databases)以及對象(objects)。分區是復制系統(replication system)的核心。

可以把分區想象成一個在配送中心倉庫里流動的“箱子”。每個用戶的訂單會被放進這個箱子里。系統會把這個箱子當作一個整體來處理,而不是處理一個個零散的訂單。這樣更容易管理,也能減少系統中活動組件的數量。

系統中的復制器(replicators)以及對象的上傳/下載操作,都是以“分區”為單位進行的。隨著系統規模擴大,其行為依舊是可預測的,因為分區的數量是固定的。

實現一個分區從概念上來說是非常簡單的:它就是一個磁盤上的目錄,里面有一個對應的哈希表,標明它包含了哪些內容。

詳細講解:


🔹 什么是 Partition(分區)?

在 Swift 中,一個分區就是一個最小的數據管理單元,里面可能包含:

  • 一組對象(object files)

  • 某個容器(container)的數據庫文件

  • 某個賬戶(account)的數據庫文件

這個“分區”在物理上就是磁盤上的一個目錄,里面保存了真實數據和索引信息(通過哈希值標識)。


🔹 為什么要用 Partition?

使用分區有兩個核心好處:

  1. 方便批量管理和復制:
    Swift 中的復制系統不是對單個文件進行復制,而是以“分區”為單位批量復制,這樣效率更高。

  2. 可控性強、易擴展:
    分區總數是固定的(比如 2182^{18}218 = 262,144 個),所以隨著設備或節點的增加,分區只是被重新分配,不增加復雜度。


🔹 分區數量是怎么確定的?

由 ring 配置中的 partition_power 控制:

partition_power = 18 

意味著總共有 2182^{18}218 個分區,這些分區將均勻分布在集群內的存儲設備上。


🔹 舉個簡單的比喻:

假設你在管理一個快遞倉庫(就是 Swift 集群):

  • 你不會對每個快遞單獨搬運。

  • 你會用大箱子(分區)統一裝快遞,然后一起移動、分發。

Swift 也是這個思路,通過將數據“裝進分區”來降低系統復雜度,提高性能。

* 每個對象文件對應一個特定的 partition(分區)

? 一個對象對應一個分區

在 OpenStack Swift 中:

  • 每個對象(object)都有一個唯一的 URL,比如:

    /v1/account/container/object

  • Swift 會對這個對象路徑進行 哈希(通常是 MD5),并根據 ring 配置中的 partition_power,從哈希值中截取一部分 bits 作為分區編號。

舉例說明:

  • 假設 partition_power = 18,那就意味著 Swift 會使用對象路徑哈希值的前 18 位來決定該對象屬于哪個分區(最多有 2^18 = 262144 個分區)。

  • 然后,這個分區號再通過 ring 文件(如 object.ring.gz)來映射到具體的設備(某塊硬盤上的某個目錄)。

📦 所以總結就是:

內容說明
一個對象哈希后定位到一個分區
一個分區包含多個對象(或容器/賬戶數據庫)
對象上傳/下載/復制都是以分區為單位來操作的
分區目錄就是磁盤上的一個目錄,比如 /srv/node/sda1/objects/12345/,里面放著對象的 .data 文件和元數據

📌 小提示

  • 一個分區可以包含多個對象(但每個對象只屬于一個分區)。

  • 多個對象可以落在同一個分區中(如果它們的哈希值前幾位相同)。

4.8?Replicators

為了確保每份數據在系統中都有三份副本,replicators(副本同步器) 會不斷地檢查每個分區(partition)。

對于本地的每一個分區,replicator 會將其與其它 zone 中對應的副本進行比較,以檢測它們之間是否存在差異。

Replicator 是通過檢查 哈希值(hashes) 來判斷是否需要復制。每個分區都有一個 哈希文件(hash file),其中包含該分區每個目錄的哈希值。對于同一個分區的多個副本,系統會比較它們的哈希文件。如果發現哈希值不同,就說明這些副本不一致,需要進行數據同步。

這也是“分區”設計非常有用的地方。系統中實體數量較少(即分區數量固定),因此可以以較大的數據塊進行傳輸(而不是無數個小 TCP 請求),效率更高,而且需要比較的哈希數量是可控的。

整個集群具有“最終一致性”行為:有時候系統可能從一個未更新的副本中讀取到舊數據,但副本同步最終會讓所有分區的數據趨于最新,保持一致。

詳細講解:


🔁 什么是 Replicator?

Swift 的存儲機制依賴于“冗余副本”。默認情況下,每份對象數據會存儲三份,分別放在不同的 zone 上以防止故障導致數據丟失。

而這些副本的同步工作,不是實時發生的,而是由一個名叫 replicator 的后臺進程定期完成。


🧩 工作流程概覽:

  1. 檢查本地每個分區(partition)

  2. 讀取哈希文件(hashes.pkl) → 每個分區內目錄的哈希信息

  3. 對比其它副本的哈希值

  4. 發現不一致 → 復制本地數據覆蓋對方,或從對方拉取數據

  5. 實現最終一致性


🔍 具體機制詳解:

? 為什么需要哈希?

  • Swift 不會逐個文件對比內容,那樣太慢。

  • 它會為每個分區中的每個目錄(例如對象的文件夾)計算哈希。

  • 如果副本 A 和 B 的分區 1024 的哈希值不一樣,就說明數據有出入。

? 哈希值存哪?

  • 每個 partition 有一個對應的哈希文件,記錄了當前所有目錄的 hash 值。

  • 這些文件默認保存在 /var/lib/swift 的數據目錄中。

? 數據怎么復制?

  • 如果對比出差異,replicator 會把本地的那個目錄復制到另一個節點(或者拉對方的)

  • 不是一個個復制對象文件,而是“目錄為單位”,提高了效率。

? 為什么說 partition 有用?

Swift 故意將數據“劃分成分區”后處理:

  • 拿一個“桶”去處理多個對象,而不是一個個對象來回傳。

  • 減少連接數和元數據操作,效率高。

  • 而且分區數量是固定的,所以系統的同步成本是可控的。


? 最終一致性是怎么回事?

  • 假如三個副本中有一個還沒同步到最新數據;

  • 客戶端可能剛好訪問的是舊副本,讀取的是舊數據;

  • 不過不要擔心!replicator 遲早會同步這個舊副本,它就會和最新副本一致;

  • 這種行為就叫做“最終一致性(Eventually Consistent)”。


舉個例子:

假設你有一個重要文件被存了三份在:

  • 服務器 A(zone 1)

  • 服務器 B(zone 2)

  • 服務器 C(zone 3)

你修改了文件,結果只有 A 和 B 收到更新,C 當時宕機了。

🛠? 一段時間后,C 重啟了,此時 replicator 開始對比分區哈希值,發現 C 的分區內容落后了,于是:

  • 從 A 或 B 拉數據,覆蓋 C;

  • 三份副本再次一致!


🧾 總結表格:

角色作用
分區(Partition)數據分組單位,用于組織副本和復制操作
哈希文件每個分區目錄的哈希摘要,用于比對副本一致性
Replicator后臺進程,負責定期比對并同步分區副本
最終一致性系統允許短時間不一致,最終通過同步保持一致性

五、使用場景舉例

5.1 Upload

客戶端通過 REST API 向一個已存在的容器發送一個 HTTP PUT 請求來上傳一個對象。集群接收到該請求。

首先,系統需要確定數據將被存儲到哪里。為此,它會使用 賬戶名(account name)容器名(container name)對象名(object name) 來計算出該對象所屬的分區(partition)

接著,通過查找 ring,系統確定哪些存儲節點包含該分區(partition)。

然后,數據被發送到每一個目標存儲節點,并存儲在相應的分區中。必須有三個副本中的至少兩個寫入成功,客戶端才會收到“上傳成功”的響應。

最后,系統會異步地更新容器數據庫,反映出該容器中新增了一個對象的信息。

詳細講解:


我們一步步來剖析整個上傳流程在 Swift 中是如何運作的:


🧾 步驟 1:客戶端發起 PUT 請求

  • 客戶端使用 REST API(通常是 PUT /v1/account/container/object)上傳一個對象。

  • 這個請求中攜帶了對象的數據和元信息。


🧾 步驟 2:系統決定對象去哪存(找分區)

  • Swift 使用賬戶名、容器名、對象名,拼接起來,計算出一個 MD5 哈希

  • 從這個哈希中提取一部分比特,用于確定該對象應該屬于哪個分區(partition index)。

  • 這個過程由 ring 控制,確保對象寫入的位置是可預測的。


🧾 步驟 3:通過 ring 查找存儲節點

  • 有了分區編號,接下來 Swift 去 ring 中查找哪些 storage node(存儲節點)包含這個分區的副本。

  • 默認會找出 3 個副本所在的位置(分布在不同的 zone)。


🧾 步驟 4:發送數據到存儲節點

  • 客戶端數據由 Proxy Server 轉發到這 3 個存儲節點(比如 node A、B、C)。

  • 每個節點會把數據寫入它本地磁盤對應分區的目錄下。

📌 寫入確認機制:

  • 只要 3 個副本中有至少 2 個寫入成功,客戶端就會收到一個 2xx 響應(成功)。

  • 這是一種 高可用但低延遲 的折中方案。


🧾 步驟 5:異步更新容器數據庫

  • 對象已經寫完,但此時 容器數據庫中還沒有這條記錄

  • Swift 會使用后臺異步任務(如 container-updater)更新對應的 container.db,加入這個新對象的信息。

🔁 這種“先寫數據,再補登記”的機制提高了寫入性能,但也導致數據查詢時有可能出現短暫的不可見狀態(最終一致性模型)。


📌 舉個例子:

比如你上傳一個頭像 PUT /v1/acc1/photos/avatar.jpg,流程大致是這樣:

  1. 系統用 acc1/photos/avatar.jpg 生成一個哈希,比如落到 partition 125。

  2. ring 查出 partition 125 在 node A, B, C 上。

  3. 數據被寫入 A、B、C 的對應路徑,如 /srv/node/sda/objects/125/xyz...

  4. A、B 寫入成功,C 剛好繁忙,但 A+B 足夠滿足“2-of-3”寫成功的條件。

  5. Swift 返回 201 Created 給客戶端。

  6. 后臺異步將 avatar.jpg 加入 container photos 的數據庫記錄中。


📌 總結圖示(邏輯流程):

客戶端 → Proxy Server → 計算 partition → 查 ring → 得到 node A/B/C → 數據寫入 node A/B/C → 至少2成功 → 響應客戶端 → 異步更新 container.db

5.2 Download

當一個請求到達(例如:account/container/object),系統會使用同樣的一致性哈希算法來確定該對象所在的分區索引(partition index)

接著,在 ring 中查找這個分區所對應的存儲節點。

系統首先會向其中一個存儲節點發送請求以獲取該對象。如果該請求失敗,就會嘗試從其他存儲節點獲取對象。

詳細講解:


下載流程與上傳有些相似,但不需要寫入,而是從副本中讀取:


🧾 步驟 1:客戶端請求下載對象

客戶端通過 REST API 發出 GET /v1/account/container/object 請求。比如:

http
GET /v1/myaccount/photos/avatar.jpg
???🧾 步驟 2:一致性哈希 → 定位分區

Swift 使用 account/container/object 組合字符串生成一個哈希值。

  • 提取哈希中的高位 bits(由 partition power 決定)來得到對象所在的 partition index(分區編號)

這個過程和上傳時是一致的,保證上傳和下載對同一個對象得到的是相同的分區編號


🧾 步驟 3:查詢 ring → 獲取存儲位置

系統通過查詢 ring 文件(比如 object.ring.gz)來查找該分區副本分別位于哪些存儲節點上(通常是三個副本,分布在不同 zone)。

例如:

  • partition 125 可能在節點 A、B、C 上。


🧾 步驟 4:從一個節點請求對象數據

Proxy Server 向節點 A 發出請求獲取 /srv/node/sda/objects/125/xxx_data 中的對象文件。

📌 如果:

  • 節點 A 正常 → 返回數據。

  • 節點 A 故障或超時 → 系統自動嘗試節點 B 或節點 C。

這也是 Swift 高可用性的體現 —— 只要任意副本能成功讀取,就能滿足用戶請求


📌 總結流程圖:

客戶端請求 object → Proxy Server 計算 partition index → 查 ring,定位節點 A/B/C → 優先從 A 獲取對象 → A 不通則嘗試 B,再嘗試 C → 讀取成功 → 返回給客戶端 

📘 說明幾點:

  • Swift 的下載是從副本中任意讀取一個,不是三副本都讀。

  • 數據一致性是通過后臺的 replicator 進程 來維護的(最終一致性)。

  • 這種架構保證了高并發高可用性水平擴展能力

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/77319.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/77319.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/77319.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Spring Boot日志系統詳解:Logback與SLF4J的默認集成

大家好呀!👋 今天我們來聊聊Spring Boot中一個超級重要但又經常被忽視的功能——日志系統! 一、日志系統的重要性 首先,咱們得明白為什么日志這么重要?🤷?♂? 想象一下,你正在玩一個超級復…

【AI提示詞】退休規劃顧問專家

提示說明 隨著人口老齡化的加劇,越來越多的人開始關注退休規劃問題。一個專業的退休規劃顧問可以幫助用戶合理規劃退休生活,確保退休后的生活質量。 提示詞 # 角色 退休規劃顧問專家## 注意 1. 專家設計應符合退休規劃的專業性和可靠性,幫…

樓梯上下檢測數據集VOC+YOLO格式5462張2類別

數據集格式:Pascal VOC格式YOLO格式(不包含分割路徑的txt文件,僅僅包含jpg圖片以及對應的VOC格式xml文件和yolo格式txt文件) 圖片數量(jpg文件個數):5462 標注數量(xml文件個數):5462 標注數量(txt文件個數):5462 …

docker 部署服務工具記錄

一、場景 項目需要使用dify和向量庫milvus, 這兩個工具都是使用docker 部署,因此需要安裝docker. 二、docker安裝 系統為debian , 剛開始安裝不是超時,就是依賴版本沖突,查看系統鏡像源文件: cat /etc/apt/sources.list 覺得可…

Oracle、MySQL、PostgreSQL三大數據庫對比分析

Oracle、MySQL、PostgreSQL 三大數據庫的對比分析,結合 Java SpringBoot 項目開發 的實際場景,重點說明分庫分表、主從復制的實現難度及案例。 一、數據庫核心對比 1. 核心區別與適用場景 維度OracleMySQLPostgreSQL定位企業級商業數據庫輕量級開源數據…

Stable Diffusion LoRA模型加載實現風格自由

對于模型微調來說,直接進行微調需要的硬件配置和時間都是相當夸張的,但要想實現風格切換自由,也不是只有模型微調一個方式,LoRA技術可以說很完美的解決了這個難題。無論是二次元畫風還是復古膠片質感,都只需要加載小巧…

貪心算法day10(無重疊區間)

1.無重疊區間 435. 無重疊區間 - 力扣(LeetCode) 思路: 代碼: class Solution {public static int eraseOverlapIntervals(int[][] intervals) {Arrays.sort(intervals,(v1,v2)->{return v1[0]-v2[0];});int left interva…

Python語言基礎教程(上)4.0

?博客主頁: https://blog.csdn.net/m0_63815035?typeblog 💗《博客內容》:.NET、Java.測試開發、Python、Android、Go、Node、Android前端小程序等相關領域知識 📢博客專欄: https://blog.csdn.net/m0_63815035/cat…

PyTorch 浮點數精度全景:從 float16/bfloat16 到 float64 及混合精度實戰

PyTorch 在深度學習中提供了多種 IEEE 754 二進制浮點格式的支持,包括半精度(float16)、Brain?float(bfloat16)、單精度(float32)和雙精度(float64),并通過統…

在conda環境下使用pip安裝庫無法import

安裝seleniumwire包,conda環境沒有,pip之后安裝不到當前conda環境 網上的方法都試過了,包括強制安裝等 python -m pip install --upgrade --force-reinstall selenium-wire 最后定位應該是沒有安裝到當前conda的環境下,使用list…

【k8s系列4】工具介紹

1、虛擬機軟件 vmware workstation 2、shell 軟件 MobaXterm 3、centos7.9 下載地址 (https://mirrors.aliyun.com/centos/7.9.2009/isos/x86_64/?spma2c6h.25603864.0.0.374bf5adOaiFPW) 4、上網軟件

ApiHug 前端解決方案 - M1 內側

背景 ApiHug UI 解決方案 - ApiHug前后端語義化設計,節約80%以上時間https://apihug.github.io/zhCN-docs/ui 現代前端框架日趨SPA(Single Page Application)化,給前后協同都帶來了挑戰,ApiHug試圖減少多人在前后協同帶來的理解難度&#x…

【人工智能】DeepSeek 與 RAG 技術:構建知識增強型問答系統的實戰

《Python OpenCV從菜鳥到高手》帶你進入圖像處理與計算機視覺的大門! 解鎖Python編程的無限可能:《奇妙的Python》帶你漫游代碼世界 本文深入探討了如何利用 DeepSeek R1 模型結合檢索增強生成(RAG)技術,構建一個高效的知識增強型問答系統。RAG 技術通過結合信息檢索與生…

強大的AI網站推薦(第五集)—— Suno

網站:Suno 號稱:被許多用戶稱為“最強音樂類AI” 博主評價:早在去年1月,我就已經開始使用過了,從小就有一個音樂夢,奈何五音不全,現在用這個來進行創作音樂,有想AI創造音樂的可以試試…

Sigma-Delta ADC(ΣΔ-ADC)中的量化器簡介

Sigma-Delta ADC(ΣΔ-ADC)是一種高精度的模數轉換器,其中的量化器是其核心組件之一。量化器負責將模擬信號轉換為數字信號,并通過獨特的噪聲整形技術實現高分辨率。接下來,我們將深入了解量化器的各個方面&#xff1a…

Oracle日志系統之附加日志

Oracle日志系統之附加日志 在 Oracle 數據庫中,附加日志(Supplemental Log)是一種增強日志記錄的機制,用于在數據庫的 redo log 中記錄更多的變更信息,尤其是在進行數據遷移、復制和同步等任務時,能夠確保…

使用源碼編譯安裝golang的docker版

編譯規則 1.4之前用C寫的&#xff0c;1.4可編譯后續一直到1.9版本&#xff0c;后續版本實現了自舉&#xff0c;后續版本是go寫的&#xff0c;基本上相互低2個版本能編譯出新版本。 Go < 1.4&#xff1a;C 工具鏈。 1.5 < Go < 1.19&#xff1a;Go 1.4 編譯器。 1.20…

Android平臺 Hal AIDL 系列文章目錄

目錄 1. Android Hal AIDL 簡介2. AIDL 語言簡介3. Android 接口定義語言 (AIDL)4. 定義AIDL 接口5. AIDL 中如何傳遞 Parcelable 對象6. 如何使用AIDL 定義的遠程接口進行跨進程通信7. 適用于 HAL 的 AIDL8. Android Hal AIDL 編譯調試9. 高版本Android (AIDL HAL) 沿用HIDL方…

【失敗】Gnome將默認終端設置為 Kitty

起因 一會兒gnome-terminal一會兒kitty終端&#xff0c;實在是受不了&#xff0c;決定取締默認的gnome-terminal。 過程 在 Ubuntu 或 Debian 系統上&#xff1a; 確保 Kitty 已經安裝。如果未安裝&#xff0c;可以在終端中運行命令sudo apt install kitty -y進行安裝。 使用系…

Linux工具學習之【gcc/g++】

&#x1f4d8;前言 書接上文&#xff0c;我們已經學習了 Linux 中的編輯器 vim 的相關使用方法&#xff0c;現在已經能直接在 Linux 中編寫C/C代碼&#xff0c;有了代碼之后就要嘗試去編譯并運行它&#xff0c;此時就可以學習一下 Linux 中的編譯器 gcc/g 了&#xff0c;我們一…