redis 基礎資料類型
Sting類型 :
Redis 的字串是動態字串,是可以修改的字串,內部結構實現上類似於 Java 的 ArrayList,採用預分配冗餘空間的方式來減少記憶體的頻繁分配,中所示,內部為當前字串實際分配的空間 capacity 一般要高於實際字串長度 len。當字串長度小於 1M 時,擴容都是加倍現有的空間,如果超過 1M,擴容時一次只會多擴 1M 的空間。需要注意的是字串最大長度為 512M。
操作命令:
set key value
get key
exists key
del key
大量設定
mset key1 value1 key2 value2 key3 value3
mget key1 key2 key3
到期設定
expire key1 5 5秒後到期
setex key 5 value #5s 後到期,等價於 set+expire
setnx key value 沒有key 返回1設定成功,key已存在 返回0
計數
incr key # 將key對應的value值 遞增加1 ,遞增若超過最大數值則報錯 (incrby age 5 按5遞增)
list類型 :
Redis 的列表相當於 Java 語言裡面的 LinkedList,注意它是鏈表而不是數組。這意味著 list 的插入和刪除操作非常快,時間複雜度為 O(1),但是索引定位很慢,時間複雜度為 O(n),這點讓人非常意外。
當列表彈出了最後一個元素之後,該資料結構自動被刪除,記憶體被回收。
操作命令:
rpush key value1 value2 value3 存放元素 value1在最左邊
llen key 查詢list長度
lpop key 從左邊取出對應的key的值,取出就沒有了 (右邊進左邊出:隊列 )
rpop key 從右邊取出對應的key的值,取出就沒有了 (右邊進右邊出:棧 )
慢操作
lindex 相當於 Java 鏈表的get(int index)方法,它需要對鏈表進行遍曆,效能隨著參數index增大而變差,
index可以為負數,index=-1表示倒數第一個元素,同樣index=-2表示倒數第二個元素。
lindex key 1 取出下標為1,也就是放進去的第二個元素 O(n) 慎用
lrange key 0 -1 # 擷取所有元素,O(n) 慎用
ltrim key 1 -1 為了截取下標為1 一直到最後 若區間為負數則清空列表 ltrim key 1 0
快速列表
首先在列表元素較少的情況下會使用一塊連續的記憶體儲存,這個結構是ziplist,也即是壓縮列表。它將所有的元素緊挨著一起儲存,分配的是一塊連續的記憶體。當資料量比較多的時候才會改成quicklist。因為普通的鏈表需要的附加指標空間太大,會比較浪費空間,而且會加重記憶體的片段化。比如這個列表裡存的只是 int 類型的資料,結構上還需要兩個額外的指標 prev 和 next 。所以 Redis 將鏈表和 ziplist 結合起來組成了 quicklist。也就是將多個 ziplist 使用雙向指標串起來使用。
hash (字典):數組 + 鏈表二維結構 值只能是字串
Java 的 HashMap 在字典很大時,rehash 是個耗時的操作,需要一次性全部 rehash。Redis 為了高效能,不能堵塞服務,所以採用了漸進式 rehash 策略。漸進式 rehash 會在 rehash 的同時,保留新舊兩個hash結構,查詢時會同時查詢兩個hash結構,然後在後續的定時任務中以及 hash 操作指令中,循序漸進地將舊 hash 的內容一點點遷移到新的 hash 結構中。當搬遷完成了,就會使用新的hash結構取而代之。
hash可以儲存一個結構體部分欄位資料,比如String類型資料若一次序列化整個結構儲存導致網路流量浪費。hash也有缺點儲存消耗大於單個字串。根據實際情況來選擇 hash還是string來儲存
操作命令:
hset books java "think in java" # 命令列的字串如果包含空格,要用引號括起來 若是更新操作直接覆蓋
hget books java
hgetall books
批量 set
hmset books java "effective java" python "learning python" golang "modern golang programming"
計數
hincrby user-laoqian age 1
應用:存放資料對象
set類型:(集合)
Redis 的集合相當於 Java 語言裡面的 HashSet,它內部的索引值對是無序的唯一的。它的內部實現相當於一個特殊的字典,字典中所有的 value 都是一個值NULL。當集合中最後一個元素移除之後,資料結構自動刪除,記憶體被回收。
操作命令:
sadd key value 成功返回1 失敗返回0
sadd key value1 value2 成功返回2 失敗返回0
smembers key # 注意順序,和插入的並不一致,因為 set 是無序的 查出所有
sismember key value # 查詢某個 value 是否存在,相當於 contains(o) 存在返回1 不存在返回0
scard books # 擷取長度相當於 count()
spop books # 彈出一個 隨機
應用 set 結構可以用來儲存活動中獎的使用者識別碼,因為有去重功能,可以保證同一個使用者不會中獎兩次。
zset類型: (有序列表)
zset 內部的排序功能是通過「跳躍列表」資料結構來實現的,它的結構非常特殊,也比較複雜。
操作命令:
zadd key score value 按score來排序
zrange key 0 -1 # 按 score 排序列出,參數區間為排名範圍 全部取出
zrevrange key 0 -1 # 按 score 逆序列出,參數區間為排名範圍
zcard key # 擷取長度相當於 count()
zscore key value # 擷取指定 value 的 score # 內部 score 使用 double 類型進行儲存,所以存在小數點精度問題
zrank key value # 排名
zrangebyscore key 0 8.91 # 根據分值區間遍曆 zset
zrangebyscore books -inf 8.91 withscores # 根據分值區間 (-∞, 8.91] 遍曆 zset,同時返回分值。inf 代表 infinite,無窮大的意思。
zrem key value # 刪除 value
應用:zset 可以用來存粉絲列表,value 值是粉絲的使用者識別碼,score 是關注時間。我們可以對粉絲列表按關注時間進行排序。
zset 還可以用來儲存學生的成績,value 值是學生的 ID,score 是他的考試成績。我們可以對成績按分數進行排序就可以得到他的名次。
容器型資料結構的通用規則:
list/set/hash/zset 這四種資料結構是容器型資料結構,它們共用下面兩條通用規則:
create if not exists
如果容器不存在,那就建立一個,再進行操作。比如 rpush 操作剛開始是沒有列表的,Redis 就會自動建立一個,然後再 rpush 進去新元素。
drop if no elements
如果容器裡元素沒有了,那麼立即刪除元素,釋放記憶體。這意味著 lpop 操作到最後一個元素,列表就消失了。
到期時間:
Redis 所有的資料結構都可以設定到期時間,時間到了,Redis 會自動刪除相應的對象。需要注意的是到期是以對象為單位,比如一個 hash 結構的到期是整個 hash 對象的到期,而不是其中的某個子 key。
還有一個需要特別注意的地方是如果一個字串已經設定了到期時間,然後你調用了 set 方法修改了它,它的到期時間會消失。