classFlushRealTimeServiceextendsFlushCommitLogService{privatelong lastFlushTimestamp =0;privatelong printTimes =0;//还是看我们的run方法publicvoidrun(){CommitLog.log.info(this.getServiceName()+" service started");while(!this.isStopped()){//是否定时刷盘,默认为false即实时刷盘boolean flushCommitLogTimed =CommitLog.this.defaultMessageStore.getMessageStoreConfig().isFlushCommitLogTimed();// 刷盘时间间隔,默认500msint interval =CommitLog.this.defaultMessageStore.getMessageStoreConfig().getFlushIntervalCommitLog();//每次刷盘最小刷入页,数默认4页,脏页达不到4页,不进行刷盘int flushPhysicQueueLeastPages =CommitLog.this.defaultMessageStore.getMessageStoreConfig().getFlushCommitLogLeastPages();//两次刷盘之间的最长时间间隔默认10sint flushPhysicQueueThoroughInterval =CommitLog.this.defaultMessageStore.getMessageStoreConfig().getFlushCommitLogThoroughInterval();boolean printFlushProgress =false;// Print flush progresslong currentTimeMillis =System.currentTimeMillis();//超过flushPhysicQueueThoroughInterval这个时间,无论脏页是否够都去刷盘,flushPhysicQueueLeastPages = 0这个之前说过只要0,就是强制刷盘if(currentTimeMillis >=(this.lastFlushTimestamp + flushPhysicQueueThoroughInterval)){this.lastFlushTimestamp = currentTimeMillis;
flushPhysicQueueLeastPages =0;
printFlushProgress =(printTimes++%10)==0;}try{if(flushCommitLogTimed){Thread.sleep(interval);}else{this.waitForRunning(interval);}if(printFlushProgress){this.printFlushProgress();}long begin =System.currentTimeMillis();//刷盘,正常情况下flushPhysicQueueLeastPages = 4,同步刷盘是0CommitLog.this.mappedFileQueue.flush(flushPhysicQueueLeastPages);long storeTimestamp =CommitLog.this.mappedFileQueue.getStoreTimestamp();if(storeTimestamp >0){CommitLog.this.defaultMessageStore.getStoreCheckpoint().setPhysicMsgTimestamp(storeTimestamp);}long past =System.currentTimeMillis()- begin;if(past >500){
log.info("Flush data to disk costs {} ms", past);}}catch(Throwable e){CommitLog.log.warn(this.getServiceName()+" service has exception. ", e);this.printFlushProgress();}}// Normal shutdown, to ensure that all the flush before exitboolean result =false;for(int i =0; i <RETRY_TIMES_OVER&&!result; i++){
result =CommitLog.this.mappedFileQueue.flush(0);CommitLog.log.info(this.getServiceName()+" service shutdown, retry "+(i +1)+" times "+(result ?"OK":"Not OK"));}this.printFlushProgress();CommitLog.log.info(this.getServiceName()+" service end");}@OverridepublicStringgetServiceName(){returnFlushRealTimeService.class.getSimpleName();}privatevoidprintFlushProgress(){// CommitLog.log.info("how much disk fall behind memory, "// + CommitLog.this.mappedFileQueue.howMuchFallBehind());}@OverridepubliclonggetJointime(){return1000*60*5;}}
flush() 刷盘
publicbooleanflush(finalint flushLeastPages){boolean result =true;//返回一个mappedFile就是返回一个commitLog的对象//获得我们刷盘要的MappedFileMappedFile mappedFile =this.findMappedFileByOffset(this.flushedWhere,this.flushedWhere ==0);if(mappedFile !=null){long tmpTimeStamp = mappedFile.getStoreTimestamp();//这里去刷新进去,因为是flushLeastPages是0mappedFile.flush(0),这个方法就代表都是强制刷盘int offset = mappedFile.flush(flushLeastPages);long where = mappedFile.getFileFromOffset()+ offset;
result = where ==this.flushedWhere;this.flushedWhere = where;if(0== flushLeastPages){this.storeTimestamp = tmpTimeStamp;}}return result;}publicintflush(finalint flushLeastPages){if(this.isAbleToFlush(flushLeastPages)){if(this.hold()){int value =getReadPosition();try{//We only append data to fileChannel or mappedByteBuffer, never both.if(writeBuffer !=null||this.fileChannel.position()!=0){this.fileChannel.force(false);}else{//mappedByteBuffer强制刷新this.mappedByteBuffer.force();}}catch(Throwable e){
log.error("Error occurred when force data to disk.", e);}//更新flushwhere为当前位置this.flushedPosition.set(value);this.release();}else{
log.warn("in flush, hold failed, flush offset = "+this.flushedPosition.get());this.flushedPosition.set(getReadPosition());}}//返回当前位置returnthis.getFlushedPosition();}//是否值得谁像你privatebooleanisAbleToFlush(finalint flushLeastPages){//刷新的位置int flush =this.flushedPosition.get();//当前写的位置int write =getReadPosition();if(this.isFull()){returntrue;}//如果不是0,会判断是否大于1页,因为我们是0,所以强制刷新if(flushLeastPages >0){//大于4K了return((write /OS_PAGE_SIZE)-(flush /OS_PAGE_SIZE))>= flushLeastPages;}return write > flush;}