Redis的常見數據類型
Redis 提供了 5 種數據結構,理解每種數據結構的特點對于 Redis 開發運維?常重要,同時掌握每
種數據結構的常?命令,會在使? Redis 的時候做到游刃有余。
預備
????????在正式介紹 5 種數據結構之前,了解?下 Redis 的?些全局命令、數據結構和內部編碼、單線程 命令處理機制是?分必要的,它們能為后?內容的學習打下?個良好的基礎。
主要體現在兩個方面
- Redis的命令有上百個,只是死記硬背比較困難,但是如何理解Redis的一些機制,會發現這些命令有很強的通用性。
- Redis不是萬金油,有些數據結構和命令必須在特定的場景下使用,一旦使用不當可能會對Redis自身造成致命傷害
全局命令
? ? ? ? Redis有5種數據結構,但是它們都是對值而言,不過對于鍵,倒是有一些通用的命令。
KEYS
返回所有滿足樣式的key。支持如下
? h?llo 匹配 hello , hallo 和 hxllo
? h*llo 匹配 hllo 和 heeeello
? h[ae]llo 匹配 hello 和 hallo 但不匹配 hillo
? hello 匹配 hallo , hbllo , ... 但不匹配 hello
? h[a-b]llo 匹配 hallo和 hbllo
舉例如下

EXISTS
判斷某個key是否存在
舉個例子

DEL
刪除指定的key
舉個例子

EXPIRE
?????????為執行的key添加過期時間
舉個例子
TTL
獲取指定key的剩余時間


TYPE
返回key對應的數據類型
返回值: none , string , list , set , zset , hash and stream
數據結構和內部編碼
type 命令實際返回的就是當前鍵的數據結構類型,它們分別是:string(字符串)、list(列
表)、hash(哈希)、set(集合)、zset(有序集合),但這些只是 Redis 對外的數據結構

Redis的數據結構和內部編碼
數據結構 | 內部編碼 |
string | raw |
int |
embstr |
hash | hashtable |
ziplist |
list | linkedlist |
ziplist |
set | hashtable |
intset |
zset | skiplist |
ziplist |
可以看到每種數據結構都有?少兩種以上的內部編碼實現,例如 list 數據結構包含了 linkedlist 和
ziplist 兩種內部編碼。同時有些內部編碼,例如 ziplist,可以作為多種數據結構的內部實現,可以通過 object encoding 命令查詢內部編碼,舉例:
Redis這樣設計有很大的好處:
?1) 可以改進內部編碼,?對外的數據結構和命令沒有任何影響,這樣?旦開發出更優秀的內部編碼, ?需改動外部數據結構和命令,例如 Redis 3.2 提供了 quicklist,結合了 ziplist 和 linkedlist 兩者的優勢,為列表類型提供了?種更為優秀的內部編碼實現,?對??來說基本?感知
?2)多種內部編碼實現可以在不同場景下發揮各?的優勢,例如 ziplist ?較節省內存,但是在列表元素 ?較多的情況下,性能會下降,這時候 Redis 會根據配置選項將列表類型的內部實現轉換為 linkedlist,整個過程??同樣?感知。
單線程架構
????????Redis 使?了單線程架構來實現?性能的內存數據庫服務,本節?先通過多個客?端命令調?的例?說明 Redis 單線程命令處理機制,接著分析 Redis 單線程模型為什么性能如此之?,最終給出為什么理解單線程模型是使?和運維 Redis 的關鍵。
簡介
宏觀上同時要求服務的客戶端
微觀上客戶端發送命令的時間是有先后次序的


為什么單線程可以這么快
通常來講,單線程處理能?要?多線程差,例如有 10 000 公?貨物,每輛?的運載能?是每次
200 公?,那么要 50 次才能完成;但是如果有 50 輛?,只要安排合理,只需要依次就可以完成任務。那么為什么 Redis 使?單線程模型會達到每秒萬級別的處理能?呢?可以將其歸結為三點
- 純內存訪問。Redis將所有的數據放在內存中,內存的響應時長大約是100ns,這是Redis達到每秒萬級別的重要基礎。
- 非阻塞IO。Redis使用epoll作為IO多路復用技術的實現,在加上Redis自身的事件處理模型將epoll中的鏈接、讀寫、關閉都轉換成事件,不在網絡IO上浪費過多的事件。
- 單線程避免了線程切換和競態產生的消耗。單線程可以簡化數據結構和算法的視線,讓程序模型更加簡單;其次避免了多線程中在線程競爭同一份共享資源時帶來的切換的等待消耗。

雖然單線程給 Redis 帶來很多好處,但還是有?個致命的問題:對于單個命令的執?時間都是有
要求的。如果某個命令執?過?,會導致其他命令全部處于等待隊列中,遲遲等不到響應,造成客戶端的阻塞,對于 Redis 這種?性能的服務來說是?常嚴重的,所以 Redis 是?向快速執?場景數據庫。
String字符串
字符串類型是 Redis 最基礎的數據類型,關于字符串需要特別注意:
- Redis中的所有的鍵的類型都是字符串類型,而且其他幾種數據類型也都是在字符串類似基礎上構建的。
- 字符串的值實際可以是字符串,包含一般格式的字符串或者類似JSON、XML格式的字符串,數字。可以使整型或者浮點型;甚至是二進制流數據
常見命令
set
將string類型的value設置到key中。如果key之前存在,就修改;不存在就創建。
SET key value [expiration EX seconds|PX milliseconds] [NX|XX]
SET命令支持多種選項來影響它的行為
- EX seconds —— 使用秒為單位來設置key的過期時間
- PX milliseconds——使用毫秒作為單位設置key的過期時間
- NX——只有key不存在的時候才設置
- XX——只有key存在的時候才設置
舉個例子

get
獲取 key 對應的 value。如果 key 不存在,返回 nil。如果 value 的數據類型不是 string,會報錯
GET key

MGET
一次性獲取多個 key 的值。如果對應的 key 不存在或者對應的數據類型不是 string,返回 nil。
MGET key [key ...]
舉個例子

mset
一次性設置多個key的值
MSET key value [key value ...]
舉個例子

setnx
設置 key-value 但只允許在 key 之前不存在的情況下。
SETNX key value

計數命令
incr
將 key 對應的 string 表?的數字加?。如果 key 不存在,則視為 key 對應的 value 是 0。如果 key 對應的 string 不是?個整型或者范圍超過了 64 位有符號整型,則報錯。
incrby
????????將 key 對應的 string 表?的數字加上對應的值。如果 key 不存在,則視為 key 對應的 value 是 0。如果 key 對應的 string 不是?個整型或者范圍超過了 64 位有符號整型,則報錯。
INCRBY key decrement
舉個例子

DECR
????????將 key 對應的 string 表?的數字減?。如果 key 不存在,則視為 key 對應的 value 是 0。如果 key 對應的 string 不是?個整型或者范圍超過了 64 位有符號整型,則報錯
DECR key

DECYBY
將 key 對應的 string 表?的數字減去對應的值。如果 key 不存在,則視為 key 對應的 value 是 0。如果 key 對應的 string 不是?個整型或者范圍超過了 64 位有符號整型,則報錯。
DECRBY key decrement
INCRBYFLOAT
將 key 對應的 string 表?的浮點數加上對應的值。如果對應的值是負數,則視為減去對應的值。如果key 不存在,則視為 key 對應的 value 是 0。如果 key 對應的不是 string,或者不是?個浮點數,則報錯。允許采?科學計數法表?浮點數。
INCRBYFLOAT key increment

其他命令
append
如果 key 已經存在并且是?個 string,命令會將 value 追加到原有 string 的后邊。如果 key 不存在,則效果等同于 SET 命令。
APPEND KEY VALUE

getrange
返回 key 對應的 string 的?串,由 start 和 end 確定(左閉右閉)。可以使?負數表?倒數。-1 代表倒數第?個字符,-2 代表倒數第?個,其他的與此類似。超過范圍的偏移量會根據 string 的?度調整成正確的值
GETRANGE key start end

SETRANGE
覆蓋字符串的?部分,從指定的偏移開始。
SETRANGE key offset value

STRLEN
獲取 key 對應的 string 的?度。當 key 存放的類似不是 string 時,報錯。
STRLEN key

結算

內部編碼
字符串類型的內部編碼有 3 種:
- int:8個字節的整型
- embstr:小于等于39個字節的字符串
- raw:大于39個字節的字符串
Redis 會根據當前值的類型和?度動態決定使?哪種內部編碼實現。