Flume-ng FileChannel原理解析
對於Flume來說主要有兩個Channel:Memory,File;對於線上環境主要以FileChannel為主,因此這裡主要討論它的實現:
在FileChannel裡主要由一個WAL的log和一個記憶體佇列組成:
FileChannel的Queue主要又以下幾個部分組成:
private final EventQueueBackingStore backingStore;
private final InflightEventWrapper inflightTakes;
private final InflightEventWrapper inflightPuts;
其中backingStore代表了queue在持久化存在,使用了記憶體對映檔案的方式;每次對queue的讀寫操作都記錄在backingStore的overwritemap(update in place)中,當進行checkpoint的時候合併到elementsBuffer並持久化到磁碟;所有未提交的正在讀寫資料都分別儲存在inflight結構中,當checkpoint時一併進行持久化,為回滾時使用;
在inflight中儲存了transactionid->fileid以及transactionid->eventptr的對映,具體儲存在backingStore裡的則是eventptr(fileid,offset);
Checkpoint file的檔案結構如下:
File Header:1029 bytes
Eventptr;
在File header裡前8個位元組儲存了版本號,接下來24個位元組是sequeuece no.(類似rdbms的scn),接下來4個位元組儲存了checkpoint的狀態;
作為WAL的Log主要儲存了(transactionid,sequenceNo,Event),每次讀寫都先在log裡寫入event,對於寫操作會拿到eventptr放入queue中;而commit和rollback操作在log中的記錄形式是(transactionid,sequenceNo,OP={commit,rollback});
這兩個結構主要是體現在FileBackedTransaction中如下:
FileBackedTransaction extends BasicTransactionSemantics
......
LinkedBlockingDeque
LinkedBlockingDeque
long transactionID;
Log log;
FlumeEventQueue queue: EventQueueBackingStoreFile
其中queue = log.getFlumeEventQueue();
首先看put/take path以及commit:
1. doPut(Event event)->
queue.addWithoutCommit(ptr, transactionID)
log.put(transactionID, event)->
synchronized LogFile.Writer.put(ByteBuffer buffer)
putList.offer(ptr)
2. doTake() ->
FlumeEventPointer ptr = queue.removeHead(transactionID);
takeList.offer(ptr),
log.take(transactionID, ptr); ->
synchronized LogFile.Writer.take(ByteBuffer buffer)
Event event = log.get(ptr);
3. doCommit()->
if(puts > 0) {
log.commitPut(transactionID);
synchronized (queue) {
while(!putList.isEmpty()) {
queue.addTail(putList.removeFirst())
queue.completeTransaction(transactionID);
}
}
else if (takes > 0) {
log.commitTake(transactionID);->
logFileWriter.commit(buffer);
logFileWriter.sync();
queue.completeTransaction(transactionID);
queueRemaining.release(takes);
}
}
從上面的程式碼可以看出,對於每一個put/take都會記錄一條oplog到log裡,當commit的時候會對log進行sync到磁碟持久化,同時會把event指標存放到queue上;這裡的log就類似於mysql裡的binlog(binlog_format=statement),而這裡的queue存放的是指向event的指標;
簡例:FileChannel如下,對FileChannel put了2個訊息,a,b;則在log,queue裡的儲存狀態如下,Log裡儲存了(transactionid,sequenceNo,Event),queue則儲存了eventptr;
Queue:ptr->a,ptr->b
WAL log:(1,1,put a),(1,2,put b),(1,3,commit)
當例項crash時,透過log來恢復queue的狀態,類似rdbms一樣,replay是很耗時的操作,因此會定期對queue進行checkpoint:
Log在初始化的時候會啟動一個排程執行緒workerExecutor,由排程執行緒定期(checkpoint interval)排程一個backgroupWorkder來進行非強制性checkpoint;
Log.writeCheckpoint(Boolean force): tryLockExclusive->
synchronized queue.checkpoint->
backingStore.beginCheckpoint();//檢查是否checkpoint正在進行;同時進行標記checkpoint開始,並同步MMAP file;
inflightPuts.serializeAndWrite();//
inflightTakes.serializeAndWrite();//將inflightputs/takes序列化並寫到相應檔案
backingStore.checkpoint();->
setLogWriteOrderID(WriteOrderOracle.next());
writeCheckpointMetaData();
//copy from overwriteMap to elementsBuffer(MMAP)
//標記checkpoint結束,並同步檔案
簡例:接上例,在a,b提交後,這時進行了一次checkpoint(儲存在磁碟上的checkpoint則是2個指標ptr->a,ptr->b),此時scn=4;之後,又完成了一個take transaction ,ptr to a 也同時被刪除;如果這時Flume crash,queue從checkpoint中重建,並且取得checkpoint scn=4,則replay這之後的log進行crash recovery;在恢復後,立刻執行一次checkpoint.
queue:ptr->b
WAL log:(1,1,put a),(1,2,put b),(1,3,commit),(2,5,take a),(2,6,commit)
[@more@]來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/11676357/viewspace-1060911/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Flume-NG原始碼閱讀之FileChannel原始碼
- Flume-ng HDFS sink原理解析
- FileChannel指南
- Java - NIO之Channel(FileChannel)Java
- Java NIO系列教程(七) FileChannelJava
- Java NIO 檔案通道 FileChannel 用法Java
- 8 Java NIO FileChannel-翻譯Java
- JAVA NIO 翻譯系列(七、FileChannel)Java
- 解析HOT原理
- DNS解析原理DNS
- Flutter原理深度解析Flutter
- Promise原理解析Promise
- CAS原理深度解析
- webpack原理解析Web
- kafka原理解析Kafka
- cli原理解析
- gpfdist原理解析
- Sentinel 原理-全解析
- EventBus 原理解析
- BlockCanary原理解析BloC
- MJExtension原理深入解析
- MyBatis原理解析MyBatis
- Flume-NG原始碼閱讀之AvroSink原始碼VRROS
- InheritWidget原理解析
- binder核心原理解析
- Flutter 路由原理解析Flutter路由
- Markdown-it 原理解析
- Mobx autorun 原理解析
- ThreadLocal原理深入解析thread
- NameServer 核心原理解析Server
- HTTPS原理解析HTTP
- CTMediator 原理解析(三)
- KonvaJS 原理解析JS
- Servlet 工作原理解析Servlet
- InnoDB search原理解析
- GeoHash核心原理解析
- DNS解析過程原理DNS
- 框架篇:Linux零拷貝機制和FileChannel框架Linux