<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          得物面試:Redis 內(nèi)存碎片是什么?如何清理?

          共 4458字,需瀏覽 9分鐘

           ·

          2024-04-19 09:03

          JavaGuide官方網(wǎng)站javaguide.cn

          這是一道不是特別高頻但很重要的 Redis 面試題,屬于 Redis 性能優(yōu)化的范疇。

          Redis 內(nèi)存碎片相關(guān)的問題在得物、美團(tuán)、阿里、字節(jié)、攜程等公司的后端面試中都曾出現(xiàn)過,還是建議認(rèn)真準(zhǔn)備一下。即使不是準(zhǔn)備面試,日常開發(fā)也是能夠用到的!

          什么是內(nèi)存碎片?

          你可以將內(nèi)存碎片簡單地理解為那些不可用的空閑內(nèi)存。

          舉個(gè)例子:操作系統(tǒng)為你分配了 32 字節(jié)的連續(xù)內(nèi)存空間,而你存儲(chǔ)數(shù)據(jù)實(shí)際只需要使用 24 字節(jié)內(nèi)存空間,那這多余出來的 8 字節(jié)內(nèi)存空間如果后續(xù)沒辦法再被分配存儲(chǔ)其他數(shù)據(jù)的話,就可以被稱為內(nèi)存碎片。

          內(nèi)存碎片

          Redis 內(nèi)存碎片雖然不會(huì)影響 Redis 性能,但是會(huì)增加內(nèi)存消耗。

          為什么會(huì)有 Redis 內(nèi)存碎片?

          Redis 內(nèi)存碎片產(chǎn)生比較常見的 2 個(gè)原因:

          1、Redis 存儲(chǔ)數(shù)據(jù)的時(shí)候向操作系統(tǒng)申請(qǐng)的內(nèi)存空間可能會(huì)大于數(shù)據(jù)實(shí)際需要的存儲(chǔ)空間。

          以下是這段 Redis 官方的原話:

          To store user keys, Redis allocates at most as much memory as the maxmemory setting enables (however there are small extra allocations possible).

          Redis 使用 zmalloc 方法(Redis 自己實(shí)現(xiàn)的內(nèi)存分配方法)進(jìn)行內(nèi)存分配的時(shí)候,除了要分配 size 大小的內(nèi)存之外,還會(huì)多分配 PREFIX_SIZE 大小的內(nèi)存。

          zmalloc 方法源碼如下(源碼地址:https://github.com/antirez/redis-tools/blob/master/zmalloc.c):

          void *zmalloc(size_t size) {
             // 分配指定大小的內(nèi)存
             void *ptr = malloc(size+PREFIX_SIZE);
             if (!ptr) zmalloc_oom_handler(size);
          #ifdef HAVE_MALLOC_SIZE
             update_zmalloc_stat_alloc(zmalloc_size(ptr))
          ;
             return ptr;
          #else
             *((size_t*)ptr) = size;
             update_zmalloc_stat_alloc(size+PREFIX_SIZE);
             return (char*)ptr+PREFIX_SIZE;
          #endif
          }

          另外,Redis 可以使用多種內(nèi)存分配器來分配內(nèi)存( libc、jemalloc、tcmalloc),默認(rèn)使用 jemalloc[1],而 jemalloc 按照一系列固定的大小(8 字節(jié)、16 字節(jié)、32 字節(jié)……)來分配內(nèi)存的。jemalloc 劃分的內(nèi)存單元如下圖所示:

          jemalloc 內(nèi)存單元示意圖

          當(dāng)程序申請(qǐng)的內(nèi)存最接近某個(gè)固定值時(shí),jemalloc 會(huì)給它分配相應(yīng)大小的空間,就比如說程序需要申請(qǐng) 17 字節(jié)的內(nèi)存,jemalloc 會(huì)直接給它分配 32 字節(jié)的內(nèi)存,這樣會(huì)導(dǎo)致有 15 字節(jié)內(nèi)存的浪費(fèi)。不過,jemalloc 專門針對(duì)內(nèi)存碎片問題做了優(yōu)化,一般不會(huì)存在過度碎片化的問題。

          2、頻繁修改 Redis 中的數(shù)據(jù)也會(huì)產(chǎn)生內(nèi)存碎片。

          當(dāng) Redis 中的某個(gè)數(shù)據(jù)刪除時(shí),Redis 通常不會(huì)輕易釋放內(nèi)存給操作系統(tǒng)。

          這個(gè)在 Redis 官方文檔中也有對(duì)應(yīng)的原話:

          文檔地址:https://redis.io/topics/memory-optimization

          如何查看 Redis 內(nèi)存碎片的信息?

          使用 info memory 命令即可查看 Redis 內(nèi)存相關(guān)的信息。下圖中每個(gè)參數(shù)具體的含義,Redis 官方文檔有詳細(xì)的介紹:https://redis.io/commands/INFO

          Redis 內(nèi)存碎片率的計(jì)算公式:mem_fragmentation_ratio (內(nèi)存碎片率)= used_memory_rss (操作系統(tǒng)實(shí)際分配給 Redis 的物理內(nèi)存空間大小)/ used_memory(Redis 內(nèi)存分配器為了存儲(chǔ)數(shù)據(jù)實(shí)際申請(qǐng)使用的內(nèi)存空間大小)

          也就是說,mem_fragmentation_ratio (內(nèi)存碎片率)的值越大代表內(nèi)存碎片率越嚴(yán)重。

          一定不要誤認(rèn)為used_memory_rss 減去 used_memory值就是內(nèi)存碎片的大小!!!這不僅包括內(nèi)存碎片,還包括其他進(jìn)程開銷,以及共享庫、堆棧等的開銷。

          很多小伙伴可能要問了:“多大的內(nèi)存碎片率才是需要清理呢?”。

          通常情況下,我們認(rèn)為 mem_fragmentation_ratio > 1.5 的話才需要清理內(nèi)存碎片。mem_fragmentation_ratio > 1.5 意味著你使用 Redis 存儲(chǔ)實(shí)際大小 2G 的數(shù)據(jù)需要使用大于 3G 的內(nèi)存。

          如果想要快速查看內(nèi)存碎片率的話,你還可以通過下面這個(gè)命令:

          > redis-cli -p 6379 info | grep mem_fragmentation_ratio

          另外,內(nèi)存碎片率可能存在小于 1 的情況。這種情況我在日常使用中還沒有遇到過,感興趣的小伙伴可以看看這篇文章 故障分析 | Redis 內(nèi)存碎片率太低該怎么辦?- 愛可生開源社區(qū)

          如何清理 Redis 內(nèi)存碎片?

          Redis4.0-RC3 版本以后自帶了內(nèi)存整理,可以避免內(nèi)存碎片率過大的問題。

          直接通過 config set 命令將 activedefrag 配置項(xiàng)設(shè)置為 yes 即可。

          config set activedefrag yes

          具體什么時(shí)候清理需要通過下面兩個(gè)參數(shù)控制:

          # 內(nèi)存碎片占用空間達(dá)到 500mb 的時(shí)候開始清理
          config set active-defrag-ignore-bytes 500mb
          # 內(nèi)存碎片率大于 1.5 的時(shí)候開始清理
          config set active-defrag-threshold-lower 50

          通過 Redis 自動(dòng)內(nèi)存碎片清理機(jī)制可能會(huì)對(duì) Redis 的性能產(chǎn)生影響,我們可以通過下面兩個(gè)參數(shù)來減少對(duì) Redis 性能的影響:

          # 內(nèi)存碎片清理所占用 CPU 時(shí)間的比例不低于 20%
          config set active-defrag-cycle-min 20
          # 內(nèi)存碎片清理所占用 CPU 時(shí)間的比例不高于 50%
          config set active-defrag-cycle-max 50

          另外,重啟節(jié)點(diǎn)可以做到內(nèi)存碎片重新整理。如果你采用的是高可用架構(gòu)的 Redis 集群的話,你可以將碎片率過高的主節(jié)點(diǎn)轉(zhuǎn)換為從節(jié)點(diǎn),以便進(jìn)行安全重啟。

          文章結(jié)尾,再推薦幾篇 Redis 相關(guān)的高頻面試題解答:

          參考資料

          [1]

          jemalloc: https://github.com/jemalloc/jemalloc

          ??推薦

          ??歡迎準(zhǔn)備 Java/后端面試的小伙伴加入我的知識(shí)星球

          點(diǎn)擊下方卡片進(jìn)入公眾號(hào)

          回復(fù) 「PDF 即可領(lǐng)取原創(chuàng)PDF技術(shù)面試手冊
          回復(fù) 「學(xué)習(xí)路線
           即可獲取4w+字最新版Java學(xué)習(xí)路線
          回復(fù) 「開源
           即可獲取優(yōu)質(zhì)Java開源項(xiàng)目合集
          免費(fèi)分享無套路,有幫助點(diǎn)個(gè)贊就好!



          瀏覽 52
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲无码护士 | 中文字幕亚洲一区 | 青青草成人在线播放 | 精品无码一区三区三区 | 天堂资源在线网 |