在分布式存儲里面,比較常見的有kafka,Hbase,HDFS,fastDFS等,這里面涉及到文件的分布式存儲以及數(shù)據(jù)的分布式存儲。分布式存儲的背景:就是將數(shù)據(jù)文件分散的存儲到分布式集群的每一個節(jié)點,提升了存儲的容量(大數(shù)據(jù)化);同時盡量凸顯分布式的檢索能力。分布式存儲的原理:分層化的hash映射、數(shù)據(jù)組織的數(shù)據(jù)摘要以及塊數(shù)據(jù)的葉子索引結(jié)構(gòu);這幾種數(shù)據(jù)結(jié)構(gòu)相結(jié)合的方式提供快速檢索的能力和存儲結(jié)構(gòu)。
先說說HDFS,其實比較早的分布式存儲解決方案;HDFS讀寫都是都是從NameNode點開始的,獲取對應(yīng)目錄結(jié)構(gòu)的region所有在的dataNode,然后從對應(yīng)的dataNode讀寫數(shù)據(jù)。HDFS內(nèi)部節(jié)點的管理是依據(jù)zookeeper. 每一個節(jié)點都會分配region(節(jié)點最多也就是1000個region),每一個節(jié)點的region信息存儲到master節(jié)點,集群的NameNode節(jié)點存儲每一個節(jié)點的元region、block(block默認大小是64MB;3.0版本是128MB)信息,還有目錄樹結(jié)構(gòu)數(shù)據(jù)對應(yīng)block信息,輔助master節(jié)點進行元數(shù)據(jù)的。region信息在master上生成一個hash結(jié)構(gòu),在讀取數(shù)據(jù)的數(shù)據(jù)的時候可以很快定位到具體的節(jié)點和region, 網(wǎng)絡(luò)通信是依靠NIO建立的socket通信,同時region文件讀取是DMA技術(shù)(換句話說hdfs底層是依靠netty實現(xiàn)的通信)。
?Hbase本質(zhì)上在文件上存儲也是基于HDFS,但是在管理region上,master節(jié)點上專門建立了一個table,來存儲region對應(yīng)位置region中包含block,block之間是靠著鏈表存儲的。Hbase存儲是默認將id按照順序分割不同的region,然后region又會分為小的block。每一個block都有最大id來標記,類似于kafka patition存儲一樣,里面包含segment,segment信息描述文件,然后block依托著鏈表來存儲連接。每一個block內(nèi)部存儲的數(shù)據(jù)也是按照id順序存儲的,然后每一個block都對應(yīng)一個葉子索引就是B+樹。對于某一列屬性建立二級索引和列對應(yīng)起來,那么就會建立另外以某列屬性值為key,行的id為value建立B+樹。
Hbase還有很重要的緩存機制,上面只是說了數(shù)據(jù)文件的存儲機制,其實hbase的高性能很大一部分上來自于基于內(nèi)存的緩存機制。在讀寫數(shù)據(jù)的時候,client都會請求zookeeper,獲取最新的region metatable信息,也就是region信息,那么client才會知道去鏈接哪一個region。在寫數(shù)據(jù)的時候(metatable也會記錄每一個region對應(yīng)的最大id),也會有對應(yīng)的region節(jié)點選擇和鏈接。
首先將數(shù)據(jù)寫到write_ahead_log(簡稱WAL,這和mysql的binlog類似),然后write_ahead_log讀到內(nèi)存中,會在內(nèi)存中按照對應(yīng)id序列拍好序的(整個內(nèi)存塊mem-store),當mem-store到一定的大小就會IO寫到Hfile中,不同的mem-store塊對應(yīng)寫到不同的Hfile,Hfile達到一定的大小就會合并在一起形成新的Block。
讀數(shù)據(jù)也有對應(yīng)的內(nèi)存塊blcok-cache,每一個block都會有對應(yīng)一到多個blcok-cache,每一個blcok-cache也是按照id組織好的。再次讀取的時候會獲取blcok-cache數(shù)據(jù),同時也會獲取mem-store數(shù)據(jù)綜合覆蓋(相同id數(shù)據(jù)條目,因為在內(nèi)存中存儲也是按照順序的,所以在檢索和獲取的時候很高效),獲取最新的數(shù)據(jù)。
下面說一下數(shù)據(jù)表文件存儲的數(shù)據(jù)細節(jié),首先每一個表文件都有表描述文件,里面有字段的順序,字段的所占的字節(jié)數(shù)(字段長度,該表描述文件一般是表名.tb)。其次就是表數(shù)據(jù)文件(一般就是表名.data),每一條數(shù)據(jù)就是按照字段的順序排列存儲,每一條數(shù)據(jù)結(jié)束有結(jié)束符號。數(shù)據(jù)庫(mysql存儲引擎innodb/mySAM)都是按照數(shù)據(jù)頁來存儲數(shù)據(jù)的,也就是每1000條(默認頁數(shù)據(jù)數(shù))放在一個文件里面,這就是一頁數(shù)據(jù)。頁數(shù)據(jù)有對應(yīng)得目錄描述,就是每一頁起始id信息,頁信息在目錄文件中按照順序存儲得,內(nèi)存加載目錄信息,按照每一頁得描述字段長度在內(nèi)存形成一個雙向鏈表結(jié)構(gòu)。(下圖是內(nèi)存加載目錄結(jié)構(gòu)文件,形成得雙向鏈表)
?所有的數(shù)據(jù)依據(jù)建立的索引的字段建立B+樹結(jié)構(gòu)(主鍵默認會創(chuàng)建索引),然后我們知道這個索引結(jié)構(gòu)是B+樹,關(guān)鍵這個樹結(jié)構(gòu)是怎么存儲到存盤文件中的,以xx.idx來命名。這個索引結(jié)構(gòu)存儲到磁盤文件之后,我們還能很多讀取這個文件在內(nèi)存中很快映射解析出這個樹結(jié)構(gòu)。首先我們看下二叉樹磁盤存儲的案例:
完全二叉樹從根結(jié)點到倒數(shù)第二層滿足完美二叉樹,最后一層可以不完全填充,其葉子結(jié)點都靠左對齊。
30
/ \
20 40
/ \ / \
15 25 35 45
/ \
5 10
換句話說,對于完全二叉樹,將層次順序遍歷的序列存儲到文件中。當我們從文件讀取時,可以推斷出第一個元素是根節(jié)點,然后接下來2個元素是級別1的二個節(jié)點,接下來讀出的4個元素是級別2的節(jié)點,依此類推。因此可以非常容易地構(gòu)造這棵完全二叉樹。
30 20 40 15 25 35 45 5 10
但是對于給定的樹,并不是完全二叉樹,即中間節(jié)點可能有缺失。比如,下面的二叉樹中節(jié)點40的左子節(jié)點有缺失。在這種情況下,當層次遍歷并序列化至文件時,需要人為添加一個值(比如-1)來表達當前節(jié)點的缺失。前提是,我們樹的所有節(jié)點的值都是正數(shù)。
30
/ \
20 40
/ \ \
15 25 45
\
10
基于上述想法,我們將-1添加到缺失的節(jié)點中,從而將一個普通的二叉樹轉(zhuǎn)換成完全二叉樹:
30
/ \
20 40
/ \ / \
15 25 -1 45
/ \
-1 10
對應(yīng)地,上面轉(zhuǎn)換后的完全二叉樹持久化到文件的內(nèi)容如下:
30 20 40 15 25 -1 45 -1 10
那么B+樹也按照層級來順序存儲到文件中,解析的時候按照層級標識符來逐層構(gòu)建B+樹。上述就算完全講述完了數(shù)據(jù)庫表數(shù)據(jù)文件存儲的方案,以及如何快速查詢的方案。但是具體到mysql上還存在一些差異,可能對于某一些數(shù)據(jù)庫每一頁也存儲了對應(yīng)的B+樹索引結(jié)構(gòu)。當然對于全面的B+索引結(jié)構(gòu)文件需要盡可能的小,需要一次性加載到內(nèi)存中,然后遍歷樹結(jié)構(gòu),定位到葉子鏈表中不同的行數(shù)據(jù)(條件區(qū)間在雙向鏈表中是連續(xù)的一段),然后再去目錄查到對應(yīng)的頁,把數(shù)據(jù)查詢出來。
對于分布式文件存儲,文件被分割成很多塊,每一個塊都對應(yīng)一個子文件。這些子文件會被記錄到塊目錄中,然后查詢的時候會通過目錄找到對應(yīng)的文件信息。
我們知道內(nèi)存中數(shù)據(jù)存儲都是有條目數(shù)據(jù)記錄數(shù)據(jù)存儲的起始位置;在內(nèi)存中存儲也是有頁(頁管理)進行管理的,有頁表記錄頁的位置和順序。對于磁盤存儲也是有最小的單元--扇區(qū),一個扇區(qū)最小的存儲大小是4KB,文件在磁盤存儲的時候也是有記錄的,也有所在目錄映射表,創(chuàng)建一個目錄的時候,會分配存儲空間和范圍,創(chuàng)建一個文件會記錄目錄信息以及存儲大小(存儲所涉及到扇區(qū)范圍)。
ceph存儲原理
Ceph是?種為優(yōu)秀的性能、可靠性和可擴展性?設(shè)計的統(tǒng)?的、分布式的存儲系統(tǒng)??赏瑫r提供三種接?:
Object:也稱為基于對象的存儲,其中的文件被拆分成多個部分并散布在多個存儲服務(wù)器,在對象存儲中,數(shù)據(jù)會被分解為稱為“對象”的離散單元,并保存在單個存儲庫中(存儲到數(shù)據(jù)文件的某一行,非關(guān)系型數(shù)據(jù)庫表文件數(shù)據(jù)的存儲機制),而不是作為文件夾中的文件或服務(wù)器上的塊來保存,對象存儲需要一個簡單的HTTP 應(yīng)用編程接口(API),以供大多數(shù)客戶端(各種語言)使用。有原?的API,?且也兼容Swift和S3的API。
Block:需要格式化,將文件直接保存到磁盤上。?持精簡配置、快照、克隆。
File:提供數(shù)據(jù)存儲的接口,是由操作系統(tǒng)針對塊存儲的應(yīng)用,即由操作系統(tǒng)提供存儲接口,應(yīng)用程序通過調(diào)用操作系統(tǒng)將文件保存到塊存儲進行持久化。Posix接?,?持快照。
(1)對象存儲:也就是通常意義的鍵值存儲,其接口就是簡單的GET、PUT、DEL 和其他擴展,代表主要有 Swift 、S3 以及 Gluster 等。
(2)塊存儲:這種接口通常以 QEMU Driver 或者 Kernel Module 的方式存在,這種接口需要實現(xiàn) Linux 的 Block Device 的接口或者 QEMU 提供的 Block Driver 接口,如 Sheepdog,AWS 的 EBS,青云的云硬盤和阿里云的盤古系統(tǒng),還有 Ceph 的 RBD(RBD是Ceph面向塊存儲的接口)。在常見的存儲中 DAS、SAN 提供的也是塊存儲。
(3)文件系統(tǒng)存儲:通常意義是支持 POSIX 接口,它跟傳統(tǒng)的文件系統(tǒng)如 Ext4 是一個類型的,但區(qū)別在于分布式存儲提供了并行化的能力,如 Ceph 的 CephFS (CephFS是Ceph面向文件存儲的接口),但是有時候又會把 GlusterFS ,HDFS 這種非POSIX接口的類文件存儲接口歸入此類。當然 NFS、NAS也是屬于文件系統(tǒng)存儲。
ceph存儲具備高性能、高可用性、高擴展特性、特性豐富:
高性能:
(1)摒棄了傳統(tǒng)的集中式存儲元數(shù)據(jù)尋址的?案,采?CRUSH算法,數(shù)據(jù)分布均衡,并?度?。
(2)考慮了容災(zāi)域的隔離,能夠?qū)崿F(xiàn)各類負載的副本放置規(guī)則,例如跨主機、跨機房、機架感知等。
(3)能夠?持上千個存儲節(jié)點的規(guī)模,?持TB到PB級的數(shù)據(jù)。高可用性:
(1)副本數(shù)可以靈活控制 (2)?持故障域分隔,數(shù)據(jù)強?致性
(3)多種故障場景?動進?修復?愈 (4)沒有單點故障,?動管理?可擴展性:
(1)去中?化? (2)擴展靈活? (3)隨著節(jié)點增加?線性增?
特性豐富:
(1)?持三種存儲接?:塊存儲、?件存儲、對象存儲。
(2)?持?定義接?,?持多種語?驅(qū)動。
ceph的基本架構(gòu):
一個ceph集群包含:(1)若干的Ceph OSD(對象存儲守護程序);(2)至少需要一個Ceph Monitors 監(jiān)視器(1,3,5,7...);(3)兩個或以上的Ceph 管理器managers (4)運行Ceph 文件系統(tǒng)客戶端時,還需要高可用的Ceph Metadata Server(文件系統(tǒng)元數(shù)據(jù)服務(wù)器)。
RADOS cluster: 由多臺host 存儲服務(wù)器組成的ceph 集群【Reliable Autonomic Distributed Object Store 即可靠的、自動化的、分布式的對象存儲系統(tǒng)】;RADOS是ceph存儲集群的基礎(chǔ)。在ceph中,所有數(shù)據(jù)都以對象的形式存儲,并且無論什么數(shù)據(jù)類型,RADOS對象存儲都將負責保存這些對象。RADOS層可以確保數(shù)據(jù)始終保持一致。
OSD(Object Storage Daemon):每臺存儲服務(wù)器的磁盤組成的存儲空間
Mon(Monitor):ceph 的監(jiān)視器,維護OSD 和PG 的集群狀態(tài),一個ceph 集群至少要有一個mon,可以是一三五七等等這樣的奇數(shù)個。
Mgr(Manager):負責跟蹤運行時指標和Ceph 集群的當前狀態(tài),包括存儲利用率,當前性
能指標和系統(tǒng)負載等。
ceph 是一個對象(object)式存儲系統(tǒng),它把每一個待管理的數(shù)據(jù)流(文件等數(shù)據(jù))切分為一到多個固定大小(默認4 兆)的對象數(shù)據(jù),并以其為原子單元(原子是構(gòu)成元素的最小單元)完成數(shù)據(jù)的讀寫。 對象數(shù)據(jù)的底層存儲服務(wù)是由多個存儲主機(host)組成的存儲集群,該集群也被稱之為RADOS(reliable automatic distributed object store)存儲集群,即可靠的、自動化的、分布式的對象存儲系統(tǒng)。 librados 是RADOS 存儲集群的API,支持C/C++/JAVA/python/ruby/php/go等編程語言客戶端。
librados:librados庫,為應(yīng)用程度提供訪問接口。同時也為塊存儲、對象存儲、文件系統(tǒng)提供原生的接口。
RADOSGW:網(wǎng)關(guān)接口,提供對象存儲服務(wù)。它使用librgw和librados來實現(xiàn)允許應(yīng)用程序與Ceph對象存儲建立連接。并且提供S3 和 Swift 兼容的RESTful API接口。
RBD:塊設(shè)備,它能夠自動精簡配置并可調(diào)整大小,而且將數(shù)據(jù)分散存儲在多個OSD上。
CephFS:Ceph文件系統(tǒng),與POSIX兼容的文件系統(tǒng),基于librados封裝原生接口。
集群結(jié)構(gòu)功能描述
Monitor(ceph-mon) ceph 監(jiān)視器: 在一個主機上運行的一個守護進程,用于維護集群狀態(tài)映射(maintains maps of the cluster state),比如ceph 集群中有多少存儲池、每個存儲池有多少PG 以及存儲池和PG的映射關(guān)系等, monitor map, manager map, the OSD map, the MDS map, and the CRUSH map,這些映射是Ceph 守護程序相互協(xié)調(diào)所需的關(guān)鍵群集狀態(tài),此外監(jiān)視器還負責管理守護程序和客戶端之間的身份驗證(認證使用cephX 協(xié)議)。通常至少需要三個監(jiān)視器才能實現(xiàn)冗余和高可用性。監(jiān)視器維護集群狀態(tài)的多種映射,同時提供認證和日志記錄服務(wù),包括有關(guān)monitor 節(jié)點端到端的信息,其中包括 Ceph 集群ID,監(jiān)控主機名和IP以及端口。并且存儲當前版本信息以及最新更改信息,通過 "ceph mon dump"查看 monitor map。
Managers(ceph-mgr)的功能:在一個主機上運行的一個守護進程,Ceph Manager 守護程序(ceph-mgr)負責跟蹤運行時指標和Ceph 集群的當前狀態(tài),包括存儲利用率,當前性能指標和系統(tǒng)負載。Ceph Manager 守護程序還托管基于python 的模塊來管理和公開Ceph 集群信息,包括基于Web的Ceph 儀表板和REST API。高可用性通常至少需要兩個管理器。
Ceph OSDs(對象存儲守護程序ceph-osd):即對象存儲守護程序,但是它并非針對對象存儲。提供存儲數(shù)據(jù),操作系統(tǒng)上的一個磁盤就是一個OSD 守護程序。是物理磁盤驅(qū)動器,將數(shù)據(jù)以對象的形式存儲到集群中的每個節(jié)點的物理磁盤上。OSD負責存儲數(shù)據(jù)、處理數(shù)據(jù)復制、恢復、回(Backfilling)、再平衡。完成存儲數(shù)據(jù)的工作絕大多數(shù)是由 OSD daemon 進程實現(xiàn)。在構(gòu)建 Ceph OSD的時候,建議采用SSD 磁盤以及xfs文件系統(tǒng)來格式化分區(qū)。此外OSD還對其它OSD進行心跳檢測,檢測結(jié)果匯報給Monitor。通常至少需要3 個Ceph OSD 才能實現(xiàn)冗余和高可用性。
MDS(ceph 元數(shù)據(jù)服務(wù)器ceph-mds):Ceph 元數(shù)據(jù),主要保存的是Ceph文件系統(tǒng)(NFS/CIFS)的元數(shù)據(jù)。注意:ceph的塊存儲和ceph對象存儲都不需要MDS。
Ceph 的管理節(jié)點:1.ceph 的常用管理接口是一組命令行工具程序,例如rados、ceph、rbd 等命令,ceph 管理員可以從某個特定的ceph-mon 節(jié)點執(zhí)行管理操作
2.推薦使用部署專用的管理節(jié)點對ceph 進行配置管理、升級與后期維護,方便后期權(quán)限管理,管理節(jié)點的權(quán)限只對管理人員開放,可以避免一些不必要的誤操作的發(fā)生。
ceph節(jié)點邏輯結(jié)構(gòu)
pool:存儲池、分區(qū),存儲池的大小取決于底層的存儲空間。
PG(placement group):一個pool 內(nèi)部可以有多個PG 存在,pool 和PG 都是抽象的邏輯概念,一個pool 中有多少個PG?可以通過公式計算。
OSD(Object Storage Daemon,對象存儲設(shè)備):每一塊磁盤都是一個osd,一個主機由一個或多個osd 組成。
ceph 集群部署好之后,要先創(chuàng)建存儲池才能向ceph 寫入數(shù)據(jù),文件在向ceph 保存之前要先進行一致性hash 計算,計算后會把文件保存在某個對應(yīng)的PG 的,此文件一定屬于某個pool 的一個PG,在通過PG 保存在OSD 上。數(shù)據(jù)對象在寫到主OSD 之后再同步對從OSD 以實現(xiàn)數(shù)據(jù)的高可用。
?ceph數(shù)據(jù)寫入流程
第一步: 計算文件到對象的映射:
File放到ceph集群后,先把文件進行分割,分割為等大小的小塊,小塊叫object(默認為4M);計算文件到對象的映射,假如file 為客戶端要讀寫的文件,得到oid(object id) = ino + ono
ino:inode number (INO),F(xiàn)ile 的元數(shù)據(jù)序列號,F(xiàn)ile 的唯一id。ono:object number (ONO),F(xiàn)ile 切分產(chǎn)生的某個object 的序號,默認以4M 切分一個塊大小。
比如:一個文件FileID為A,它被切成了兩個對象,一個對象編號0,另一個編號1,那么這兩個文件的oid則為A0與A1。
1)由Ceph集群指定的靜態(tài)Hsah函數(shù)計算Object的oid,獲取到其Hash值。
2)將該Hash值與mask進行與操作,從而獲得PG ID。
第二步:通過hash 算法計算出文件對應(yīng)的pool 中的PG:
小塊跟據(jù)一定算法跟規(guī)律,算法是哈希算法,放置到PG組里。
通過一致性HASH 計算Object 到PG, Object -> PG 映射hash(oid) & mask-> pgid?
第三步: 通過CRUSH 把對象映射到PG 中的OSD:
再把PG放到OSD里面。
通過CRUSH 算法計算PG 到OSD,PG -> OSD 映射:[CRUSH(pgid)->(osd1,osd2,osd3)]?
第四步:PG 中的主OSD 將對象寫入到硬盤。
第五步: 主OSD 將數(shù)據(jù)同步給備份OSD,并等待備份OSD 返回確認。
第六步: 備份OSD返回確認后,主OSD 將寫入完成返回給客戶端。
Ceph中數(shù)據(jù)寫入,會有三次映射
?(1)File -> object映射
?(2)Object -> PG映射,hash(oid) & mask -> pgid
?(3)PG -> OSD映射,CRUSH算法
CRUSH算法介紹
CRUSH,Controlled Replication Under Scalable Hashing,它表示數(shù)據(jù)存儲的分布式選擇算法, ceph 的高性能/高可用就是采用這種算法實現(xiàn)。CRUSH 算法取代了在元數(shù)據(jù)表中為每個客戶端請求進行查找,它通過計算系統(tǒng)中數(shù)據(jù)應(yīng)該被寫入或讀出的位置。CRUSH能夠感知基礎(chǔ)架構(gòu),能夠理解基礎(chǔ)設(shè)施各個部件之間的關(guān)系。并CRUSH保存數(shù)據(jù)的多個副本,這樣即使一個故障域的幾個組件都出現(xiàn)故障,數(shù)據(jù)依然可用。CRUSH 算是使得 ceph 實現(xiàn)了自我管理和自我修復。
Ceph 使用CRUSH 算法來準確計算數(shù)據(jù)應(yīng)該被保存到哪里,以及應(yīng)該從哪里讀取,和保存元數(shù)據(jù)不同的是,CRUSH 按需計算出元數(shù)據(jù),因此它就消除了對中心式的服務(wù)器/網(wǎng)關(guān)的需求,它使得Ceph 客戶端能夠計算出元數(shù)據(jù),該過程也稱為CRUSH 查找,然后和OSD 直接通信。
(1)如果是把對象直接映射到OSD 之上會導致對象與OSD 的對應(yīng)關(guān)系過于緊密和耦合,當OSD 由于故障發(fā)生變更時將會對整個ceph 集群產(chǎn)生影響。
(2).于是ceph 將一個對象映射到RADOS 集群的時候分為兩步走:(a)首先使用一致性hash 算法將對象名稱映射到PG? (b)然后將PG ID 基于CRUSH 算法映射到OSD 即可查到對象
(3)以上兩個過程都是以”實時計算”的方式完成,而沒有使用傳統(tǒng)的查詢數(shù)據(jù)與塊設(shè)備的對應(yīng)表的方式,這樣有效避免了組件的”中心化”問題,也解決了查詢性能和冗余問題。使得ceph集群擴展不再受查詢的性能限制。
(4)這個實時計算操作使用的就是CRUSH 算法(Controllers replication under scalable hashing) 可控的、可復制的、可伸縮的一致性hash算法。
CRUSH 是一種分布式算法,類似于一致性hash 算法,用于為RADOS 存儲集群控制數(shù)據(jù)的分配。
對象存儲與文件存儲:文章來源:http://www.zghlxwxcb.cn/news/detail-469816.html
文件存儲和對象存儲底層都是塊存儲,但是文件存儲在管理文件上是文件樹,對象存儲是扁平化的小文件存儲,管理上不能單單靠文件樹結(jié)構(gòu)?文章來源地址http://www.zghlxwxcb.cn/news/detail-469816.html
到了這里,關(guān)于分布式數(shù)據(jù)(文件)存儲的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!