Redis設計與實現 筆記 第二章 簡單動態字串

2021-10-02 19:50:01 字數 1667 閱讀 6849

redis使用自定義字串來替代c語言傳統的字串,

struct sdshdr ;
可以使用

printf("%s",s->buff)來輸出
通常 c 語言長度會使用 strlen() 來進行長度的計算,其原理為從開始指標往後尋找 『\0』 字元來確定長度, 複雜度是 o(n) 實際上是進行了遍歷,而redis使用的結構,其記錄了 len 的長度,所以複雜度是 o(1) ,確保獲取字串長度的工作不會成為 redis的效能瓶頸.反覆使用strlen命令也不會造成任何影響.

c 語言使用 strcat() 來進行字串拼接,典型出現的問題是,當目標字串分配的長度不夠追加長度和源字串長度時,會造成記憶體溢位, redis 中使用 sdscatsds() 來進行字串拼接,在拼接時會進行長度檢查,如果長度不夠會進行額外的處理,生成長度適當的物件來儲存

sds sdsmakeroomfor(sds s, size_t addlen) 

sds sdscatlen(sds s, const void *t, size_t len)

sds sdscatsds(sds s, const sds t)

上述提到, c 語言字元字進行拼接時,會進行額外的分配,如果原字串的長度不夠,需要重新進行分配操作,在一般程式中,如果修改字串長度的情況不太常出現,那麼每次修改都執行一次記憶體重分配是可以接受的,但是 redis 作為資料庫,經常被用於速度要求嚴苛,資料被頻繁修改的場合,如果每進行字串長度修改就要重分配記憶體,會對效能造成影響.

所以 redis 作出以下優化:

(1): 空間預分配:

當 sds 長度小於1mb時候(len值),額外分配一倍記憶體,也就是如果buff長度為13位元組,那麼未使用空間也將是13位元組,也就是buf實際長度為 13byte+13byte+1byte = 27

當 sds 長度大於1mb時,額外分配 1mb 的記憶體, 也就是buff識記長度為 1mb+ 1mb + 1byte

(2): 惰性空間釋放

當乙個字串進行字元刪減時,多出來的字元也會存放至free中,以備在未來可能的需要,總的來說,無論是預分配還是釋放規則,最終目的都是用空間來減少記憶體的申請和釋放,也是用空間換時間的思路.

sds sdstrim(sds s, const char *cset)
當然如果確定某字串不會改變時,呼叫下面函式來進行真正的釋放,來節省空間

sds sdsremovefreespace(sds s)
雖然 redis 是使用長度來決定字串的長度,但是每個字串後還是會用』\0』來進行結尾,也就是意味著, strcat(c_string,s->buff);第二個引數可以直接使用 sds 的成員來進行呼叫.

c 字串

sds獲取字串長度複雜度為o(n)

獲取字串長度複雜度為o(1)

api是不安全的,會造成緩衝區溢位

api是安全的,不會造成緩衝區溢位

修改字串長度n次必然需要執行n次記憶體分配

修改字串長度n次最多需要執行n次記憶體分配

只能儲存文字內容

可以使用中所有的函式

可以使用一部分中的函式

redis 只會使用 c 字串作為字面量,大多數情況下會使用 sds 來表示字串

linux 核心設計與實現(第二章筆記)

最近開始學習linux 核心相關的知識,一直想對linux核心做些了解,但是時間上的問題,雖然學習了三年的linux,也玩了幾乎四年的linux系統,但是從來沒有對linux 核心做乙個詳細的了解,最近抽出課餘時間對 linux核心設計與實現 進行了第一遍閱讀,相關的筆記如下,如果覺得不錯會做第二遍...

第二章筆記

1.遞迴查詢和迭代查詢 遞迴查詢是一條環路,直接想成遞迴的定義就行,你想查乙個 的ip,首先將這個 傳給它的本地dns,然後認為本地dns可以直接將ip給你,然後本地dns為了知道這個ip又詢問下個dns伺服器。從此可以看出,增加了被涉及的伺服器的資料,所以一般用迭代查詢,迭代查詢是你詢問完後給你下...

第二章 Redis入門介紹

redis學習 一 入門概述 1.1 什麼是 redis 1.2 學習重點 學習內容 1 資料型別 基本操作和配置。2 持久化和複製 rdb aodf 3 事務的控制 管道 分布式鎖和lua指令碼 4 主從複製 5 二 redis 安裝 2.1 docker 安裝 redis 並以配置檔案方式啟動 ...