最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

RocketMQ設計之異步刷盤

 更新時間:2022年03月21日 10:29:20   作者:周杰倫本人  
本文介紹RocketMQ設計之異步刷盤,RocketMQ消息存儲到磁盤上,這樣既保證斷電后恢復,也讓存儲消息量超出內(nèi)存限制,RocketMQ為了提高性能,會盡可能保證磁盤順序?qū)?消息通過Producer寫入RocketMQ的時候,有兩種方式,上篇介紹了同步刷盤,本文介紹異步刷盤,需要的朋友可以參考下

上一篇RocketMQ設計之同步刷盤

異步刷盤方式:在返回寫成功狀態(tài)時,消息可能只是被寫入了內(nèi)存的PAGECACHE,寫操作的返回快,吞吐量大;當內(nèi)存里的消息量積累到一定程度時,統(tǒng)一觸發(fā)寫磁盤操作,快速寫入

RocketMQ默認采用異步刷盤,異步刷盤兩種策略:開啟緩沖池,不開啟緩沖池

CommitLog的handleDiskFlush方法:

public void handleDiskFlush(AppendMessageResult result, PutMessageResult putMessageResult, MessageExt messageExt) {
? ? // Synchronization flush
? ? if (FlushDiskType.SYNC_FLUSH == this.defaultMessageStore.getMessageStoreConfig().getFlushDiskType()) {
? ? ? ? final GroupCommitService service = (GroupCommitService) this.flushCommitLogService;
? ? ? ? if (messageExt.isWaitStoreMsgOK()) {
? ? ? ? ? ? GroupCommitRequest request = new GroupCommitRequest(result.getWroteOffset() + result.getWroteBytes());
? ? ? ? ? ? service.putRequest(request);
? ? ? ? ? ? boolean flushOK = request.waitForFlush(this.defaultMessageStore.getMessageStoreConfig().getSyncFlushTimeout());
? ? ? ? ? ? if (!flushOK) {
? ? ? ? ? ? ? ? log.error("do groupcommit, wait for flush failed, topic: " + messageExt.getTopic() + " tags: " + messageExt.getTags()
? ? ? ? ? ? ? ? ? ? + " client address: " + messageExt.getBornHostString());
? ? ? ? ? ? ? ? putMessageResult.setPutMessageStatus(PutMessageStatus.FLUSH_DISK_TIMEOUT);
? ? ? ? ? ? }
? ? ? ? } else {
? ? ? ? ? ? service.wakeup();
? ? ? ? }
? ? }
? ? // Asynchronous flush
? ? else {
? ? ? ? if (!this.defaultMessageStore.getMessageStoreConfig().isTransientStorePoolEnable()) {
? ? ? ? ? ? flushCommitLogService.wakeup();
? ? ? ? } else {
? ? ? ? ? ? commitLogService.wakeup();
? ? ? ? }
? ? }
}

不開啟緩沖池:默認不開啟,刷盤線程FlushRealTimeService會每間隔500毫秒嘗試去刷盤。

class FlushRealTimeService extends FlushCommitLogService {
? ? private long lastFlushTimestamp = 0;
? ? private long printTimes = 0;

? ? public void run() {
? ? ? ? CommitLog.log.info(this.getServiceName() + " service started");

? ? ? ? while (!this.isStopped()) {
? ? ? ? ? ? boolean flushCommitLogTimed = CommitLog.this.defaultMessageStore.getMessageStoreConfig().isFlushCommitLogTimed();

? ? ? ? ? ? //每次Flush間隔500毫秒
? ? ? ? ? ? int interval = CommitLog.this.defaultMessageStore.getMessageStoreConfig().getFlushIntervalCommitLog();
? ? ? ? ? ? //每次Flush最少4頁內(nèi)存數(shù)據(jù)(16KB)
? ? ? ? ? ? int flushPhysicQueueLeastPages = CommitLog.this.defaultMessageStore.getMessageStoreConfig().getFlushCommitLogLeastPages();

? ? ? ? ? ??? ?//距離上次刷盤時間閾值為10秒
? ? ? ? ? ? int flushPhysicQueueThoroughInterval =
? ? ? ? ? ? ? ? CommitLog.this.defaultMessageStore.getMessageStoreConfig().getFlushCommitLogThoroughInterval();

? ? ? ? ? ? boolean printFlushProgress = false;

? ? ? ? ? ? // Print flush progress
? ? ? ? ? ? long currentTimeMillis = System.currentTimeMillis();
? ? ? ? ? ? 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();
? ? ? ? ? ? ? ? CommitLog.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 exit
? ? ? ? boolean 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");
? ? }

? ? @Override
? ? public String getServiceName() {
? ? ? ? return FlushRealTimeService.class.getSimpleName();
? ? }

? ? private void printFlushProgress() {
? ? ? ? // CommitLog.log.info("how much disk fall behind memory, "
? ? ? ? // + CommitLog.this.mappedFileQueue.howMuchFallBehind());
? ? }

? ? @Override
? ? public long getJointime() {
? ? ? ? return 1000 * 60 * 5;
? ? }
}
  • 判斷是否超過10秒沒刷盤了,如果超過強制刷盤
  • 等待Flush間隔500ms
  • 通過MappedFile刷盤
  • 設置StoreCheckpoint刷盤時間點
  • 超過500ms的刷盤記錄日志
  • Broker正常停止前,把內(nèi)存page中的數(shù)據(jù)刷盤

開啟緩沖池:

class CommitRealTimeService extends FlushCommitLogService {

? ? private long lastCommitTimestamp = 0;

? ? @Override
? ? public String getServiceName() {
? ? ? ? return CommitRealTimeService.class.getSimpleName();
? ? }

? ? @Override
? ? public void run() {
? ? ? ? CommitLog.log.info(this.getServiceName() + " service started");
? ? ? ? while (!this.isStopped()) {
? ? ? ? ? ? //每次提交間隔200毫秒
? ? ? ? ? ? int interval = CommitLog.this.defaultMessageStore.getMessageStoreConfig().getCommitIntervalCommitLog();

? ? ? ? ? ? //每次提交最少4頁內(nèi)存數(shù)據(jù)(16KB)
? ? ? ? ? ? int commitDataLeastPages = CommitLog.this.defaultMessageStore.getMessageStoreConfig().getCommitCommitLogLeastPages();

? ? ? ? ? ? //距離上次提交時間閾值為200毫秒
? ? ? ? ? ? int commitDataThoroughInterval =
? ? ? ? ? ? ? ? CommitLog.this.defaultMessageStore.getMessageStoreConfig().getCommitCommitLogThoroughInterval();

? ? ? ? ? ? long begin = System.currentTimeMillis();
? ? ? ? ? ? if (begin >= (this.lastCommitTimestamp + commitDataThoroughInterval)) {
? ? ? ? ? ? ? ? this.lastCommitTimestamp = begin;
? ? ? ? ? ? ? ? commitDataLeastPages = 0;
? ? ? ? ? ? }

? ? ? ? ? ? try {
? ? ? ? ? ? ? ? boolean result = CommitLog.this.mappedFileQueue.commit(commitDataLeastPages);
? ? ? ? ? ? ? ? long end = System.currentTimeMillis();
? ? ? ? ? ? ? ? if (!result) {
? ? ? ? ? ? ? ? ? ? this.lastCommitTimestamp = end; // result = false means some data committed.
? ? ? ? ? ? ? ? ? ? //now wake up flush thread.
? ? ? ? ? ? ? ? ? ? flushCommitLogService.wakeup();
? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? if (end - begin > 500) {
? ? ? ? ? ? ? ? ? ? log.info("Commit data to file costs {} ms", end - begin);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? this.waitForRunning(interval);
? ? ? ? ? ? } catch (Throwable e) {
? ? ? ? ? ? ? ? CommitLog.log.error(this.getServiceName() + " service has exception. ", e);
? ? ? ? ? ? }
? ? ? ? }

? ? ? ? boolean result = false;
? ? ? ? for (int i = 0; i < RETRY_TIMES_OVER && !result; i++) {
? ? ? ? ? ? result = CommitLog.this.mappedFileQueue.commit(0);
? ? ? ? ? ? CommitLog.log.info(this.getServiceName() + " service shutdown, retry " + (i + 1) + " times " + (result ? "OK" : "Not OK"));
? ? ? ? }
? ? ? ? CommitLog.log.info(this.getServiceName() + " service end");
? ? }
}

RocketMQ申請一塊和CommitLog文件相同大小的堆外內(nèi)存來做緩沖池,數(shù)據(jù)會先寫入緩沖池,提交線程CommitRealTimeService也每間隔500毫秒嘗試提交到文件通道等待刷盤,刷盤最終由FlushRealTimeService來完成,和不開啟緩沖池的處理一致。使用緩沖池的目的是多條數(shù)據(jù)合并寫入,從而提高io性能。

  • 判斷是否超過200毫秒沒提交,需要強制提交
  • 提交到MappedFile,此時還未刷盤
  • 然后喚醒刷盤線程
  • 在Broker正常停止前,提交內(nèi)存page中的數(shù)據(jù)

到此這篇關于RocketMQ設計之異步刷盤的文章就介紹到這了,更多相關RocketMQ異步刷盤內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Spring定時任務只執(zhí)行一次的原因分析與解決方案

    Spring定時任務只執(zhí)行一次的原因分析與解決方案

    在使用Spring的@Scheduled定時任務時,你是否遇到過任務只執(zhí)行一次,后續(xù)不再觸發(fā)的情況?這種情況可能由多種原因?qū)е?如未啟用調(diào)度、線程池問題、異常中斷等,本文將深入分析Spring定時任務只執(zhí)行一次的原因,并提供完整的解決方案,需要的朋友可以參考下
    2025-03-03
  • Java 類型信息詳解和反射機制介紹

    Java 類型信息詳解和反射機制介紹

    這篇文章主要介紹了Java 類型信息詳解和反射機制介紹,需要的朋友可以參考下
    2020-11-11
  • 關于SpringBoot打包測試、生產(chǎn)環(huán)境方式

    關于SpringBoot打包測試、生產(chǎn)環(huán)境方式

    這篇文章主要介紹了關于SpringBoot打包測試、生產(chǎn)環(huán)境方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • 淺試仿?mapstruct實現(xiàn)微服務編排框架詳解

    淺試仿?mapstruct實現(xiàn)微服務編排框架詳解

    這篇文章主要為大家介紹了淺試仿?mapstruct實現(xiàn)微服務編排框架詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • Springboot如何設置靜態(tài)資源緩存一年

    Springboot如何設置靜態(tài)資源緩存一年

    這篇文章主要介紹了Springboot如何設置靜態(tài)資源緩存一年,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-11-11
  • java.lang.IllegalStateException異常解決

    java.lang.IllegalStateException異常解決

    異常是程序在執(zhí)行過程中遇到的錯誤或異常情況,本文就來介紹一下java.lang.IllegalStateException異常解決,感興趣的可以了解一下
    2023-11-11
  • java中List接口的方法詳解

    java中List接口的方法詳解

    這篇文章主要介紹了java中List接口的方法詳解,List接口是繼承Collection接口,所以Collection集合中有的方法,List集合也繼承過來,本文主要介紹一下list下的方法,需要的朋友可以參考下
    2023-10-10
  • 詳解Mybatis Generator的具體使用教程

    詳解Mybatis Generator的具體使用教程

    Mybatis Generator可以幫助我們自動生成很多結構化的代碼,比如每張表對應的Entity、Mapper接口和Xml文件,可以省去很多繁瑣的工作,今天通過本文給大家介紹Mybatis Generator的具體使用教程,感興趣的朋友一起看看吧
    2022-02-02
  • struts2自定義攔截器的示例代碼

    struts2自定義攔截器的示例代碼

    本篇文章主要介紹了struts2自定義攔截器的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08
  • java基礎的詳細了解第四天

    java基礎的詳細了解第四天

    這篇文章對Java編程語言的基礎知識作了一個較為全面的匯總,在這里給大家分享一下。需要的朋友可以參考,希望能給你帶來幫助
    2021-08-08

最新評論

仙桃市| 商都县| 沙河市| 芜湖县| 随州市| 泽州县| 南投县| 清涧县| 开化县| 东乌珠穆沁旗| 汽车| 怀来县| 杂多县| 安吉县| 正宁县| 崇州市| 寻甸| 连云港市| 岳池县| 锡林浩特市| 太原市| 青阳县| 驻马店市| 云南省| 望谟县| 健康| 通化市| 郯城县| 南昌县| 连城县| 龙口市| 上高县| 乌兰浩特市| 建宁县| 潞城市| 三原县| 靖西县| 英德市| 三门县| 台东市| 河南省|