<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>

          Go map[int64]int64 寫入 redis 占用多少內(nèi)存

          共 1563字,需瀏覽 4分鐘

           ·

          2021-11-18 02:51

          我們在系統(tǒng)設(shè)計面試或者在實(shí)際工作中,免不了要進(jìn)行一些估算。之前的文章里講過一些技巧,今天來個實(shí)戰(zhàn)。

          這是我最近在做的一個工作,將內(nèi)存中的一個超大的 map[int64]int64 寫入到 redis,map 里的元素個數(shù)是千萬級的。設(shè)計方案的時候,需要對 redis 的容量做一個估算。

          如果不了解 redis 的話,可能你的答案是用元素個數(shù)直接乘以 16B(key 和 value 各占 8B)。我們假設(shè)元素個數(shù)是 5kw,那估算結(jié)果就是:5kw * 16B=50kk * 16B = 800MB。

          答案是錯的。

          為了解決這個問題,需要深入地研究一下 redis 的數(shù)據(jù)結(jié)構(gòu)。

          整個 redis 數(shù)據(jù)庫就是一個大的 map,它容納了所有的 key,我們都知道 key 都是 string 類型,而 value 則有 string, list, set, hashmap, zset……等類型。

          Redis 中的一個 k-v 對用一個 entry 項(xiàng)表示,其中每個 entry 包含 key、value、next 三個指針,共 24 字節(jié)。由于 redis 使用 jemalloc 分配內(nèi)存,因此一個 entry 需要申請 32 字節(jié)的內(nèi)存。這里的 key, value 指針分別指向一個 RedisObject:

          redis entry
          typedef?struct?redisObject?{
          ????unsigned?type:4;
          ????unsigned?encoding:4;
          ????unsigned?lru:LRU_BITS;?
          ????int?refcount;
          ????void?*ptr;
          }?robj;

          RedisObject 對應(yīng)前面提到的各種數(shù)據(jù)類型,其中最簡單的就是 redis 內(nèi)部的字符串了。它有如下幾種編碼格式:

          SDS 編碼(圖片來自極客時間-redis 專欄)

          圖中的元數(shù)據(jù)包括 type,encoding,lru, refcount,分別表示數(shù)據(jù)類型,編碼類型,最近一次訪問的時間戳,引用次數(shù)。

          當(dāng)字符串是一個整型時,直接放在 ptr 位置,不用再分配新的內(nèi)存了,非常高效。

          解析一下 44 字節(jié)的原因:元數(shù)據(jù)和 ptr 共占 16 字節(jié),加上 44 字節(jié),再加上字符串末尾的 '\0',共61 字節(jié)。因?yàn)樽址拈L度只有 44,因此 len 和 alloc 各用 1 個字節(jié)就夠了。再加上 1 個字節(jié)的 flags,剛好是 64 字節(jié)。超過了這個值,SDS 就需要單獨(dú)再申請一塊內(nèi)存,導(dǎo)致訪問的時候就多了一跳指針。

          多提一句,redis 最大支持 512MB 大小的字符串。

          回答本文的問題,恰好我們要寫入 redis 的 map 中的 key 和 value 都是整數(shù),因此直接將值寫入 ptr 處即可。

          于是 map 的一個 key 占用的內(nèi)存大小為:32(entry)+16(value)+16(value)=64B。于是,5kw 個 key 占用的內(nèi)存大小是 5kw*64B = 50 kk * 64B = 3200MB ≈ 3G。

          假如我們在 key 前面加上了前綴,那就會生成 SDS,占用的內(nèi)存會變大,訪問效率也會變差。

          總之,我們根據(jù)要寫入 redis 中的字符串的長度可以很方便地估算占用內(nèi)存的總大小。如果 key 和 value 恰好都是 int64 類型的,那么盡量不要在 key 前加前綴,這樣可以直接使用 key 的個數(shù)乘以 64B 就能算出占用內(nèi)存的大小。


          瀏覽 75
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <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>
                  猛操人妻 | 欧美成人性网站 | 伊人久久大香线蕉av一区 | 国产在线拍揄自揄拍无码男男 | 国产黄色网啪啪啪精品视频a |