SDS-redis動態字串

新手村出發 發表於 2022-03-30
Redis

與C語言類似,redis自己建立了簡單動態字串SDS(Simple Dynamic String)即簡單動態字串,建立字串型別的鍵值對,SDS表示字串值,鍵值對的值為字串物件

SDS用途可以做緩衝區,客戶端狀態輸入緩衝,AOF持久化緩衝區等。

SDS結構及定義

struct sdshdr{
    int len;
    //sds字串的長度
    int free;
   // 記錄buff陣列未使用的陣列長度,為0則表示
    char buff[];
    // 位元組陣列,儲存字串,最後一個位元組儲存'\0'      
}

最後一個空字元不在SDS的len 屬性。

SDS和C字串區別

  1. o(1)複雜度獲取字串長度。與C不同(O(N)),C不計入字串長度需要遍歷,而SDS有自己的len屬性記錄長度且有自己的api更新設定。
  2. 緩衝區不會溢位。C的字串不計入自身長度,所以分配記憶體都假設分配足夠多記憶體,但是如果要修改更長的字串就會溢位。之所以SDS為動態的就體現在這,在分配資源時,會檢查空間是否滿足修改的要求,不滿足會擴充套件SDS修改要的大小,再進行修改。
  3. 減少記憶體重分配。增長字串C如果不重分配會緩衝區溢位,減少會記憶體重分配釋放空間,造成記憶體洩漏。對於redis來說,這兩操作較多,重分配次數多了效能會收到制約。
  • 空間先分配。修改擴充套件時會預分配額外未使用的空間。分兩種情況。
  1. SDS修改之後長度小於1MB,free分配與len值相同的空間,總長度=len+len+1
  2. 修改後的len大於1MB,則會分配1MB的未使用空間,實際總長度=len+1MB+1byte

這樣下次再修改會有足夠的空間儲存不用再重分配

  • 惰性空間釋放。用於縮短字串操作。當縮短字串時,先不記憶體重分配回收多出的位元組,用free記錄這些位元組屬性,以便後續使用,比如增長字串操作。

  SDS的buff陣列儲存二進位制資料,文字資料以及二進位制流。SDS還相容部分c函式

SDS相關操作API

 

1 SET key value
設定指定 key 的值。
2 GET key
獲取指定 key 的值。
3 GETRANGE key start end
返回 key 中字串值的子字元
4 GETSET key value
將給定 key 的值設為 value ,並返回 key 的舊值(old value)。
5 GETBIT key offset
對 key 所儲存的字串值,獲取指定偏移量上的位(bit)。
6 MGET key1 [key2..]
獲取所有(一個或多個)給定 key 的值。
7 SETBIT key offset value
對 key 所儲存的字串值,設定或清除指定偏移量上的位(bit)。
8 SETEX key seconds value
將值 value 關聯到 key ,並將 key 的過期時間設為 seconds (以秒為單位)。
9 SETNX key value
只有在 key 不存在時設定 key 的值。
10 SETRANGE key offset value
用 value 引數覆寫給定 key 所儲存的字串值,從偏移量 offset 開始。
11 STRLEN key
返回 key 所儲存的字串值的長度。
12 MSET key value [key value ...]
同時設定一個或多個 key-value 對。
13 MSETNX key value [key value ...]
同時設定一個或多個 key-value 對,當且僅當所有給定 key 都不存在。
14 PSETEX key milliseconds value
這個命令和 SETEX 命令相似,但它以毫秒為單位設定 key 的生存時間,而不是像 SETEX 命令那樣,以秒為單位。
15 INCR key
將 key 中儲存的數字值增一。
16 INCRBY key increment
將 key 所儲存的值加上給定的增量值(increment) 。
17 INCRBYFLOAT key increment
將 key 所儲存的值加上給定的浮點增量值(increment) 。
18 DECR key
將 key 中儲存的數字值減一。
19 DECRBY key decrement
key 所儲存的值減去給定的減量值(decrement) 。
20 APPEND key value
如果 key 已經存在並且是一個字串, APPEND 命令將指定的 value 追加到該 key 原來值(value)的末尾。

 

應用場景:

 一般常用在需要計數的場景,比如使用者的訪問次數、熱點文章的點贊轉發數量等等。

//計數器

127.0.0.1:6379> set number 1
OK
127.0.0.1:6379> incr number # 將 key 中儲存的數字值增一
(integer) 2
127.0.0.1:6379> get number
"2"
127.0.0.1:6379> decr number # 將 key 中儲存的數字值減一
(integer) 1
127.0.0.1:6379> get number
"1"

 

參考:redis設計與實現