Redis是工作中使用比較多的中介軟體,它支援豐富的資料結構,擁有極強的讀寫效能,tps可以達到10w+。
今天這篇文章來分析和總結String型別也是使用最多的一種資料結構之一。本文是基於redis5.0進行分析。【相關推薦:Redis視訊教學】
set key value [EX seconds] [PX milliseconds] [NX|XX]
1、set是語法,key是指定名稱, value是需要儲存的值
2、EX 指定過期的秒時間,PX指定過期的毫秒時間
3、NX:只有key不存在的時候,才設定成功
4、XX:只有key存在的時候,才設定成功
總結:5.0支援set命令指定過期時間和不存在的時候才設定成功,也就是通過一條命令就可以實現分散式鎖加鎖的功能,以前的版本設定key和設定過期時間需要分成兩個命令,原子性保證難度更大。
1、熱點資料快取,分散式session
2、Setnx 分散式鎖
3、incr 計數器
4、Incr 全域性id
5、Incr 限流
6、bit 操作,點陣圖功能,線上使用者統計 0/1標記
整型,字元型,float(單浮點型)
在Redis中,資料儲存在一個RedisObject類中
typedef struct redisObject { //這個型別可以是string,也可以是hash,zset等等 unsigned type:4; unsigned encoding:4; //記錄lru,lfu淘汰演演算法依賴的存取時間和存取頻率 unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or * LFU data (least significant 8 bits frequency * and most significant 16 bits access time). */ //參照計數器 int refcount; //指向真實資料結構物件 void *ptr; } robj;
對於String,Redis自定義了一種簡單動態字串的資料結構來儲存字串數。
原始碼實現:多種資料結構,分別表示可以儲存不同長度的字串。
len:代表已經使用的長度
alloc:分配的總記憶體大小
flags:代表儲存型別
buf[]:實際的資料
1、embstr的RedisObject,SDS記憶體在一塊,只要建立時分配一次記憶體
,銷燬時釋放一次記憶體
,查詢方便
2、raw則RedisObject,SDS記憶體不在一塊,需要建立時分配兩次記憶體
,銷燬時釋放兩次記憶體
3、embstr的結構,決定了他需要增加長度時,RedisObject,SDS都需要重新分配記憶體。因此embstr編碼的資料是不能修改的,唯讀的
。
1、int型別的資料不再是int型別,轉成raw
2、長度大於2^63-1轉成embstr
3、embstr字元超過44位元組,轉成raw
1、二進位制安全的
可以儲存圖片 整形,浮點型
2、String 的三種編碼,充分利用記憶體,提高記憶體利用率
int
儲存8個位元組長整形 long ,2^63-1Embstr
embstr格式的SDS simple Dynamic String 記憶體空間是連續的,唯讀的,只要執行修改就會轉成rawRaw
,SDS,儲存大於44個位元組的字串3、不用擔心記憶體溢位,sds具備自動擴容能力
4、獲取字串長度時間複雜度O(1)
,儲存了len屬性
5、通過空間預分配
和惰性空間釋放
防止多次分配記憶體
6、判斷是否結束使用len屬性,可以包含'\0',操作字串。
1、需要預先分配記憶體,可能記憶體溢位
2、獲取長度需要遍歷陣列,時間複雜度O(n)
3、字元陣列長度變化,需要記憶體重分配
4、c的字元陣列中,'\0'代表判斷結束。二進位制資料儲存不安全
,不能儲存圖片,視訊等。
通過原始碼分析,擴容策略是字串在長度小於 SDS_MAX_PREALLOC 之前,擴容空間採用加倍策略,也就是保留 100% 的冗餘空間。當長度超過 SDS_MAX_PREALLOC 之後,為了避免加倍後的冗餘空間過大而導致浪費,每次擴容只會多分配 SDS_MAX_PREALLOC大小的冗餘空間。
惰性空間釋放用於優化 SDS 的字串縮短操作:當 SDS 的 API 需要縮短 SDS 儲存的字串時, 程式並不立即使用記憶體重分配來回收縮短後多出來的位元組, 而是使用 free 屬性將這些位元組的數量記錄起來,並等待將來使用。
//僅僅設定長度,沒有真正清除資料 void sdsclear(sds s) { //單純設定長度為0 sdssetlen(s, 0); //第一個字元設定為結束符 s[0] = '\0'; }
真正的清除空間
sds sdsRemoveFreeSpace(sds s) { struct sdshdr *sh; sh = (void*) (s-(sizeof(struct sdshdr))); // 進行記憶體重分配,讓 buf 的長度僅僅足夠儲存字串內容 sh = zrealloc(sh, sizeof(struct sdshdr)+sh->len+1); // 空餘空間為 0 sh->free = 0; return sh->buf; }
以上便是關於string的知識點記錄,string的設計很多地方都非常巧妙,比如不同的結構體儲存不同長度的字串,不同編碼型別儲存不同長度的字串,
空間預分配,空間惰性釋放等,從儲存結構,編碼型別,記憶體分配策略和回收策略,作者都從效能方面做了非常多的考量設計,可想而知這也是redis為什麼效能極高的原因,工作中也要學習這種追求極致效能的優良風格和設計風格。
更多程式設計相關知識,請存取:!!
以上就是Redis資料型別學習之聊聊String原理的詳細內容,更多請關注TW511.COM其它相關文章!