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