淺談MySQL、Hadoop、BigTable、Clickhouse數據讀寫機制

個人理解,歡迎指正

資料庫 引擎 寫數據 讀數據 補充
MySql

InnoDB:支援事務,高速讀寫性能一般

Myisam:不支援事務,高速讀寫性能好

以InnoDB更新一條記錄為例

1、B+Tree搜索找到這行記錄,如果數據頁在記憶體直接返回給【執行器】,否則從磁碟讀入記憶體再返回

2、【執行器】更新數據,再調用【引擎】介面寫入這行新數據

3、【引擎】將舊數據備份到undo log,然後更新記憶體中數據頁的這行數據,同時將操作記錄寫到redo log里,此時redo log 處於prepare狀態

4、【執行器】記錄binlog日誌

5、【執行器】調用引擎介面,【引擎】將redo log改成commit狀態

6、此時更新就算完成了,【InnoBD引擎】會在適當的時候將操作記錄批量刷到磁碟,並清理redo log

其基本流程是:先去快取頁查找,若沒有則通過B+Tree檢索到葉子節點對應的數據頁,然後加到快取頁並返回

redo log(重做日誌)和 binlog(歸檔日誌)

1、redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 層實現的,所有引擎都可以使用。

2、redo log 是物理日誌,記錄的是「在某個數據頁上做了什麼修改」;binlog 是邏輯日誌,記錄的是這個語句的原始邏輯,比如「給 ID=2 這一行的 c 欄位加 1 」。

3、redo log 是循環寫的,空間固定會用完;binlog 是可以追加寫入的。「追加寫」是指 binlog 文件寫到一定大小後會切換到下一個,並不會覆蓋以前的日誌。 

Hadoop

存儲:HDFS

計算:MapReduce

HDFS寫數據

1、Client向NameNode請求上傳Block(文件塊)

2、NameNode向Client返回DataNode地址

3、Client以Package為單位向DataNode依次寫入,直到寫完整個Block

4、每傳輸完一個Package,DataNode會向Clent返回一個ack,若失敗會重試

HDFS讀數據

1、Client向NameNode請求下載文件

2、NameNode按負載均衡和節點距離返回DataNode給Client

3、Client讀取DataNode,以Package為單位拉取,先存入快取,最後生成文件,中間有checksum校驗

MapReduce運算

1、InputFormat會從DataNode拉取一個個Bolck塊

2、然後啟動若干個MapTask對Block數據做運算

3、運算後的結果經過Shuffer落到磁碟

4、然後啟動若干個ReduceTask從磁碟讀取數據進行聚合

5、最後通過OutputFormat把結果寫到HDFS或其他存儲介質里

BigTable SSTable

其實SSTable文件也是存在GFS上,但GFS不支援隨機寫【增刪改】,那麼BigTable是如何實現的呢?

1、其實BigTable在記憶體里維護了一個記憶體表(MemTable),每次數據【增刪改】都會增加一條記錄,並附帶版本。當容量到達閥值的時候會把MemTable轉成SSTable【順序寫】到GFS上,後續數據繼續寫新的MemTable

2、另外,會啟動一個後台進程(Major Compaction機制),不斷的合併SSTable,只保留【增刪改】的最終數據,老版本的數據被刪除

當查詢數據時,會去讀取索引數據,找到數據塊返回給Tablet Server,再從這個數據塊里提取出對應的 KV 數據返回給客戶端

1、記憶體里快取 BloomFilter,使得對於不存在於 SSTable 中的行鍵,可以直接過濾掉,無需訪問 SSTable 文件才能知道它並不存在

2、通過 Scan Cache 和 Block Cache 這兩層快取,利用局部性原理,使得查詢結果可以在快取中找到,而無需訪問 GFS 上的硬碟

3、經過前2步還沒找到,會通過SSTable索引來查找,底層是AVL紅黑樹或跳錶,隨機讀寫都是O(log n)

1、SSTable 的文件格式是由兩部分組成:

數據塊(data block),就是實際要存儲的行鍵、列、值以及時間戳,這些數據會按照行鍵排序分成一個個固定大小的塊(block)來進行存儲。

元數據塊(meta block),是一系列的元數據和索引資訊,這其中包括用來快速過濾當前 SSTable 中不存在的行鍵的布隆過濾器,以及整個數據塊的一些統計指標。

另外還有針對數據塊和元數據塊的索引(index),這些索引內容,則分別是元數據索引塊(metaindex block)和數據索引塊(index block)

2、因為 SSTable 裡面的數據塊是順序存儲的,所以Major Compaction做的是一個有序鏈表的多路歸併,這個過程中在磁碟上是順序讀寫

Clickhouse 表引擎主要是MergeTree系列,還有Log系列等其他引擎

1、一個Table是由多個Partition組成,一個Partition是由多個Part組成,Part里按column【列式存儲】

2、舊數據在一個Part,新數據會寫另一個Part,然後通過MergeTree引擎將多個Part非同步合併(按排序鍵歸併排序)

因為是按排序鍵已經排好序了,所以索引結構不需要像其他引擎設計的那麼複雜;

底層是稀疏索引(默認8192為一個步長),通過【稀疏索引+標記的偏移量】就能很快找到Block的位置

 

1、Clickhouse通過【批處理+預排序】將數據提前排好序

2、Clickhouse能處理的最小單位是block,block就是一群行的集合,默認最大8192行組成一個block

 

相關資料

HDFS設計原理

日誌系統:一條SQL更新語句是如何執行的?

SSTable存儲引擎

Clickhouse的優化手段之block+lsm

Clickhouse索引結構

Clickhouse存儲引擎

Clickhouse官方文檔:MergeTree系列