分布式对象存储设计原理
保存像圖片、音視頻這類大文件就是對象存儲。不僅有很好的大文件讀寫性能,還可通過水平擴展實現近乎無限容量,并兼顧服務高可用、數據高可靠。
對象存儲“全能”,主要因,對象存儲是原生分布式存儲系統,相對于MySQL、Redis這類單機存儲系統來說。雖然這些非原生存儲系統,也具備集群能力,但它們構建大規模分布式集群非常不容易。
隨云計算普及,很多新生代存儲系統,都是原生分布式系統,一開始設計目標之一就是分布式存儲集群,如[Elasticsearch]、[Ceph]和國內很多大廠推出的新一代數據庫,做到:
- 近乎無限的存儲容量
- 超高的讀寫性能
- 數據高可靠:節點磁盤損毀不會丟數據
- 實現服務高可用:節點宕機不會影響集群對外提供服務
這些原生分布式存儲如何實現這些特性?“互相抄作業”,除了存儲的數據結構不一樣,提供的查詢服務不一樣以外,這些分布式存儲系統,面臨的很多問題都一樣,實現方法差不多。
對象存儲的查詢服務和數據結構都簡單,是最簡單的原生分布式存儲系統。
1 對象存儲數據是如何保存大文件的?
對象存儲對外提供的服務,就是個近乎無限容量的大文件KV存儲,所以對象存儲和分布式文件系統之間,沒有那么明確的界限。對象存儲的內部,肯定有很多的存儲節點,用于保存這些大文件,這個就是數據節點的集群。
為管理這些數據節點和節點中的文件,還需要一個存儲系統保存集群的節點信息、文件信息和它們的映射關系。這些為管理集群而存儲的數據,叫元數據(Metadata)。保存元數據的存儲系統須是個集群。但元數據集群存儲的數據量少,數據變動不頻繁,客戶端或網關都會緩存一部分元數據,所以元數據集群對并發要求不高。類似ZooKeeper或者etcd這類分布式存儲就可。
存儲集群為對外提供訪問服務,還要一個網關集群,對外接收外部請求,對內訪問元數據和數據節點。網關集群中的每個節點不需保存任何數據,都是無狀態節點。有些對象存儲沒有網關,是客戶端,功能和作用一樣。
對象存儲如何處理對象讀寫請求?處理讀和寫請求的流程一樣。網關收到對象讀寫請求后,先拿請求中的Key,去元數據集群查找這Key在哪個數據節點,再去訪問對應數據節點讀寫數據,最后把結果返回給客戶端。
這張圖雖畫的對象存儲集群結構,但名詞改改,可套用到絕大多數分布式文件系統和數據庫上去,如HDFS。
2 對象如何拆分和保存的?
對象存儲如何保存大文件對象。一般,對象存儲中保存的文件都是圖片、視頻大文件。在對象存儲中,每個大文件都會被拆成多個大小相等塊兒(Block),把文件從頭到尾按固定塊大小,切成一塊一塊,最后一塊長度有可能不足一個塊大小,也按一塊處理。塊大小配置為幾十KB到幾MB。
大對象文件拆分成塊的目的:
- 提升讀寫性能,這些塊可分散到不同的數據節點,就可并行讀寫
- 把文件分成大小相等塊兒,便于維護管理
對象被拆成塊后,還是過于碎片化,如直接管理這些塊,會導致元數據的數據量大,也沒必要管理到這么細粒度。所以一般都會再把塊聚合,放到塊的容器。“容器”,存放一組塊的邏輯單元。沒有統一叫法,如ceph中稱為Data Placement。容器內的塊數大多固定,所以容器大小也固定。
容器類似MySQL和Redis的“分片”,都是復制、遷移數據的基本單位。每個容器都會有N個副本,這些副本的數據都一樣。其中有一個主副本,其他是從副本,主副本負責數據讀寫,從副本去到主副本上去復制數據,保證主從數據一致。
對象存儲一般不記錄類似Binlog的日志。主從復制復制的不是日志,而是整塊數據:
以上的對象(即文件)、塊和容器,都是邏輯層概念,數據落實到副本上,這些副本就是真正物理存在。這些副本再被分配到數據節點上保存起來。這里的數據節點就是運行在服務器上的服務進程,負責在本地磁盤上保存副本的數據。
數據訪問
請求一個Key時:
- 網關首先去元數據查找這個Key的元數據
- 然后根據元數據中記錄的對象長度,計算出對象有多少塊
- 就可分塊并行處理。對每個塊,還要再去元數據,找到它被放在哪個容器
容器就是分片,怎么把塊映射到容器,不同的系統選擇實現的方式也不一樣,有用哈希分片的,也有用查表法把對應關系保存在元數據。找到容器后,再去元數據中查找容器的N個副本都分布在哪些數據節點上。然后,網關直接訪問對應的數據節點讀寫數據就可以了。
小結
對象存儲是最簡單的分布式存儲系統,主要由數據節點集群、元數據集群和網關集群(或者客戶端)三部分構成。數據節點集群負責保存對象數據,元數據集群負責保存集群的元數據,網關集群和客戶端對外提供簡單的訪問API,對內訪問元數據和數據節點讀寫數據。
為了便于維護和管理,大的對象被拆分為若干固定大小的塊兒,塊兒又被封裝到容器(也就分片)中,每個容器有一主N從多個副本,這些副本再被分散到集群的數據節點上保存。
對象存儲雖然簡單,但是它具備一個分布式存儲系統的全部特征。所有分布式存儲系統共通的一些特性,對象存儲也都具備,比如說數據如何分片,如何通過多副本保證數據可靠性,如何在多個副本間復制數據,確保數據一致性等等。
希望你通過這節課的學習,不僅是學會對象存儲,還要對比分析一下,對象存儲和其他分布式存儲系統,比如MySQL集群、HDFS、Elasticsearch等等這些,它們之間有什么共同的地方,差異在哪兒。想通了這些問題,你對分布式存儲系統的認知,絕對會上升到一個全新的高度。然后你再去看一些之前不了解的存儲系統,就非常簡單了。
FAQ
對象存儲不是基于日志來進行主從復制。假設對象存儲一主二從三副本,采用半同步方式復制數據,即主副本和任意一個從副本更新成功后,就給客戶端返回成功響應。主副本所在節點宕機之后,這兩個從副本中,至少有一個副本上的數據是和宕機的主副本上一樣的,我們需要找到這個副本作為新的主副本,才能保證宕機不丟數據。
但沒有日志,如果這兩個從副本上的數據不一樣,如何確定哪個上面的數據是和主副本一樣新?
如果出現緩存不同步的情況,在你負責的業務場景下,該如何降級或者補償?
設置一個合理TTL,即使出現緩存不同步,等緩存過期后就會自動恢復。再如識別用戶手動刷新操作,強制重新加載緩存數據(注意防止大量緩存穿透)。還可以在管理員后臺系統中,預留一個手動清除緩存的功能,必要的時候人工干預。
做素材庫的,現在自建對象服務器,對象服務器里面大多都是圖片素材,場景是讀多寫少。選擇Ceph可以用于生成環境嗎?建議你使用公有云的對象存儲服務,小規模的公司自建對象存儲維護成本太高,不是太劃算。
對象存儲的cdn緩存是怎么做的?是每次要訪問這些元數據,還是直接把這些源數據所有都放在內存里?數據量這么大感覺不適合放內存里吧?CDN緩存的文件一般是保存在CDN節點的磁盤上,當然不排除某些CDN會用節點的內存緩存文件,加速訪問。
為什么分塊后又聚合到容器中,直接一個容器一個塊不行嗎?
一個容器就是一個分片,是數據復制的基本單位。也就是說,每個分片都有n個 副本。
分片不能做的太小,越小意味著存儲同樣容量的數據,分片數量越多。數量過多,查找分片時,需要查找的元數據就會太多,影響查找效率。
對數據復制,同樣要有一定的開銷,比如記錄日志位置,維護數據一致性的開銷。分片太小,相對的,這些開銷就大。
數據冗余技術主要由兩種:
\1. 傳統副本復制
\2. 糾刪碼,基于糾刪算法,時間換空間 (著名開源對象存儲MinIO就是基于糾刪碼的)
總結
以上是生活随笔為你收集整理的分布式对象存储设计原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 最新目标检测算法回顾2022笔记
- 下一篇: 嵌入式学习笔记7 WIFI相关1——WI