Redis用到的所有主要數(shù)據(jù)結(jié)構(gòu),簡單動態(tài)字符串(SDS)、雙端列表、字典、跳躍表、整數(shù)集合、壓縮列表。
Redis并沒有直接使用這些數(shù)據(jù)結(jié)構(gòu)來實現(xiàn)鍵值對的數(shù)據(jù)庫,而是基于這些數(shù)據(jù)結(jié)構(gòu)創(chuàng)建了一個對象西永,這個系統(tǒng)包含字符串對象、列表對象、哈希對象、集合對象和有序集合對象這五種類型的對象,每中對象都用到了至少一種我們前面所介紹的數(shù)據(jù)結(jié)構(gòu)。
通過這五種不同類型的對象,Redis可以在執(zhí)行命令之前,根據(jù)對象的類型來判斷一個對象是否可以執(zhí)行給定的命令。使用對象的一個好處是,我們可以針對不同的使用場景,為對象設(shè)置多種不同的數(shù)據(jù)結(jié)構(gòu)實現(xiàn),從而優(yōu)化對象在不同場景下的使用效率。
Redis的對象系統(tǒng)還實現(xiàn)了基于引用計數(shù)技術(shù)的內(nèi)存回收機制,當程序不在使用某個對象的時候,這個對象所占用的內(nèi)存就會被自動釋放;另外,Redis還通過引用計數(shù)技術(shù)實現(xiàn)了對象的共享機制,這一機制可以在適當?shù)臈l件下,通過讓多個數(shù)據(jù)庫鍵共享用一個對象來節(jié)約內(nèi)次。
最后,Redis的對象帶有訪問時間記錄信息,該信息可以用于計算數(shù)據(jù)庫鍵的空轉(zhuǎn)時長,在服務(wù)器啟用了maxmemory功能的情況下,空轉(zhuǎn)時長較大的那些鍵可能會優(yōu)先被服務(wù)器刪除。
8.1 對象的類型與編碼
Redis使用對象來表示數(shù)據(jù)庫中的鍵和值,每次當我們在Redis的數(shù)據(jù)庫中新創(chuàng)建一個鍵值對,我們至少創(chuàng)建兩個對象,一個對象用作鍵值對的鍵,另一個對象用作鍵值對的值。
Redis中的每個對象都由一個redisObject結(jié)構(gòu)表示,該結(jié)構(gòu)中和保存數(shù)據(jù)有關(guān)的三個屬性分別是type屬性、encoding屬性和ptr屬性:
typedef struct redisObject{
//類型
unsigned type:4;
//編碼
unsigned encoding:4;
//指向底層實現(xiàn)數(shù)據(jù)結(jié)構(gòu)的指針
void *ptr;
}
8.1.1 類型
對象的type屬性記錄了對象的類型,這個屬性的值如下
| 類型常量 | 對象的名稱 |
|---|---|
REDIS_STRING |
字符串對象 |
REDIS_LIST |
列表對象 |
REDIS_HASH |
哈希對象 |
REDIS_SET |
集合對象 |
REDIS_ZSET |
有序結(jié)合對象 |
對于Redis數(shù)據(jù)庫保存的鍵值對來說,鍵總是一個字符串對象,而值則可以是String, List, Hash, Set, ZSet對象中的其中一個。
TYPE命令:當我們對一個數(shù)據(jù)庫鍵執(zhí)行TYPE命令時,命令返回的結(jié)果為數(shù)據(jù)庫鍵對應的值對象的類型,而不是鍵對象的類型
8.1.2 編碼和底層實現(xiàn)
對象的ptr指針指向?qū)ο蟮牡讓訉崿F(xiàn)數(shù)據(jù)結(jié)構(gòu),而這些數(shù)據(jù)結(jié)構(gòu)由對象的encoding屬性決定。
encoding屬性記錄了對象所使用的編碼,也就是說這個對象上用了什么數(shù)據(jù)結(jié)構(gòu)作為對象的底層實現(xiàn),屬性如下:
| 編碼常量 | 編碼所對應的底層數(shù)據(jù)結(jié)構(gòu) |
|---|---|
REDIS_ENCODING_INT |
long類型的整數(shù) |
REDIS_ENCODING_EMBSTR |
embstr編碼的簡單動態(tài)字符串 |
REDIS_ENCODING_RAW |
簡單動態(tài)字符串 |
REDIS_ENCODING_HT |
字典 |
REDIS_ENCODING_LINKEDLIST |
雙端列表 |
REDIS_ENCODING_ZIPLIST |
壓縮列表 |
REDIS_ENCODING_INTSET |
整數(shù)集合 |
REDIS_ENCODING_SKIPLIST |
跳躍表 |
每種類型的對象都至少使用了兩種不同的編碼
| 類型 | 編碼 | 對象 |
|---|---|---|
REDIS_STRING |
REDIS_ENCODING_INT |
使用整數(shù)值實現(xiàn)的字符串對象 |
REDIS_STRING |
REDIS_ENCODING_EMBSTR |
使用embstr編碼的簡單動態(tài)字符串實現(xiàn)的字符串對象 |
REDIS_STRING |
REDIS_ENCODING_RAW |
使用簡單動態(tài)字符串實現(xiàn)的字符串對象 |
REDIS_LIST |
REDIS_ENCODING_ZIPLIST |
使用壓縮列表實現(xiàn)的列表對象 |
REDIS_LIST |
REDIS_ENCODING_LINKEDLIST |
使用雙端列表實現(xiàn)的列表對象 |
REDIS_HASH |
REDIS_ENCODING_ZIPLIST |
使用壓縮列表實現(xiàn)的哈希對象 |
REDIS_HASH |
REDIS_ENCODING_HT |
使用字典實現(xiàn)的哈希對象 |
REDIS_SET |
REDIS_ENCODING_INTSET |
使用整數(shù)集合實現(xiàn)的集合對象 |
REDIS_SET |
REDIS_ENCODING_HT |
使用字典實現(xiàn)的集合對象 |
REDIS_ZSET |
REDIS_ENCODING_ZIPLIST |
使用壓縮列表實現(xiàn)的有序集合對象 |
REDIS_ZSET |
REDIS_ENCODING_SKIPLIST |
使用跳躍表實現(xiàn)的有序集合對象 |
OBJECT ENCODING命令:可以查看一個數(shù)據(jù)庫鍵的值對象的編碼:
通過encoding屬性來設(shè)定對象所使用的編碼。而不是為特定類型的對象關(guān)聯(lián)一種固定的編碼,極大地提升了Redis的靈活性,因為Redis可以根據(jù)不同的使用場景來為一個對象設(shè)置不同的編碼,從而優(yōu)化對象在某一場景下的效率。
8.1.3 Key(鍵)命令
1. DEL
DEL key [key ...]
刪除給定的一個或多個key
不存在的key會被忽略
2. DUMP
DUMP key
序列化給定key,并返回被序列化的值,使用RESTORE命令可以將這個值反序列化為Redis鍵
序列化生成的值有以下幾個特點:
- 帶有64為的校驗和,用于檢測錯誤,
RESTORE在進行反序列化之前會先檢查校驗和。 - 值的編碼格式和RDB文件保持一致。
- RDB版本會編碼在序列化值當眾,如果因為Redis的版本不同造成RDB格式不兼容,那么Redis會拒絕為這個值進行反序列操作。
序列化的值不包括任何生存時間信息。
3. EXISTS
EXISTS key
檢查給定的key是否存在
4. EXPIRE
EXPIRE key seconds
為給定的key設(shè)置生存時間,當key過期時,會被自動刪除。
5. EXPIREAT
EXPIREAT key timestamp
EXPIREAT的作用和EXPIRE類似,都用于為key設(shè)置生存時間
不同在于EXPIREAT命令接受的時間參數(shù)是UNIX時間戳
6. KEYS
KEYS pattern
查詢所有符合給定模式pattern的key
KEYS * 匹配數(shù)據(jù)庫中所有的key
KEYS h?llo匹配hello, hallo和hxllo等
KEYS h*llo匹配hllo, heeeeello等
KEYS h[ae]llo匹配hello和hallo,但不匹配hillo。
7. MIGRATE
MIGRATE host port key destination-db timeout [COPY] [REPLACE]
將key原子性地從當前實例傳送到目標實例的指定數(shù)據(jù)庫上,一旦傳送成功,key保證會出現(xiàn)在目標實例上,而當前實例上的key會被刪除。
這個命令是一個原子操作,它在執(zhí)行的時候會阻塞進行遷移的兩個實例,直到以下任意結(jié)果發(fā)生:遷移成功,遷移失敗,等待超時。
命令的內(nèi)部實現(xiàn)是這樣的:它在當前實例對給定key執(zhí)行DUMP命令 ,將它序列化,然后傳送到目標實例,目標實例再使用RESTORE對數(shù)據(jù)進行反序列化,并將反序列化所得的數(shù)據(jù)添加到數(shù)據(jù)庫中;當前實例就像目標實例的客戶端那樣,只要看到RESTORE命令返回OK,它就會調(diào)用DEL刪除自己數(shù)據(jù)庫上的key。
timeout參數(shù)以毫秒為格式,指定當前實例和目標實例進行溝通的最大間隔時間。這說明操作并不一定要在timeout毫秒內(nèi)完成,只是說數(shù)據(jù)傳送的時間不能超過這個timeout數(shù)。
MIGRATE命令需要在給定的時間規(guī)定內(nèi)完成IO操作。如果在傳送數(shù)據(jù)時發(fā)生IO錯誤,或者達到了超時時間,那么命令會停止執(zhí)行,并返回一個特殊的錯誤:IOERR。
當IOERR出現(xiàn)時,有以下兩種可能:
-
key可能存在于兩個實例 -
key可能只存在于當前實例
唯一不可能發(fā)生的情況就是丟失key,因此,如果一個客戶端執(zhí)行MIGRATE命令,并且不幸遇上IOERR錯誤,那么這個客戶端唯一要做的就是檢查自己數(shù)據(jù)庫上的key是否已經(jīng)被正確地刪除。 -
COPY:不移除源實例上的key。 -
REPLACE:替換目標實例上已存在的key。
8. MOVE
MOVE key db
將當前數(shù)據(jù)庫的key移動到給定的數(shù)據(jù)庫db當中。
如果當前數(shù)據(jù)庫(源數(shù)據(jù)庫)和給定數(shù)據(jù)庫(目標數(shù)據(jù)庫)有相同名字的給定key,或者key不存在于當前數(shù)據(jù)庫,那么MOVE沒有任何效果。
因此,也可以利用這一特性,將MOVE當作鎖(locking)原語(primitive)。
9. OBJECT
OBJECT subcommand [arguments [arguments]]
OBJECT命令允許從內(nèi)部察看給定key的Redis對象。
OBJECT命令有多個子命令:
OBJECT REFCOUNT <key>返回給定key引用所儲存的值的次數(shù)。此命令主要用于除錯。
OBJECT ENCODING <key>返回給定key鎖儲存的值所使用的內(nèi)部表示(representation)。
OBJECT IDLETIME <key>返回給定key自儲存以來的空閑時間(idle, 沒有被讀取也沒有被寫入),以秒為單位。
10. PERSIST
PERSIST key
移除給定key的生存時間,將這個key從『易失的』(帶生存時間key)轉(zhuǎn)換成『持久的』(一個不帶生存時間、永不過期的key)。
11. PEXPIRE
PEXPIRE key milliseconds
這個命令和EXPIRE命令的作用類似,但是它以毫秒為單位設(shè)置key的生存時間,而不像EXPIRE命令那樣,以秒為單位。
12. PEXPIREAT
PEXPIREAT key milliseconds-timestamp
這個命令和EXPIREAT命令類似,但它以毫秒為單位設(shè)置key的過期unix時間戳,而不是像EXPIREAT那樣,以秒為單位。
13. PTTL
PTTL key
這個命令類似于TTL命令,但它以毫秒為單位返回key的剩余生存時間,而不是像TTL命令那樣,以秒為單位。
14. RANDOMKEY
RANDOMKEY
從當前數(shù)據(jù)庫中隨機返回(不刪除)一個key。
15. RENAME
RENAME key newkey
將key改名為newkey。
當key 和newkey相同,或者key不存在時,返回一個錯誤。 當newkey已經(jīng)存在時,RENAME`命令將覆蓋舊值。
16. RENAMENX
RENAMENX key newkey
當且僅當newkey不存在時,將key改名為newkey。
當key不存在時,返回一個錯誤。
17. RESTORE
RESTORE key ttl serialized-value [REPLACE]
反序列化給定的序列化值,并將它和給定的key關(guān)聯(lián)。
18. SORT
SORT key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]] [ASC | DESC] [ALPHA] [STORE destination]
返回或保存給定列表、集合、有序集合key中經(jīng)過排序的元素。
排序默認以數(shù)字作為對象,值被解釋為雙精度浮點數(shù),然后進行比較。
19. TTL
TTL key
以秒為單位,返回給定key的剩余生存時間(TTL, time to live)。
20. TYPE
TYPE key
返回key所儲存的值的類型。
返回值:
-
none(key不存在) -
string(字符串) -
list(列表) -
set(集合) -
zset(有序集) -
hash(哈希表)
21. SCAN
SCAN cursor [MATCH pattern] [COUNT count]