redis.conf翻譯與配置(六)【redis6.0.6】
750
2022-05-28
環(huán)形緩沖區(qū)底層實(shí)現(xiàn)
首先明白改過程發(fā)生在Map——Collect階段:在用戶編寫的map()函數(shù)中,當(dāng)數(shù)據(jù)處理完成后,一般會(huì)調(diào)用OutputCollector.collect()輸出結(jié)果。在該函數(shù)內(nèi)部,它會(huì)將生成的key/value分片(通過調(diào)用Partitioner),并寫入一個(gè)環(huán)形內(nèi)存緩沖區(qū)中。
MapOutputBuffer內(nèi)部使用了一個(gè)緩沖區(qū)暫時(shí)存儲(chǔ)用戶輸出數(shù)據(jù),當(dāng)緩沖區(qū)使用率達(dá)到一定閾值后,再將緩沖區(qū)中的數(shù)據(jù)寫到磁盤上。
數(shù)據(jù)緩沖區(qū)的設(shè)計(jì)方式直接影響到Map Task的寫效率,而現(xiàn)有多種數(shù)據(jù)結(jié)構(gòu)可供選擇,最簡單的是單向緩沖區(qū),生產(chǎn)者向緩沖區(qū)中單向?qū)懭胼敵觯?dāng)緩沖區(qū)寫滿后,一次性寫到磁盤上,就這樣,不斷寫緩沖區(qū),直到所有數(shù)據(jù)寫到磁盤上。單向緩沖區(qū)最大的問題是性能不高,不能支持同時(shí)讀寫數(shù)據(jù)。
雙緩沖區(qū)是對(duì)單向緩沖區(qū)的一個(gè)改進(jìn),它使用兩個(gè)緩沖區(qū),其中一個(gè)用于寫入數(shù)據(jù),另一個(gè)將寫滿的數(shù)據(jù) 寫到磁盤上,這樣,兩個(gè)緩沖區(qū)交替讀寫,進(jìn)而提高效率。實(shí)際上,雙緩沖區(qū)只能一定程度上讓讀寫并行,仍會(huì)存在讀寫等待問題。
一種更好的緩沖區(qū)設(shè)計(jì)方式是采用環(huán)形緩沖區(qū):當(dāng)緩沖區(qū)使用率達(dá)到一定閾值后,便開始向磁盤上寫入數(shù)據(jù),同時(shí),生產(chǎn)者仍可以向不斷增加的剩余空間中循環(huán)寫入數(shù)據(jù),進(jìn)而達(dá)到真正的讀寫并行。
底層就是一個(gè)字節(jié)數(shù)組:數(shù)組前面記錄關(guān)于KV的索引位置,數(shù)組后面記錄KV數(shù)據(jù)。首尾相接構(gòu)成一個(gè)環(huán)形的緩沖區(qū),中間是赤道。用于數(shù)據(jù)spll溢出處理。
單生產(chǎn)者消費(fèi)者模型,其中,MapOutputBuffer的collect方法和MapOutputBuffer.Buffer的write方法是生 產(chǎn)者,spillThread線程是消費(fèi)者,它們之間同步是通過可重入的互斥鎖spillLock和spillLock上的兩個(gè)條件變量(spillDone和spillReady)完成 的.生產(chǎn)者主要代碼如下
//取得下一個(gè)可寫入的位置 spillLock.lock(); if(緩沖區(qū)使用率達(dá)到閾值){ //喚醒SpillThread線程,將緩沖區(qū)數(shù)據(jù)寫入磁盤 spillReady.signal(); } if(緩沖區(qū)滿){ //等待SpillThread線程結(jié)束 spillDone.wait(); } spillLock.lock(); //將數(shù)據(jù)寫入緩沖區(qū)
MapOutputBuffer內(nèi)部采用了兩級(jí)索引結(jié)構(gòu),涉及三個(gè)環(huán)形內(nèi)存緩沖區(qū),分別是kvoffsets、kvindices和kvbuffer,這三個(gè)緩沖 區(qū)所占內(nèi)存空間總大小為io.sort.mb(默認(rèn)是100 MB)。
kvoffsets即偏移量索引數(shù)組,用于保存key/value信息在位置索引kvindices中的偏移量。考慮到一對(duì)key/value需占用數(shù)組kvoffsets的1個(gè) int(整型)大小,數(shù)組kvindices的3個(gè)int大?。ǚ謩e保存所在partition號(hào)、key開始位置和value開始位置),所以Hadoop按比例1:3將大小為 ${io.sort.record.percent}*${io.sort.mb}的內(nèi)存空間分配給數(shù)組kvoffsets和kvindices,
該過 程由指針kvstart/kvend/kvindex控制,其中kvstart表示存有數(shù)據(jù)的內(nèi)存段初始位置,kvindex表示未存儲(chǔ)數(shù)據(jù)的內(nèi)存段初始位置,而在正常寫 入情況下,kvend=kvstart,一旦滿足溢寫條件,則kvend=kvindex,此時(shí)指針區(qū)間[kvstart, kvend)為有效數(shù)據(jù)區(qū)間。
kvindices即位置索引數(shù)組,用于保存key/value值在數(shù)據(jù)緩沖區(qū)kvbuffer中的起始位置。
kvbuffer即數(shù)據(jù)緩沖區(qū),用于保存實(shí)際的key/value值,默認(rèn)情況下最多可使用io.sort.mb中的95%,當(dāng)該緩沖區(qū)使用率超過 io.sort.spill.percent(默認(rèn)80%)后,便會(huì)觸發(fā)線程SpillThread將數(shù)據(jù)寫入磁盤。
更多的詳細(xì)信息你可以參考《Hadoop技術(shù)內(nèi)幕:深入解析MapReduce架構(gòu)設(shè)計(jì)與實(shí)現(xiàn)原理 》
你可以點(diǎn)這里掃描二維碼(或者微信搜 :孫中明) 回復(fù)關(guān)鍵字 3006 獲取相關(guān)書籍此類
MapReduce 數(shù)據(jù)結(jié)構(gòu)
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。