內(nèi)存碎片的產(chǎn)生與對(duì)數(shù)據(jù)進(jìn)行的操作,數(shù)據(jù)的特點(diǎn)等有關(guān),與使用的內(nèi)存分配器也有關(guān)。如果redis服務(wù)器的內(nèi)存碎片很大,可以通過(guò)安全重啟的方式減少內(nèi)存碎片,重啟后,redis重新從備份文件中讀取數(shù)據(jù),在內(nèi)存中進(jìn)行重排,為每個(gè)數(shù)據(jù)重新選擇合適的內(nèi)存單元,減少內(nèi)存碎片
linux采用著名的伙伴系統(tǒng)buddy system算法來(lái)解決外碎片問(wèn)題。把所有的空閑頁(yè)框分組為11個(gè)塊鏈表,每個(gè)鏈表分別包含大小為1,2,4,8,16,32,64,128,256,512,1024連續(xù)的頁(yè)框,對(duì)1024頁(yè)框的最大請(qǐng)求對(duì)應(yīng)著4MB大小的連續(xù)RAM(每頁(yè)大小為4KB),每個(gè)塊的第一個(gè)頁(yè)框的物理地址是該塊大小的整數(shù)倍,例如,大小為16個(gè)頁(yè)框的塊,其起始地址是16*2^12的倍數(shù)。
我們通過(guò)一個(gè)例子來(lái)說(shuō)明伙伴算法的工作原理,假設(shè)現(xiàn)在要請(qǐng)求一個(gè)256個(gè)頁(yè)框的塊(1MB),算法步驟如下:
- 在256頁(yè)框的鏈表中檢查是否有一個(gè)空閑塊,如果沒(méi)有,查找下一個(gè)更大的塊,如果有,請(qǐng)求滿足。
- 在512頁(yè)框的鏈表中檢查是否有一個(gè)空閑塊,如果有,把512個(gè)頁(yè)框的空閑塊分為兩份,第一份用于滿足請(qǐng)求,第二份鏈接到256個(gè)頁(yè)框的鏈表中。如果沒(méi)有空閑塊,繼續(xù)尋找下一個(gè)更大的塊。
下圖比較形象地描述了該過(guò)程。
以上過(guò)程的逆過(guò)程,就是頁(yè)框塊的釋放過(guò)程,也是該算法名字的由來(lái),內(nèi)核試圖把大小為B的一對(duì)空閑伙伴塊合并為一個(gè)2B的單獨(dú)塊,滿足以下條件的兩個(gè)塊稱之為伙伴:
- 兩個(gè)塊具有相同的大小
- 他們的物理地址是連續(xù)的
- 第一塊的第一個(gè)頁(yè)框的物理地址是2 * B * 2^12
該算法是遞歸的,如果它成功合并了B,就會(huì)試圖去合并2B,以再次試圖形成更大的塊。






