Apache BookKeeper中數(shù)據(jù)目錄分析

Apache BookKeeper中數(shù)據(jù)目錄分析

需要落盤(pán)的數(shù)據(jù)
  • Journals
  1. 這個(gè)journals文件里存儲(chǔ)的相當(dāng)于BookKeeper的事務(wù)log或者說(shuō)是寫(xiě)前l(fā)og, 在任何針對(duì)ledger的更新發(fā)生前碑韵,都會(huì)先將這個(gè)更新的描述信息持久化到這個(gè)journal文件中。
  2. Bookeeper提供有單獨(dú)的sync線程根據(jù)當(dāng)前journal文件的大小來(lái)作journal文件的rolling;
  • EntryLogFile
  1. 存儲(chǔ)真正數(shù)據(jù)的文件占卧,寫(xiě)入的時(shí)候Entry數(shù)據(jù)先緩存在內(nèi)存buffer中华蜒,然后批量flush到EntryLogFile中;
  2. 默認(rèn)情況下,所有l(wèi)edger的數(shù)據(jù)都是聚合然后順序?qū)懭氲酵粋€(gè)EntryLog文件中豁遭,避免磁盤(pán)隨機(jī)寫(xiě);
  • Index文件
  1. 所有Ledger的entry數(shù)據(jù)都寫(xiě)入相同的EntryLog文件中蓖谢,為了加速數(shù)據(jù)讀取,會(huì)作 ledgerId + entryId 到文件offset的映射啥辨,這個(gè)映射會(huì)緩存在內(nèi)存中盯腌,稱(chēng)為IndexCache;
  2. IndexCache容量達(dá)到上限時(shí),會(huì)被 Sync線程flush到文件;
  • LastLogMark
  1. 從上面的的講述可知着倾, 寫(xiě)入的EntryLog和Index都是先緩存在內(nèi)存中卡者,再根據(jù)一定的條件周期性的flush到磁盤(pán)客们,這就造成了從內(nèi)存到持久化到磁盤(pán)的時(shí)間間隔,如果在這間隔內(nèi)BookKeeper進(jìn)程崩潰恒傻,在重啟后盈厘,我們需要根據(jù)journal文件內(nèi)容來(lái)恢復(fù)官边,這個(gè)LastLogMark就記錄了從journal中什么位置開(kāi)始恢復(fù);
  2. 它其實(shí)是存在內(nèi)存中外遇,當(dāng)IndexCache被flush到磁盤(pán)后其值會(huì)被更新跳仿,其也會(huì)周期性持久化到磁盤(pán)文件菲语,供BookKeeper進(jìn)程啟動(dòng)時(shí)讀取來(lái)從journal中恢復(fù);
  3. LastLogMark一旦被持久化到磁盤(pán)惑灵,即意味著在其之前的Index和EntryLog都已經(jīng)被持久化到了磁盤(pán)佩憾,那么journal在這個(gè)LastLogMark之前的數(shù)據(jù)都可以被清除了潭辈。
落盤(pán)數(shù)據(jù)目錄設(shè)置優(yōu)化
  • journal, entrylog, index最好設(shè)置在不同磁盤(pán)上,避免IO競(jìng)爭(zhēng);
  • journal 最好寫(xiě)在SSD等高速磁盤(pán)上修赞。
數(shù)據(jù)寫(xiě)入后各種文件的更新流程
  • 流程圖
data-flow1.png
文件目錄使用情況監(jiān)控
  • 用于寫(xiě)入文件的目錄有三種狀態(tài):

    1. 可寫(xiě);
    2. 可寫(xiě)柏副,但剩余空間低于所配置的警告閾值;
    3. 不可寫(xiě)割择,已經(jīng)寫(xiě)滿(mǎn); 當(dāng)被GC清理了一部分?jǐn)?shù)據(jù)后萎河,其狀態(tài)又可變?yōu)榭蓪?xiě);
  • BookKeeper需要持續(xù)監(jiān)控目錄空間使用情況, 通過(guò) LedgerDirsMonitor 類(lèi)實(shí)現(xiàn), 我們主要來(lái)分析一下它的 check 方法玛歌, 注釋寫(xiě)在函數(shù)體內(nèi)

    private void check(final LedgerDirsManager ldm) {
    // 對(duì)于Index, EntryLog, Journal都可以設(shè)置多個(gè)存儲(chǔ)路徑, 每一種對(duì)應(yīng)一個(gè)LedgerDirsManager
    // 先獲取每種對(duì)應(yīng)的dirs的使用情況
        final ConcurrentMap<File, Float> diskUsages = ldm.getDiskUsages();
        try {
        //獲取當(dāng)前可寫(xiě)狀態(tài)的目錄
            List<File> writableDirs = ldm.getWritableLedgerDirs();
            // Check all writable dirs disk space usage.
            // 循環(huán)遍歷當(dāng)前可寫(xiě)狀態(tài)的dirs的剩余可寫(xiě)容量,更新diskUsages
            // 同時(shí)處理各種異常值朋,比如
            // 1. 讀dir失敗,回調(diào)diskFailed
            // 2. 可寫(xiě)容量低于警戒閾值圈膏,但還處于可寫(xiě)狀態(tài), 回調(diào) diskAlmostFull
            // 3. 不可寫(xiě)稽坤,調(diào)用ldm.addToFilledDirs
            for (File dir : writableDirs) {
                try {
                    diskUsages.put(dir, diskChecker.checkDir(dir));
                } catch (DiskErrorException e) {
                    LOG.error("Ledger directory {} failed on disk checking : ", dir, e);
                    // Notify disk failure to all listeners
                    for (LedgerDirsListener listener : ldm.getListeners()) {
                        listener.diskFailed(dir);
                    }
                } catch (DiskWarnThresholdException e) {
                    diskUsages.compute(dir, (d, prevUsage) -> {
                        if (null == prevUsage || e.getUsage() != prevUsage) {
                            LOG.warn("Ledger directory {} is almost full : usage {}", dir, e.getUsage());
                        }
                        return e.getUsage();
                    });
                    for (LedgerDirsListener listener : ldm.getListeners()) {
                        listener.diskAlmostFull(dir);
                    }
                } catch (DiskOutOfSpaceException e) {
                    diskUsages.compute(dir, (d, prevUsage) -> {
                        if (null == prevUsage || e.getUsage() != prevUsage) {
                            LOG.error("Ledger directory {} is out-of-space : usage {}", dir, e.getUsage());
                        }
                        return e.getUsage();
                    });
                    // Notify disk full to all listeners
                    ldm.addToFilledDirs(dir);
                }
            }
            // Let's get NoWritableLedgerDirException without waiting for the next iteration
            // in case we are out of writable dirs
            // otherwise for the duration of {interval} we end up in the state where
            // bookie cannot get writable dir but considered to be writable
            // check完之前所有可寫(xiě)目錄的最新?tīng)顟B(tài)后得湘,
            // 看看現(xiàn)在還有沒(méi)有可寫(xiě)的目錄摆马,沒(méi)有可用的就拋出異常
            ldm.getWritableLedgerDirs();
        } catch (NoWritableLedgerDirException e) {
            LOG.warn("LedgerDirsMonitor check process: All ledger directories are non writable");
            boolean highPriorityWritesAllowed = true;
            try {
                // disk check can be frequent, so disable 'loggingNoWritable' to avoid log flooding.
                ldm.getDirsAboveUsableThresholdSize(minUsableSizeForHighPriorityWrites, false);
            } catch (NoWritableLedgerDirException e1) {
                highPriorityWritesAllowed = false;
            }
            
            //進(jìn)到這里,表明沒(méi)有可寫(xiě)的目錄了惩淳,回調(diào)allDisksFull
            for (LedgerDirsListener listener : ldm.getListeners()) {
                listener.allDisksFull(highPriorityWritesAllowed);
            }
        }

        List<File> fullfilledDirs = new ArrayList<File>(ldm.getFullFilledLedgerDirs());
        boolean makeWritable = ldm.hasWritableLedgerDirs();

        // When bookie is in READONLY mode, i.e there are no writableLedgerDirs:
        // - Update fullfilledDirs disk usage.
        // - If the total disk usage is below DiskLowWaterMarkUsageThreshold
        // add fullfilledDirs back to writableLedgerDirs list if their usage is < conf.getDiskUsageThreshold.
        try {
            if (!makeWritable) {
                // 返回當(dāng)前所有目錄總的已用容量百分比
                float totalDiskUsage = diskChecker.getTotalDiskUsage(ldm.getAllLedgerDirs());
                if (totalDiskUsage < conf.getDiskLowWaterMarkUsageThreshold()) {
                    makeWritable = true;
                } else {
                    LOG.debug(
                        "Current TotalDiskUsage: {} is greater than LWMThreshold: {}."
                                + " So not adding any filledDir to WritableDirsList",
                        totalDiskUsage, conf.getDiskLowWaterMarkUsageThreshold());
                }
            }
            // Update all full-filled disk space usage
            // 之前處于不可寫(xiě)狀態(tài)的目錄,如果GC時(shí)清除掉一些數(shù)據(jù)棉磨,則可能變?yōu)榭蓪?xiě)狀態(tài)乘瓤,這里作check
            for (File dir : fullfilledDirs) {
                try {
                    diskUsages.put(dir, diskChecker.checkDir(dir));
                    if (makeWritable) {
                        ldm.addToWritableDirs(dir, true);
                    }
                } catch (DiskErrorException e) {
                    // Notify disk failure to all the listeners
                    for (LedgerDirsListener listener : ldm.getListeners()) {
                        listener.diskFailed(dir);
                    }
                } catch (DiskWarnThresholdException e) {
                    diskUsages.put(dir, e.getUsage());
                    // the full-filled dir become writable but still above the warn threshold
                    if (makeWritable) {
                        ldm.addToWritableDirs(dir, false);
                    }
                } catch (DiskOutOfSpaceException e) {
                    // the full-filled dir is still full-filled
                    diskUsages.put(dir, e.getUsage());
                }
            }
        } catch (IOException ioe) {
            LOG.error("Got IOException while monitoring Dirs", ioe);
            for (LedgerDirsListener listener : ldm.getListeners()) {
                listener.fatalError();
            }
        }
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末差油,一起剝皮案震驚了整個(gè)濱河市蓄喇,隨后出現(xiàn)的幾起案子妆偏,更是在濱河造成了極大的恐慌叔锐,老刑警劉巖愉烙,帶你破解...
    沈念sama閱讀 221,273評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件步责,死亡現(xiàn)場(chǎng)離奇詭異蔓肯,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)气忠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人陪毡,你說(shuō)我怎么就攤上這事勾扭∶钌” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,709評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵芍碧,是天一觀的道長(zhǎng)泌豆。 經(jīng)常有香客問(wèn)我踪危,道長(zhǎng)陨倡,這世上最難降的妖魔是什么兴革? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,520評(píng)論 1 296
  • 正文 為了忘掉前任杂曲,我火速辦了婚禮擎勘,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘噪漾。我一直安慰自己欣硼,他們只是感情好诈胜,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著缓熟,像睡著了一般薛夜。 火紅的嫁衣襯著肌膚如雪梯澜。 梳的紋絲不亂的頭發(fā)上晚伙,一...
    開(kāi)封第一講書(shū)人閱讀 52,158評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音午磁,去河邊找鬼毡们。 笑死,一個(gè)胖子當(dāng)著我的面吹牛衙熔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播红氯,決...
    沈念sama閱讀 40,755評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼痢甘,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼喇嘱!你這毒婦竟也來(lái)了产阱?” 一聲冷哼從身側(cè)響起块仆,我...
    開(kāi)封第一講書(shū)人閱讀 39,660評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎悔据,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體藻烤,經(jīng)...
    沈念sama閱讀 46,203評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評(píng)論 3 340
  • 正文 我和宋清朗相戀三年涎显,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了呐赡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晨另。...
    茶點(diǎn)故事閱讀 40,427評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡路翻,死狀恐怖帚桩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情疼邀,我是刑警寧澤,帶...
    沈念sama閱讀 36,122評(píng)論 5 349
  • 正文 年R本政府宣布蹬铺,位于F島的核電站,受9級(jí)特大地震影響恒序,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜与帆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望郭卫。 院中可真熱鬧蟹肘,春花似錦、人聲如沸舵盈。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,272評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)秃殉。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留簿寂,地道東北人纳令。 一個(gè)月前我還...
    沈念sama閱讀 48,808評(píng)論 3 376
  • 正文 我出身青樓捏雌,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親叹括。 傳聞我的和親對(duì)象是個(gè)殘疾皇子报咳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容