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