【系統設計】S3 對象存儲

f86c9deec3d8d0cfc95574d5f248e1a0.gif

在本文中,我們設計了一個類似于 Amazon Simple Storage Service (S3) 的對象存儲服務。S3 是 Amazon Web Services (AWS) 提供的一項服務, 它通過基于 RESTful API 的接口提供對象存儲。根據亞馬遜的報告,到 2021 年,有超過 100 萬億個對象存儲在 S3 中。

在深入設計之前,有必要先回顧一下存儲系統和相關的術語。

存儲系統

在高層次上,存儲系統分類三大類:

  • ??塊存儲

  • ??文件存儲

  • ??對象存儲

塊存儲

塊存儲最早出現在 1960 年。常見的物理存儲設備,比如常說的 HDD 和 SSD 都屬于塊存儲。塊存儲直接暴露出來卷或者盤,這是最靈活,最通用的存儲形式。

塊存儲不局限于物理連接的存儲,也可以通過網絡、光纖和 iSCSI 行業標準協議連接到服務器。從概念上講,網絡附加塊存儲仍然暴露原始塊,對于服務器來說,它的工作方式和使用物理連接的塊存儲是相同的。

文件存儲

文件存儲在塊存儲的上層,提供了更高級別的抽象,文件存儲不需要處理管理塊、格式化卷等,所以它處理文件和目錄更簡單,數據文件存儲在分層目錄結構。

對象存儲

對象存儲相對來說比較新,為了高持久性,大規模和低成本而犧牲性能,這是一個非常刻意的權衡。對象存儲針對的是相對 “冷” 的數據,主要用于歸檔和備份。對象存儲把所有的數據作為對象存儲在平面結構中,沒有分層的目錄結構。

通常提供了 RESTful API 用來支持數據訪問,和其他的存儲相比,它是比較慢的,大多云服務商都提供了對象存儲的產品,比如 AWS S3, Azure Blob 存儲等。

對比

905a8f1b6863d12633818efc94fb0417.png

術語

要設計一個類似于 S3 的對象存儲,我們需要先了解一些對象存儲的核心概念。

  • ??桶 (Bucket),桶是對象的邏輯容器,存儲桶名稱是全局唯一的。

  • ??對象(Object),對象時我們存儲在桶中的單個數據,它由對象數據和元數據組成。對象可以是我們存儲的任何字節序列,元數據是一組描述對象的鍵值對。

  • ??版本控制 (Versioning), 數據更新時,允許多版本共存。

  • ??統一資源標識符 (URI),對象存儲提供了 RESTful API 來訪問資源,所以每個資源都有一個URI 唯一標識。

  • ??服務等級協議 (SLA),SLA 是服務提供商和客戶之間的協議。比如 AWS S3 對象存儲,提供了 99.9 的可用性,以及夸張的 99.999999999% (11個9) 的數據持久性。

設計要求

8c8b8beadc44a47f9413c4b832bfc5de.png

在這個面試的系統設計環節中,需要設計一個對象存儲,并且要滿足下面的幾個要求。

  • ??基礎功能,桶管理,對象上傳和下載,版本控制。

  • ??對象數據有可能是大對象(幾個 GB),也可能是小對象(幾十 kb)。

  • ??一年需要存儲 100 PB 的數據。

  • ??服務可用性 99.99% (4個9), 數據持久性 99.9999 % (6個 9)。

  • ??需要比較低的存儲成本。

對象存儲的特點

在開始設計對象存儲之前,你需要了解它的下面這些特點。

對象不變性

對象存儲和其他兩種存儲的主要區別是,存儲對象是不可變的,允許進行刪除或者完全更新,但是不能進行增量修改。

鍵值存儲

我們可以使用 URI 來訪問對象數據,對象的 URI 是鍵,對象的數據是值,如下

Request:
GET?/bucket1/object1.txt?HTTP/1.1Response:
HTTP/1.1?200?OK
Content-Length:?4567[4567?bytes?of?object?data]

寫一次,讀多次

對象數據的訪問模式是一次寫入,多次讀取。根據 LinkedIn 做的研究報告,95 %的請求是讀取操作。

【Ambry: LinkedIn’s Scalable Geo-Distributed Object Store】

支持小型和大型對象

對象存儲的設計理念和 UNIX 文件系統的設計理念非常相似。在 UNIX 中,當我們在本地文件系統中保存文件時,它不會把文件名和文件數據一起保存。那是怎么做的呢?它把文件名存儲在 inode 的數據結構中,把文件數據存儲在不同的磁盤位置。inode 包含一個文件塊指針列表,這些指針指向文件數據的磁盤位置。當我們訪問本地文件時,首先會獲取 inode 中的元數據。然后我們按照文件塊指針來讀取磁盤的文件數據。

對象存儲的工作方式也是如此,元數據和數據存儲分離,如下

af2777b27fd3721ac70527968cb71f43.png

看一看我們的存儲桶和對象的設計

37d2ca273ab490ac91912b82f60c86fc.png

整體設計

下圖顯示了對象存儲的整體設計。

1730349eabed9f7409d07423628ff630.png
  • ? Load balancer 負載均衡,向多個 API 服務分發 RESTful API 請求。

  • ? API Service,編排身份驗證服務,元數據服務和存儲服務,它是無狀態的,可以很好的支持水平擴展。

  • ? Identity & Access Management (IAM),身份和訪問管理,這是處理身份驗證、授權和訪問控制的服務。

  • ? Data Store 數據存儲,存儲和檢索對象數據,所有和數據有關的操作都是基于對象 ID(UUID)。

  • ? Metadata Service 元數據服務,存儲對象的元數據。

接下來我們一起來探索對象存儲中的一些重要的工作流程。

  • ??上傳對象

  • ??下載對象

  • ??版本控制

上傳對象

c760c7289e1de285caf3fdb9da56fa86.png

在上面的流程中,我們首先創建了一個名為 "bucket-to-share" 的存儲桶,然后把一個名為 "script.txt" 的文件上傳到這個桶。

  1. 1. 客戶端發送一個創建 “bucket-to-share” 桶的 HTTP PUT 請求,經過負載均衡器轉發到 API 服務。

  2. 2. API 服務調用 IAM 確保用戶已獲得授權并且有 Write 權限。

  3. 3. API 服務調用元數據服務,創建存儲桶,并返回成功給客戶端。

  4. 4. 客戶端發送創建 “script.txt” 對象的 HTTP PUT 請求。

  5. 5. API 服務驗證用戶的身份并確保用戶對存儲桶具有 Write 權限。

  6. 6. API 服務把 HTTP 請求發到到數據存儲服務,完成存儲后返回對象的 UUID。

  7. 7.?調用元數據服務并創建元數據項,格式如下

    6537a9b63132580ec3cac3879ec99175.png

上傳數據的 Http 請求示例如下

69d60ef85e7ae8db70231639c323edc5.png

下載對象

存儲對象可以通過 HTTP GET 請求進行下載,示例如下

39ed4c3b476b841ea90ead52fe2e683f.png

下載流程圖

1a153022e97e42bb48817eb6b04433b8.png
  1. 1.?客戶端發送 GET 請求,GET /bucket-to-share/script.txt

  2. 2. API 服務查詢 IAM 驗證用戶是否有對應桶的讀取權限。

  3. 3. 驗證后,API 服務會從元數據服務中獲取對象的 UUID。

  4. 4. 通過 對象的 UUID 從數據存儲中獲取相應的對象。

  5. 5. API 服務返回對象給客戶端。

深入設計

接下來,我們會討論下面幾個比較重要的部分。

  • ??數據一致性

  • ??元數據

  • ??版本控制

  • ??優化大文件的上傳

  • ??垃圾收集 GC

數據一致性

對象數據只存放在單個節點肯定是不行的,為了保證高可用,需要把數據復制到多個節點。這種情況下,我們需要考慮到一致性和性能問題。

d8563071bd5bbf03790018acf9cb5400.png

保證強一致性就要犧牲性能,如果性能要求比較高時,可以選擇弱一致性。魚和熊掌不可兼得。

數據存儲方式

對于數據存儲,一個簡單的方式是把每個對象都存儲在一個獨立的文件中,這樣當然是可以的。但是,當有大量的小型文件時,會有下面兩個問題。

第一個問題是,會浪費很多數據塊。文件系統把文件存儲在磁盤塊中,磁盤塊的大小在卷初始化的時候就固定了,一般是 4 kb。所以,對于小于 4kb 的文件,它也會占滿整個磁盤塊。如果文件系統中保存了大量的小文件,那就會就會有很多浪費。

第二個問題是,系統的 inode 容量是有限的。文件系統把文件元數據存儲在 inode 特殊類型的磁盤塊中。對于大多數文件系統,inode 的數量在磁盤初始化時是固定的。所以有大量的文件時,要考慮到 inode 容量滿的問題。

為了解決這個問題,我們可以把很多小文件合并到一個更大的文件中。從概念上講,類似于預寫日志(WAL)。當我們保存一個對象時,它被附加到一個現有的文件中。文件大小達到一定值(比如說 1 GB)后,創建一個新的文件來存儲對象,下圖解釋了它的工作流程。

0df051c75649659ee8814cd6dabe0647.png

數據持久性

對存儲系統來說,數據持久性非常重要,如何設計出一個 6 個 9 (99.9999%) 持久性 的存儲系統?

硬件故障和故障域

無論使用哪種存儲,硬件故障都是不可避免的。所以為了數據持久性,需要把數據復制到多個硬盤中。

假設硬盤的年故障率是 0.81 %, 當然不同的型號和品牌這些是不一樣的,那個我們需要三個數據副本,1-(0.0081)^3=~0.999999, 才可以滿足要求。

另外,我們還需要考慮到不同故障域的影響。這樣可以在極端情況下,帶來更好的可靠性,比如大規模停電,自然災害等。

3188356e612f6772df27f4acb8385a13.png

Erasure Coding 糾刪碼

上面提到,我們用三個完整的數據副本可以提供大概 6 個 9 的數據持久性,但是,這樣的成本太高了。

還能不能優化呢?我們可以使用糾刪碼技術,它的原理其實很簡單,假設現在有 a 和 b 兩條數據,進行異或 (XOR)運算后得到 c,a ^ b = c , 而 b = c ^ a,a = c ^ b,所以這三條數據丟失任意一條數據,都可以通過剩余兩條數據計算出丟失數據。

下面是一個 4 +2 糾刪碼的例子。

3e21667fe2909f754ca4d236006fbad7.png
  1. 1. 數據被分成四個大小均勻的數據塊 d1、d2、d3 和 d4。

  2. 2.?使用 Reed-Solomon 數學公式計算校驗塊,比如?p1?=?d1?+?2*d2?-?d3?+?4*d4?
    p2?=?-d1?+?5*d2?+?d3?-?3*d4?

  3. 3. 節點崩潰,導致數據 d3 和 d4 丟失。

  4. 4. 通過數據公式和現有數據,計算出丟失的數據并恢復。d3?=?3*p1?+?4*p2?+?d1?-?26*d2
    d4?=?p1?+?p2?-?7*d2

和多副本復制相比,糾刪碼占用的存儲空間更少。但是,在進行丟失數據恢復時,它需要先根據現有數據計算出丟失數據,這也消耗了 CPU 資源。

數據完整性校驗

糾刪碼技術在保證數據持久性的同時,也降低的存儲成本。接下來,我們可以繼續解決下一個難題:數據損壞。

我們可以給數據通過 Checksum 算法計算出校驗和。常見的 checksum 算法有 MD5, SHA1 等。

55e814a94c732b50f990f47726666f98.png

當需要驗證數據時,只需要對比校驗和即可,如果不一致,說明文件數據發生了改變。

我們同樣可以把校驗和添加到存儲系統中,對于讀寫文件,每個對象都計算校驗和,而對于只讀文件,只需要在文件的末尾添加上整個文件的校驗和即可。

7f3fad0a1b02a7c49d85b6bbe515edb5.png

版本控制

版本控制可以讓一個對象的多個版本同時保存在存儲桶中。這樣的好處是,我們可以恢復意外刪除或者覆蓋的對象。

為了支持版本控制,元數據存儲的列表中需要有一個 object_version 的列。上傳對象文件時,不是直接覆蓋現有的記錄,而是插入一個新記錄。

8eedf02270424d01a40a5867bdc16860.png

當進行對象刪除的時候,不需要刪除這條記錄,而是添加一個刪除標記即可,然后等垃圾收集器自動處理它。

2b1431658de764cc442b86c173e23732.png

優化大文件上傳

對于比較大的對象文件(可能有幾個 GB),上傳可能需要較長的時間。如果在上傳過程中網絡連接失敗,就要重新進行上傳了。

為了解決這個問題,我們可以使用分段上傳,上傳失敗時可以快速恢復。

c77141afeb3aefb25f4592b5627f75a9.png
  1. 1. 客戶端調用對象存儲服務發起分段上傳請求。

  2. 2. 數據存儲服務返回一個唯一的 uploadID。

  3. 3. 客戶端把大文件拆分為小對象并開始上傳,假設文件大小是 1.6 GB, 每個部分的大小是 200 MB, 客戶端上傳第一部分和 uploadID 。

  4. 4. 上傳第一部分后,數據存儲服務會返回一個 ETag,本質上它是第一部分的 md5 校驗和,客戶端通過它來判斷數據是否發生了更改,如果是則重新上傳。

  5. 5. 當每個部分都上傳成功后,客戶端發送一個分段上傳成功的請求。

  6. 6. 數據存儲服務組裝小對象為大文件,并返回一個成功消息。

垃圾收集 GC

垃圾收集是自動回收不再使用的存儲空間的過程,數據可能變成垃圾的幾種方式:

  • ??延遲刪除的對象,對象在刪除時標記成已刪除,但實際上還沒有刪除。

  • ??孤兒數據,比如上傳一半的數據。

  • ??損壞的數據。

對于需要刪除的對象,我們使用壓縮機制定期清理,下圖顯示了它的工作流程。

13570168df1ad0786cac8155f892a267.png
  1. 1. 垃圾收集器把對象 “/data/b”復制到一個名為“/data/d”的新文件中。這里會跳過對象 2 和 5,因為它們的刪除標志都是 true。

  2. 2. 復制完所有的對象后,垃圾收集器會更新 object_mapping 表,指向新的文件地址,然后刪除掉舊的文件。

總結

在本文中,介紹了類似于 S3 的對象存儲,比較了塊存儲、文件存儲和對象存儲之間的區別,設計了對象上傳,對象下載,版本控制功能,并討論了兩種提高可靠性和持久性的方法:復制和糾刪碼,最后介紹了對象存儲的垃圾收集的工作流程。

希望這篇設計對象存儲的文章對大家有用!

Reference

[0] System Design Interview Volume 2:
https://www.amazon.com/System-Design-Interview-Insiders-Guide/dp/1736049119

[1] Fibre channel: https://en.wikipedia.org/wiki/Fibre_Channel

[2] iSCSI: https://en.wikipedia.org/wiki/ISCSI

[3] Server Message Block: https://en.wikipedia.org/wiki/Server_Message_Block

[4] Network File System: https://en.wikipedia.org/wiki/Network_File_System

[5] Amazon S3 Strong Consistency: https://aws.amazon.com/s3/consistency/

[6] Serial Attached SCSI: https://en.wikipedia.org/wiki/Serial_Attached_SCSI

[7] AWS CLI ls command: https://docs.aws.amazon.com/cli/latest/reference/s3/ls.html

[8] Amazon S3 Service Level Agreement: https://aws.amazon.com/s3/sla/

[9] Ambry: LinkedIn’s Scalable Geo-Distributed Object Store: https://assured-cloud-computing.illinois.edu/files/2014/03/Ambry-LinkedIns-Scalable-GeoDistributed-Object-Store.pdf

[10] inode: https://en.wikipedia.org/wiki/Inode

[11] Ceph’s Rados Gateway: https://docs.ceph.com/en/pacific/radosgw/index.html

[12] grpc: https://grpc.io/

[13] Paxos: https://en.wikipedia.org/wiki/Paxos_(computer_science)

[14] Raft: https://raft.github.io/

[15] Consistent hashing: https://www.toptal.com/big-data/consistent-hashing

[16] RocksDB: https://github.com/facebook/rocksdb

[17] SSTable: https://www.igvita.com/2012/02/06/sstable-and-log-structured-storage-leveldb/

[18] B+ tree: https://en.wikipedia.org/wiki/B%2B_tree

[19] SQLite: https://www.sqlite.org/index.html

[20] Data Durability Calculation: https://www.backblaze.com/blog/cloud-storage-durability/

[21] Rack: https://en.wikipedia.org/wiki/19-inch_rack

[22] Erasure Coding: https://en.wikipedia.org/wiki/Erasure_code

[23] Reed–Solomon error correction:?https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction

[24] Erasure Coding Demystified: https://www.youtube.com/watch?v=Q5kVuM7zEUI

[25] Checksum:https://en.wikipedia.org/wiki/Checksum

[26] Md5: https://en.wikipedia.org/wiki/MD5

[27] Sha1: https://en.wikipedia.org/wiki/SHA-1

[28] Hmac: https://en.wikipedia.org/wiki/HMAC

[29] TIMEUUID: https://docs.datastax.com/en/cql-oss/3.3/cql/cql_reference/timeuuid_functions_r.html

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

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

相關文章

轉: telnet命令學習

1.每天一個linux命令(58):telnet命令 轉自: http://www.cnblogs.com/peida/archive/2013/03/13/2956992.html telnet命令通常用來遠程登錄。telnet程序是基于TELNET協議的遠程登錄客戶端程序。Telnet協議是TCP/IP協議族中的一員&a…

禪道、碼云、coding、redmine、jira、teambition幾大敏捷開發項目管理系統試用對比體驗

作為一個軟件公司的管理人員,在項目和人員多起來后,就需要通過系統來對項目和人員進行管理。 我們是典型的軟件外包公司,專為客戶定制軟件,所以我們的業務都是項目型的。因此,在管理模式上,我們就要用所謂…

Dubbo中的SPI機制

Dubbo中的SPI機制 概述 Service Provider Interface 即 SPI,是JDK內置的一種服務提供發現機制,可以用來啟用框架擴展和替換組件。可以讓不同的廠商針對統一接口編寫不同的實現 SPI實際上是“接口策略模式配置文件”實現的動態加載機制。在系統設計中&…

JWT:擁有我,即擁有權力

Hi,這里是桑小榆。上篇文章中,我們一起探討了 OAuth 協議的原理以及授權認證流程,本次我們一起探討 jwt 令牌作為授權協議的傳輸介質。OAuth協議規范了幾個參與角色的授權標準,安全可控的授予第三方應用,第三方應用獲取…

雙十一到來之前,阿里AI設計師“魯班”1天能做4000萬張海報

相比較去年,“魯班”的設計技藝有所提升。 人工智能很大程度上便利了我們的生活,現在他們甚至還能取代了一些設計師的工作,在雙十一正式到來之前,淘寶的宣傳已經鋪天蓋地,然而很多人都沒想到,我們打開淘寶…

Appium移動自動化測試之獲取appPackage和appActivity

方法一:直接打開Appium,點擊左上角機器人圖標 選擇apk所在位置,如圖所示,這里以ContactManager.apk為例 方法二:利用dex2jar和jd-gui這兩個工具反編譯apk文件 這里仍以ContactManager.apk為例 (1)重命名ContactManager.apk為Conta…

CAD轉WPF: 關于CAD圖紙文件轉換為WPF矢量代碼文件(xaml文件)的技巧

前言:下面的文章,我將會以幾個很簡單的步驟,來演示一下通過CAD圖紙轉換為XAML代碼文件的方法,供大佬們參考。一、為了演示一個簡單的操作,我此處先打開一個空白的CAD,等下用來進行繪制點內容使用。二、自定…

python之新式類與經典類

經典類與新式類經典類:P 或 P()--深度查找,向上查父節點新式類 :P(object)---廣度查找,繼承object,新式類的方法較多轉載于:https://www.cnblogs.com/zyy98877/p/8574983.html

Flowportal-BPM——環境配置

環境配置: 一、控制面板→程序和功能→打開或不關閉Window功能→選擇選項 二、控制面板→管理工具→Internet信息服務(IIS)管理器→左側第一個→ISAPI和CGI限制→全部選為【允許】 三、控制面板→管理工具→Internet信息服務(IIS&…

一篇文章帶你搞懂什么是DevOps?

DevOps DevOps 它的英文發音是 /de’v?ps/,類似于“迪沃普斯”,一詞本身是對于 development 以及 operation 兩個詞的混合,其目的在于縮短系統開發的生命周期,在這過程中發布特性、修復bug以及更新均被緊密的結合。 簡化的含義為…

iOS 時間戳的轉換

在開發iOS程序時,有時候需要將時間格式調整成自己希望的格式,這個時候我們可以用NSDateFormatter類來處理。例如: //實例化一個NSDateFormatter對象 NSDateFormatter *dateFormatter [[NSDateFormatter alloc] init]; //設定時間格式,這里可…

微服務架構下分布式事務解決方案 —— 阿里GTS

1 微服務的發展 微服務倡導將復雜的單體應用拆分為若干個功能簡單、松耦合的服務,這樣可以降低開發難度、增強擴展性、便于敏捷開發。當前被越來越多的開發者推崇,很多互聯網行業巨頭、開源社區等都開始了微服務的討論和實踐。Hailo有160個不同服務構成&…

重要消息丨.NET Core 3.1 將于今年12月13日結束支持

點擊上方藍字關注我們(本文閱讀時間:5分鐘).NET Core 3.1 將于 2022 年 12 月 13 日結束支持。此后,Microsoft 將不再為 .NET Core 3.1 提供服務更新或技術支持。我們建議盡快遷移到 .NET 6。如果您在支持日期結束后仍在使用 .NET Core 3.1&a…

產品設計的三大原則

1.它有用嗎? 如果我們必須從這三個特性中選擇一個作為最重要的,那就是有用性。 首要的是,一個產品必須有用。如果它無用,其它任何東西都是不相關的,因為沒有人會需要它。很明顯,有用性和可享用性看上去一樣重要&#…

常用的17個運維監控系統

1. Zabbix Zabbix 作為企業級的網絡監控工具,通過從服務器,虛擬機和網絡設備收集的數據提供實時監控,自動發現,映射和可擴展等功能。 Zabbix的企業級監控軟件為用戶提供內置的Java應用服務器監控,硬件監控&#xff0c…

關于html-三角的制作

因為最近看到別人寫的不錯的樣式,所以就想自己實現,但是呢用到了一個三角形,所以稍微研究一下。效果是這樣的:注意是下邊那個淺色三角,感覺書簽的效果有木有。看著很有層次感。接下來就是實現了,利用border…

ABP中的數據過濾器

本文首先介紹了ABP內置的軟刪除過濾器(ISoftDelete)和多租戶過濾器(IMultiTenant),然后介紹了如何實現一個自定義過濾器,最后介紹了在軟件開發過程中遇到的實際問題,同時給出了解決問題的一個未必最優的思路。一.預定義過濾器ABP中的數據過濾…

ActiveMQ與spring整合

2019獨角獸企業重金招聘Python工程師標準>>> 1 生產者 第一步&#xff1a;引用相關的jar包。 <dependency> <groupId>org.springframework</groupId><artifactId>spring-jms</artifactId> </dependency> <dependency><…

最新遠程部署運維工具匯總

一&#xff0e;Puppet 轉載https://baike.baidu.com/item/puppet/5109503?fraladdin puppet是一種Linux、Unix、windows平臺的集中配置管理系統&#xff0c;使用自有的puppet描述語言&#xff0c;可管理配置文件、用戶、cron任務、軟件包、系統服務等。puppet把這些系統實體…

Kali Linux 2016.2初體驗使用總結

Kali Linux 2016.2初體驗使用總結Kali Linux官方于8月30日發布Kali Linux 2016的第二個版本Kali Linux 2016.2。該版本距離Kali Linux 2016.1版本發布&#xff0c;已經有7個月。在這期間&#xff0c;在Kali Linux 2016.2版本發布的這段時間&#xff0c;Kali Linux官方增補了94個…