欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

幾分鐘教你掌握Redis簡(jiǎn)單動(dòng)態(tài)字符串SDS

 更新時(shí)間:2023年01月28日 11:24:46   作者:golandscape  
這篇文章主要為大家介紹了幾分鐘教你掌握Redis簡(jiǎn)單動(dòng)態(tài)字符串SDS方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

正文

Redis 沒有直接使用 C 語言傳統(tǒng)的字符串表示(而是以空字符結(jié)尾的字符數(shù)組,以下簡(jiǎn)稱 C 字符串),自己構(gòu)建了一種名為簡(jiǎn)單動(dòng)態(tài)字符串(simple dynamic string,SDS) 的抽象類型,并將 SDS 用作 Redis 的默認(rèn)字符串表示。

在 Redis 里面,C 字符串只會(huì)作為字符串字面量(string literal),用在一些無須對(duì)字符串值進(jìn)行修改的地方,比如打印日志:

redisLog(REDIS_WARNING,"Redis is now ready to exit, bye bye...");

當(dāng) Redis 需要的不僅僅是一個(gè)字符串字面量,而是一個(gè)可以被修改的字符串值時(shí),Redis 就會(huì)使用 SDS 來表示字符串值:比如在 Redis 的數(shù)據(jù)庫(kù)里面,包含字符串的鍵值對(duì)在底層都是由 SDS 實(shí)現(xiàn)的。

舉個(gè)例子,如果客戶端執(zhí)行命令:

redis> SET msg "hello world"
OK

那么 Redis 將在數(shù)據(jù)庫(kù)中創(chuàng)建了一個(gè)新的鍵值對(duì),其中:

  • 鍵值對(duì)的鍵是一個(gè)字符串對(duì)象,對(duì)象的底層實(shí)現(xiàn)是一個(gè)保存著字符串 "msg" 的 SDS 。
  • 鍵值對(duì)的值也是一個(gè)字符串對(duì)象,對(duì)象的底層實(shí)現(xiàn)是一個(gè)保存著字符串 "hello world" 的SDS。

又比如說,如果客戶端執(zhí)行命令:

redis> RPUSH fruits "apple" "banana" "cherry"
(integer) 3

那么 Redis 將在數(shù)據(jù)庫(kù)中創(chuàng)建一個(gè)新的鍵值對(duì),其中:

  • 鍵值對(duì)的鍵是一個(gè)字符串對(duì)象,對(duì)象的底層實(shí)現(xiàn)是一個(gè)保存了字符串 "fruits" 的 SDS 。
  • 鍵值對(duì)的值是一個(gè)列表對(duì)象,列表對(duì)象包含了三個(gè)字符串對(duì)象,這三個(gè)字符串對(duì)象分別由三個(gè) SDS 實(shí)現(xiàn):第一個(gè) SDS 保存著字符串 "apple" ,第二個(gè) SDS 保存著字符串 "banana" ,第三個(gè) SDS 保存著字符串 "cherry"

除了用來保存數(shù)據(jù)庫(kù)中的字符串值之外,SDS 還被用作緩沖區(qū)(buffer):AOF 模塊中的 AOF 緩沖區(qū),以及客戶端狀態(tài)中的輸入緩沖區(qū),都是由 SDS 實(shí)現(xiàn)的,在之后介紹 AOF 持久化和客戶端狀態(tài)的時(shí)候,我們會(huì)看到 SDS 在這兩個(gè)模塊中的應(yīng)用。

AOF中記錄的是每一個(gè)命令的詳細(xì)信息,包括完整的命令類型、參數(shù)等。只要產(chǎn)生寫命令,就會(huì)實(shí)時(shí)寫入到AOF文件中

SDS的定義

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

與C字符串的區(qū)別

C語言使用長(zhǎng)度為 N+1 的字符數(shù)組來表示長(zhǎng)度為 N 的字符串,并且字符數(shù)組的最后一個(gè)元素總是空字符 '\0'

獲取字符串長(zhǎng)度

因?yàn)?C 字符串并不記錄自身的長(zhǎng)度信息,所以為了獲取一個(gè) C 字符串的長(zhǎng)度,程序必須遍歷整個(gè)字符串O(N)O(N)O(N) 。

和 C 字符串不同,因?yàn)?SDS 在 len 屬性中記錄了 SDS 本身的長(zhǎng)度,所以獲取一個(gè) SDS 長(zhǎng)度的復(fù)雜度僅為 O(1)O(1)O(1) 。

杜絕緩沖區(qū)溢出

C 字符串不記錄自身長(zhǎng)度帶來的另一個(gè)問題是容易造成緩沖區(qū)溢出(buffer overflow)。

假設(shè)程序里有兩個(gè)在內(nèi)存中緊鄰著的 C 字符串 s1 和 s2 ,其中 s1 保存了字符串 "Redis" ,而 s2 則保存了字符串 "MongoDB" .

如果一個(gè)程序員決定通過執(zhí)行:strcat(s1, "Cluster")將 s1 的內(nèi)容修改為 "Redis Cluster" ,但粗心的他卻忘了在執(zhí)行 strcat 之前為 s1 分配足夠的空間,那么在 strcat 函數(shù)執(zhí)行之后,s1 的數(shù)據(jù)將溢出到 s2 所在的空間中,導(dǎo)致 s2 保存的內(nèi)容被意外地修改。

SDS 的空間分配策略完全杜絕了發(fā)生緩沖區(qū)溢出的可能性:當(dāng) SDS API 需要對(duì) SDS 進(jìn)行修改時(shí),API 會(huì)先檢查 SDS 的空間是否滿足修改所需的要求,如果不滿足的話,API 會(huì)自動(dòng)將 SDS 的空間擴(kuò)展至執(zhí)行修改所需的大小,然后才執(zhí)行實(shí)際的修改操作,所以使用 SDS 既不需要手動(dòng)修改 SDS 的空間大小,也不會(huì)出現(xiàn)前面所說的緩沖區(qū)溢出問題。

減少內(nèi)存分配次數(shù)

因?yàn)?C 字符串的長(zhǎng)度和底層數(shù)組的長(zhǎng)度之間存在著這種關(guān)聯(lián)性,所以每次增長(zhǎng)或者縮短一個(gè) C 字符串,程序都總要對(duì)保存這個(gè) C 字符串的數(shù)組進(jìn)行一次內(nèi)存重分配操作,在 SDS 中,數(shù)組里面可以包含未使用的字節(jié),而這些字節(jié)的數(shù)量就由 SDS 的 free 屬性記錄。并實(shí)現(xiàn)了兩種優(yōu)化策略:

空間預(yù)分配,當(dāng)進(jìn)行字符串增長(zhǎng)操作時(shí),程序會(huì)額外分配空間,并記錄的free字段

比如原長(zhǎng)度為8的字符串,新增5個(gè)長(zhǎng)度后,總共為13長(zhǎng)度,則預(yù)分配13+13+1=27字節(jié)(額外一字節(jié)用于保存空字符串)

對(duì)于大于1M來說,分配空間為原有總長(zhǎng)度+1MB+1byte

比如增加完字符串后長(zhǎng)度為15MB,則為15MB+1MB+1byte

惰性空間釋放,當(dāng)進(jìn)行字符串縮短操作時(shí),程序不立即重新分配內(nèi)存,而是用free屬性將這些字節(jié)的數(shù)量記錄起來。

二進(jìn)制安全

C字符串中不能包含空字符串,否則會(huì)被誤認(rèn)為是字符串結(jié)尾。所有 SDS API 都會(huì)以處理二進(jìn)制的方式來處理 SDS 存放在 buf 數(shù)組里的數(shù)據(jù),程序不會(huì)對(duì)其中的數(shù)據(jù)做任何限制、過濾、或者假設(shè) ——數(shù)據(jù)在寫入時(shí)是什么樣的,它被讀取時(shí)就是什么樣。

以上就是幾分鐘教你掌握Redis簡(jiǎn)單動(dòng)態(tài)字符串SDS的詳細(xì)內(nèi)容,更多關(guān)于Redis動(dòng)態(tài)字符串SDS的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • windows上修改redis端口號(hào)的操作步驟

    windows上修改redis端口號(hào)的操作步驟

    redis是一個(gè)開源的內(nèi)存數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)系統(tǒng),常用做數(shù)據(jù)庫(kù)、緩存和消息代理,默認(rèn)的端口號(hào)為6379,那么如何在windows上修改redis端口號(hào),接下來本文給大家詳細(xì)介紹了windows上修改redis端口號(hào)的操作方法,需要的朋友可以參考下
    2024-02-02
  • Redis實(shí)現(xiàn)編碼生成規(guī)則方式

    Redis實(shí)現(xiàn)編碼生成規(guī)則方式

    在自動(dòng)生成編碼時(shí)應(yīng)采用“MD+年月日+4位序列號(hào)”的規(guī)則,如“MD202310130001”,為避免使用隨機(jī)序列號(hào)導(dǎo)致的重復(fù)編碼,建議使用從0開始的自增序列號(hào),此外,使用Redis的incrBy功能實(shí)現(xiàn)序列號(hào)自增,可以有效提高效率和降低實(shí)現(xiàn)難度
    2023-01-01
  • Redis實(shí)現(xiàn)延遲隊(duì)列的項(xiàng)目示例

    Redis實(shí)現(xiàn)延遲隊(duì)列的項(xiàng)目示例

    延遲隊(duì)列是Redis的一個(gè)重要應(yīng)用場(chǎng)景,本文主要介紹了Redis實(shí)現(xiàn)延遲隊(duì)列的項(xiàng)目示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-06-06
  • NestJS+Redis實(shí)現(xiàn)手寫一個(gè)限流器

    NestJS+Redis實(shí)現(xiàn)手寫一個(gè)限流器

    限流是大型系統(tǒng)必備的保護(hù)措施,本文將結(jié)合redis , lua 腳本 以及 Nestjs Guard 來實(shí)現(xiàn) 限流的效果,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-11-11
  • 深入理解redis刪除策略和淘汰策略

    深入理解redis刪除策略和淘汰策略

    每隔一段時(shí)間就掃描一定數(shù)據(jù)的設(shè)置了過期時(shí)間的key,并清除其中已過期的keys,本文主要介紹了深入理解redis刪除策略和淘汰策略,感興趣的可以了解一下
    2024-08-08
  • Redis cluster集群的介紹

    Redis cluster集群的介紹

    今天小編就為大家分享一篇關(guān)于Redis cluster集群的介紹,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • redis?lua腳本解決高并發(fā)下秒殺場(chǎng)景

    redis?lua腳本解決高并發(fā)下秒殺場(chǎng)景

    這篇文章主要為大家介紹了redis?lua腳本解決高并發(fā)下秒殺場(chǎng)景,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10
  • 利用redis實(shí)現(xiàn)分布式鎖,快速解決高并發(fā)時(shí)的線程安全問題

    利用redis實(shí)現(xiàn)分布式鎖,快速解決高并發(fā)時(shí)的線程安全問題

    這篇文章主要介紹了利用redis實(shí)現(xiàn)分布式鎖,快速解決高并發(fā)時(shí)的線程安全問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • Redis不僅僅是緩存,還是……

    Redis不僅僅是緩存,還是……

    Redis是一個(gè)開源的(BSD協(xié)議),內(nèi)存中的數(shù)據(jù)結(jié)構(gòu)存儲(chǔ),它可以用作數(shù)據(jù)庫(kù),緩存,消息代理。這篇文章主要介紹了Redis不僅僅是緩存,還是……,需要的朋友可以參考下
    2020-12-12
  • redis服務(wù)啟動(dòng)與停止方式

    redis服務(wù)啟動(dòng)與停止方式

    這篇文章主要介紹了redis服務(wù)啟動(dòng)與停止方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01

最新評(píng)論