最近在找工做時被問到swift底層的一些原理,爲了之後能有印象,因此決定作一下筆記git
如下由(http://www.openstack.cn/?p=776)轉載github
——Openstack Swift 開源雲存儲技術解析算法
OpenStack Swift 開源項目提供了彈性可伸縮、高可用的分佈式對象存儲服務,適合存儲大規模非結構化數據。本文將深刻介紹 Swift 的基本設計原理、對稱式的系統架構和 RESTful API。數據庫
Swift 最初是由 Rackspace 公司開發的高可用分佈式對象存儲服務,並於 2010 年貢獻給 OpenStack 開源社區做爲其最初的核心子項目之一,爲其 Nova 子項目提供虛機鏡像存儲服務。Swift 構築在比較便宜的標準硬件存儲基礎設施之上,無需採用 RAID(磁盤冗餘陣列),經過在軟件層面引入一致性散列技術和數據冗餘性,犧牲必定程度的數據一致性來達到高可用性和可伸縮性,支持多租戶模式、容器和對象讀寫操做,適合解決互聯網的應用場景下非結構化數據存儲問題。編程
此項目是基於 Python 開發的,採用 Apache 2.0 許可協議,可用來開發商用系統。swift
面對海量級別的對象,須要存放在成千上萬臺服務器和硬盤設備上,首先要解決尋址問題,即如何將對象分佈到這些設備地址上。Swift 是基於一致性散列技術,經過計算可將對象均勻分佈到虛擬空間的虛擬節點上,在增長或刪除節點時可大大減小需移動的數據量;虛擬空間大小一般採用 2 的 n 次冪,便於進行高效的移位操做;而後經過獨特的數據結構 Ring(環)再將虛擬節點映射到實際的物理存儲設備上,完成尋址過程。api
如圖 1 中所示,以逆時針方向遞增的散列空間有 4 個字節長共 32 位,整數範圍是[0~232-1];將散列結果右移 m 位,可產生 232-m個虛擬節點,例如 m=29 時可產生 8 個虛擬節點。在實際部署的時候須要通過仔細計算獲得合適的虛擬節點數,以達到存儲空間和工做負載之間的平衡。數組
按照 Eric Brewer 的 CAP(Consistency,Availability,Partition Tolerance)理論,沒法同時知足 3 個方面,Swift 放棄嚴格一致性(知足 ACID 事務級別),而採用最終一致性模型(Eventual Consistency),來達到高可用性和無限水平擴展能力。爲了實現這一目標,Swift 採用 Quorum 仲裁協議(Quorum 有法定投票人數的含義):緩存
(1)定義:N:數據的副本總數;W:寫操做被確認接受的副本數量;R:讀操做的副本數量服務器
(2)強一致性:R+W>N,以保證對副本的讀寫操做會產生交集,從而保證能夠讀取到最新版本;若是 W=N,R=1,則須要所有更新,適合大量讀少許寫操做場景下的強一致性;若是 R=N,W=1,則只更新一個副本,經過讀取所有副原本獲得最新版本,適合大量寫少許讀場景下的強一致性。
(3)弱一致性:R+W<=N,若是讀寫操做的副本集合不產生交集,就可能會讀到髒數據;適合對一致性要求比較低的場景。
Swift 針對的是讀寫都比較頻繁的場景,因此採用了比較折中的策略,即寫操做須要知足至少一半以上成功 W >N/2,再保證讀操做與寫操做的副本集合至少產生一個交集,即 R+W>N。Swift 默認配置是 N=3,W=2>N/2,R=1 或 2,即每一個對象會存在 3 個副本,這些副本會盡可能被存儲在不一樣區域的節點上;W=2 表示至少須要更新 2 個副本纔算寫成功;當 R=1 時意味着某一個讀操做成功便馬上返回,此種狀況下可能會讀取到舊版本(弱一致性模型);當 R=2 時,須要經過在讀操做請求頭中增長 x-newest=true 參數來同時讀取 2 個副本的元數據信息,而後比較時間戳來肯定哪一個是最新版本(強一致性模型);若是數據出現了不一致,後臺服務進程會在必定時間窗口內經過檢測和複製協議來完成數據同步,從而保證達到最終一致性。如圖 2 所示:
環是爲了將虛擬節點(分區)映射到一組物理存儲設備上,並提供必定的冗餘度而設計的,其數據結構由如下信息組成:
以查找一個對象的計算過程爲例:
使用對象的層次結構 account/container/object 做爲鍵,使用 MD5 散列算法獲得一個散列值,對該散列值的前 4 個字節進行右移操做獲得分區索引號,移動位數由上面的 part_shift 設置指定;按照分區索引號在分區到設備映射表(replica2part2dev_id)裏查找該對象所在分區的對應的全部設備編號,這些設備會被儘可能選擇部署在不一樣區域(Zone)內,區域只是個抽象概念,它能夠是某臺機器,某個機架,甚至某個建築內的機羣,以提供最高級別的冗餘性,建議至少部署 5 個區域;權重參數是個相對值,能夠來根據磁盤的大小來調節,權重越大表示可分配的空間越多,可部署更多的分區。
Swift 爲帳戶,容器和對象分別定義了的環,查找帳戶和容器的是一樣的過程。
Swift 採用層次數據模型,共設三層邏輯結構:Account/Container/Object(即帳戶/容器/對象),每層節點數均沒有限制,能夠任意擴展。這裏的帳戶和我的帳戶不是一個概念,可理解爲租戶,用來作頂層的隔離機制,能夠被多個我的帳戶所共同使用;容器表明封裝一組對象,相似文件夾或目錄;葉子節點表明對象,由元數據和內容兩部分組成,如圖 4 所示:
系統架構
Swift 採用徹底對稱、面向資源的分佈式系統架構設計,全部組件均可擴展,避免因單點失效而擴散並影響整個系統運轉;通訊方式採用非阻塞式 I/O 模式,提升了系統吞吐和響應能力。
Swift 經過 Proxy Server 向外提供基於 HTTP 的 REST 服務接口,對帳戶、容器和對象進行 CRUD 等操做。在訪問 Swift 服務以前,須要先經過認證服務獲取訪問令牌,而後在發送的請求中加入頭部信息 X-Auth-Token。下面是請求返回帳戶中的容器列表的示例:
GET /v1/<account> HTTP/1.1 Host: storage.swift.com X-Auth-Token: eaaafd18-0fed-4b3a-81b4-663c99ec1cbb 響應頭部信息中包含狀態碼 200,容器列表包含在響應體中: HTTP/1.1 200 Ok Date: Thu, 07 Jan 2013 18:57:07 GMT Server: Apache Content-Type: text/plain; charset=UTF-8 Content-Length: 32 images movies documents backups
Swift 支持的全部操做能夠總結爲表 1:
資源類型 | URL | GET | PUT | POST | DELETE | HEAD |
---|---|---|---|---|---|---|
帳戶 | /account/ | 獲取容器列表 | - | - | - | 獲取帳戶元數據 |
容器 | /account/container | 獲取對象列表 | 建立容器 | 更新容器元數據 | 刪除容器 | 獲取容器元數據 |
對象 | /account/container/object | 獲取對象內容和元數據 | 建立、更新或拷貝對象 | 更新對象元數據 | 刪除對象 | 獲取對象元數據 |
詳細的 API 規範能夠參考開發者指南。應用開發可採用 Swift 項目自己已經包含的 Python 的綁定實現;若是使用其它編程語言,能夠參考 Rackspace 兼容 Swift 的 Cloud Files API,支持 Java,.Net,Ruby,PHP 等語言綁定。
OpenStack Swift 做爲穩定和高可用的開源對象存儲被不少企業做爲商業化部署,如新浪的 App Engine 已經上線並提供了基於 Swift 的對象存儲服務,韓國電信的 Ucloud Storage 服務。有理由相信,由於其徹底的開放性、普遍的用戶羣和社區貢獻者,Swift 可能會成爲雲存儲的開放標準,從而打破 Amazon S3 在市場上的壟斷地位,推進雲計算在朝着更加開放和可互操做的方向前進。