吐血總結(jié)了各個中間件是如何實(shí)現(xiàn)持久化的
文轉(zhuǎn)載自微信公眾號「Java3y」,作者Java3y。轉(zhuǎn)載本文請聯(lián)系Java3y公眾號。
到目前為止,三歪也已經(jīng)接觸到了不少的中間件了,比如說「Elasticsearch」「Redis」「HDFS」「Kafka」「HBase」等等。
可以發(fā)現(xiàn)的是,它們的持久化機(jī)制都差不得太多。今天想來總結(jié)一下,一方面想來回顧一下這些組件,一方面給還沒入門過這些中間件的同學(xué)總結(jié)一下持久化的”套路“,后面再去學(xué)習(xí)的時候就會輕松很多。
這些中間件我的GitHub目錄都是在的:
- https://github.com/ZhongFuCheng3y/3y
- https://gitee.com/zhongfucheng/Java3y
持久化
下面我們就直接來分別回顧一下各個中間件/組件的持久化機(jī)制,最后再總結(jié)就好了(三歪相信大家應(yīng)該也能從回顧中看出些端倪)
為什么要持久化?原因也很簡單:數(shù)據(jù)需要存儲下來,不希望出了問題導(dǎo)致數(shù)據(jù)丟失
Elasticsearch
Elasticsearch是一個全文搜索引擎,對模糊搜索非常擅長。
Elasticsearch在寫數(shù)據(jù)的時候,會先寫到內(nèi)存緩存區(qū),然后寫到translog緩存區(qū),每隔5s將translog緩沖區(qū)的數(shù)據(jù)刷到磁盤中
Kafka
眾所周知,Kafka是一個高吞吐量的消息隊(duì)列,那它是怎么持久化的呢?
Kafka relies heavily on the filesystem for storing and caching messages.
沒錯Kafka用的是文件系統(tǒng)來存儲的。
在Kafka官網(wǎng)上其實(shí)也說了,Kafka的持久化依賴操作系統(tǒng)的pagecache和順序?qū)憗韺?shí)現(xiàn)的。
HDFS
HDFS是分布式文件系統(tǒng),能存儲海量的數(shù)據(jù),那HDFS在寫入數(shù)據(jù)的時候是怎么樣的呢?
HDFS Client客戶端無論讀寫都需要走到NameNode去獲取/增刪改文件的元數(shù)據(jù),而NameNode則是專門維護(hù)這些元數(shù)據(jù)的地方。
所以,在HDFS寫數(shù)據(jù),需要先去NameNode上詢問這些切分好的block往哪幾個DataNode上寫數(shù)據(jù)。
為了提高NameNode的效率,在寫數(shù)據(jù)的時候,NameNode實(shí)際上是操作的是內(nèi)存,然后涉及到增刪改的數(shù)據(jù)順序?qū)懙絜ditlog日志文件上
Redis
Redis是基于內(nèi)存的,如果不想辦法將數(shù)據(jù)保存在硬盤上,一旦Redis重啟(退出/故障),內(nèi)存的數(shù)據(jù)將會全部丟失。
我們肯定不想Redis里頭的數(shù)據(jù)由于某些故障全部丟失(導(dǎo)致所有請求都走M(jìn)ySQL),即便發(fā)生了故障也希望可以將Redis原有的數(shù)據(jù)恢復(fù)過來,所以Redis有RDB和AOF的持久化機(jī)制。
- RDB:基于快照,將某一時刻的所有數(shù)據(jù)保存到一個RDB文件中。
- AOF(append-only-file),當(dāng)Redis服務(wù)器執(zhí)行寫命令的時候,將執(zhí)行的寫命令保存到AOF文件中。
AOF持久化功能的實(shí)現(xiàn)可以分為3個步驟:
- 命令追加:命令寫入aof_buf緩沖區(qū)
- 文件寫入:調(diào)用flushAppendOnlyFile函數(shù),考慮是否要將aof_buf緩沖區(qū)寫入AOF文件中
- 文件同步:考慮是否將內(nèi)存緩沖區(qū)的數(shù)據(jù)真正寫入到硬盤
HBase
HBase是一個能存儲海量數(shù)據(jù)的數(shù)據(jù)庫。
HBase在寫數(shù)據(jù)的時候,會先寫到Mem Store,當(dāng)MemStore超過一定閾值,就會將內(nèi)存中的數(shù)據(jù)刷寫到硬盤上,形成StoreFile,而StoreFile底層是以HFile的格式保存,HFile是HBase中KeyValue數(shù)據(jù)的存儲格式。
我們寫數(shù)據(jù)的時候是先寫到內(nèi)存的,為了防止機(jī)器宕機(jī),內(nèi)存的數(shù)據(jù)沒刷到磁盤中就掛了。我們在寫Mem store的時候還會寫一份HLog
MySQL
MySQL我們用得最多的InnoDB引擎是怎么存儲的呢?它有redo log來支撐持久化的功能。
MySQL引入了redo log,內(nèi)存寫完了,然后會寫一份redo log,這份redo log記載著這次在某個頁上做了什么修改。
總結(jié)看完上面常見的中間件/組件的持久化方式,應(yīng)該就不用我多說了吧?思想幾乎都是一樣的,只是他們記錄“log”的名字不一樣而已。
先寫buffer,然后順序IO寫Log。防止buffer的數(shù)據(jù)還沒刷到磁盤,宕機(jī)導(dǎo)致數(shù)據(jù)丟失。
對于Log文件,中間件也不會放任它們一直膨脹,導(dǎo)致體積很大:
- 在Redis里邊,會對AOF文件進(jìn)行重寫
- 在HDFS里邊,editlog會定時生成fsimage
- 在Elasticsearch里邊,translog會根據(jù)閾值觸發(fā)commit操作
- .....