<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的String是如何實(shí)現(xiàn)的?

          共 2077字,需瀏覽 5分鐘

           ·

          2021-04-11 22:22

          ????關(guān)注后回復(fù) “進(jìn)群” ,拉你進(jìn)程序員交流群????
          作者丨安琪拉的博客
          來(lái)源丨安琪拉的博客

          第44題: Redis 的String 是怎么實(shí)現(xiàn)的?為什么不直接用c的字符串?

          Redis 沒有直接使用C 語(yǔ)言的字符串表示,而是自己構(gòu)建一種簡(jiǎn)單動(dòng)態(tài)字符串(SDS: simple dynamic string)。

          Redis 中的String 都是SDS,例如我們執(zhí)行這樣一條命令:

          redis> SET blog angela

          那么Redis 在內(nèi)存中創(chuàng)建了一個(gè)鍵值對(duì),

          • 鍵:鍵是一個(gè)字符串對(duì)象,對(duì)應(yīng)底層實(shí)現(xiàn)是一個(gè)保存字符串“blog” 的SDS;
          • 值:值也是一個(gè)字符串對(duì)象,對(duì)應(yīng)底層實(shí)現(xiàn)是一個(gè)保存字符串是“angela”的SDS。

          如果執(zhí)行

          redis> RPUSH blog "angela" "de" "blog"

          那么Redis 將在內(nèi)存中創(chuàng)建一個(gè)鍵值對(duì),鍵還是一個(gè)SDS,存放“blog”,值是一個(gè)列表,存放三個(gè)SDS,“angela”、“de”、“blog”

          SDS如何實(shí)現(xiàn)的呢?

          首先SDS被定義為這樣一個(gè)結(jié)構(gòu)體:

          struct sdshdr {
             char buf[];//字節(jié)數(shù)組,用于保存字符串
             int len;//記錄buf數(shù)組中已使用字節(jié)的數(shù)量
             int free;//記錄buf數(shù)組中未使用字節(jié)的數(shù)量
          }

          舉個(gè)例子:

          現(xiàn)有執(zhí)行redis> SET blog angela 命令后,value值在redis 中存放如下圖所示,buf存放字節(jié)數(shù)組(真實(shí)數(shù)據(jù)),len表示存放字符串的長(zhǎng)度(不包括結(jié)束符號(hào)'\0'),free表示剩余空間,可以看到還剩5個(gè)字節(jié)。

          SDS遵循了C語(yǔ)言字符串以空字符結(jié)尾的慣例,保存空字符的1個(gè)字節(jié)空間不在SDS 的len屬性里面。這樣做有個(gè)好處是我們直接可以復(fù)用C 提供的庫(kù)函數(shù),比如打印字符串,直接用C 提供的printf("%s", s->buf);

          那又是為什么不直接用C語(yǔ)言提供的字符串呢?

          在C語(yǔ)言中,表示一個(gè)“angela” 的字符串如下圖所示,結(jié)束也是通過(guò)空字符表示:

          C語(yǔ)言的字符串和SDS的區(qū)別如下:

          • 長(zhǎng)度獲取效率:C語(yǔ)言如果需要獲取字符串長(zhǎng)度,需要從頭開始遍歷,時(shí)間復(fù)雜度O(n),SDS提供len屬性,訪問(wèn)時(shí)間復(fù)雜度O(1), Redis的strlen 獲取字符串長(zhǎng)度函數(shù)性能毫無(wú)壓力;

          • 杜絕溢出:C字符串不記錄自身長(zhǎng)度的另一個(gè)問(wèn)題是容易造成緩沖區(qū)溢出,比如要做字符串拼接,char *strcat(char *dest, const char *src), 講src 字符串拼到desc字符串,如果desc忘記提前擴(kuò)容,就會(huì)溢出,而恰好desc后面正好有數(shù)據(jù),則會(huì)被覆蓋;

          • 減少內(nèi)存重分配:對(duì)于Redis這種內(nèi)存數(shù)據(jù)庫(kù),很多場(chǎng)景會(huì)頻繁更新value的值,那如果采用C字符串,value長(zhǎng)度有變化,就需要頻繁分配內(nèi)存,SDS做了內(nèi)存的預(yù)分配和惰性釋放,能有效減少內(nèi)存分配次數(shù),內(nèi)存的重分配代價(jià)還是很高昂的,對(duì)于Redis這種對(duì)性能要求非常高的緩存產(chǎn)品,這種性能損耗是不能接受的;

          • 二進(jìn)制安全:C字符串必須符合某種編碼(比如ASCII),除了空字符結(jié)尾,字符串中間是不能包含空字符的,否則會(huì)被誤以為是字符串結(jié)尾。這就限定了C字符串不能用來(lái)存儲(chǔ)類型圖片、音頻、視頻、壓縮文件這種二進(jìn)制書數(shù)據(jù),但是SDS可以,SDS設(shè)計(jì)的API都是二進(jìn)制安全的。

          -End-

          最近有一些小伙伴,讓我?guī)兔φ乙恍?nbsp;面試題 資料,于是我翻遍了收藏的 5T 資料后,匯總整理出來(lái),可以說(shuō)是程序員面試必備!所有資料都整理到網(wǎng)盤了,歡迎下載!

          點(diǎn)擊??卡片,關(guān)注后回復(fù)【面試題】即可獲取

          在看點(diǎn)這里好文分享給更多人↓↓

          瀏覽 17
          點(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>
                  一区二区三区四区五区六区七区八区九区 | 国产玖玖在线 | 精品乱伦网站 | 国产逼操| 爱爱199极品 |