一、Redis簡介 Redis是一款基於key-value的高性能NoSQL資料庫,開源免費,遵守BSD協議。支持string(字元串) 、 hash(哈希) 、list(列表) 、 set(集合) 、 zset(有序集合)等數據結構,除此之外還提供了鍵過期、發佈訂閱、Lua腳本、事務、流水線(Pi ...
一、Redis簡介
Redis是一款基於key-value的高性能NoSQL資料庫,開源免費,遵守BSD協議。支持string(字元串) 、 hash(哈希) 、list(列表) 、 set(集合) 、 zset(有序集合)等數據結構,除此之外還提供了鍵過期、發佈訂閱、Lua腳本、事務、流水線(Pipeline)、持久化和主從複製等功能,並通過 Redis 哨兵(Sentinel)和 Redis Cluster(集群)自動分區提供了高可用性。可用於資料庫、緩存和消息隊列等多種場景。
二、數據結構
Redis 是一個key-value資料庫,即數據存儲是以一個唯一的 key 對應一個 value,value 有 5 種基礎數據結構: string (字元串)、 hash (哈希) 、 list (列表)、 set (集合)和 zset (有序集合)。
1、string(字元串)
string 的值可以是字元串(簡單的、以及json、xml格式的)、數字,甚至是二進位數據(圖片、音頻、視頻), 最大能存儲512MB。Redis 的字元串是動態的,是可以修改的,當字元串長度小於 1M 時,擴容都是加倍現有的空間,如果超過 1M,擴容時一次只會多擴 1M 的空間。
相關命令
(1)設置值與獲取值
set key value 設置指定 key 的值
get key 獲取指定 key 的值
批量設置與獲取
mset key value [key value ...] 同時設置一個或多個 key-value 對。
msetlen key value [key value ...] 同時設置一個或多個 key-value 對,當且僅當所有給定 key 都不存在。
mget key1 [key2..] 獲取所有(一個或多個)給定 key 的值。
從 Redis 2.6.12 開始 set 命令支持一些選項修改其行為:
·ex seconds:設置 key 秒級過期時間。
·px milliseconds:設置 key 毫秒級過期時間。
·nx:只有 key 不存在時,才可以設置成功。
·xx:只有 key 存在時,才可以設置成功。
用法:set key value [ex seconds] [px milliseconds] [nx|xx]
同時redis也有相關命令實現以上行為:
setex key seconds value 將值 value 關聯到 key ,並將 key 的過期時間設為 seconds (以秒為單位)。
psetex key milliseconds value 這個命令和 SETEX 命令相似,但它以毫秒為單位設置 key 的生存時間,而不是像 SETEX 命令那樣,以秒為單位。
setnx key value 只有在 key 不存在時設置 key 的值。
由於以上三個命令可以使用 set 命令選項替代,所以可能會被廢棄,並最終被刪除。
(2)自增自減
incr key 將 key 中儲存的數字值增一。
decr key 將 key 中儲存的數字值減一。
incrby key increment 將 key 所儲存的值加上給定的增量值(increment)。
decrby key decrement key 所儲存的值減去給定的減量值(decrement) 。
如果 key 不存在,那麼 key 的值會先被初始化為 0 ,然後再執行操作。
如果值包含錯誤的類型,或字元串類型的值不能表示為數字,那麼返回一個錯誤。
以上操作的值僅限於 64 位有符號整數。
incrbyfloat key increment 將 key 所儲存的值加上給定的浮點增量值(increment) 。
(3)其他命令
strlen key 返回 key 所儲存的字元串值的長度(實際是位元組長度)。
getset key value 將給定 key 的值設為 value ,並返回 key 的舊值(old value)。
append key value 如果 key 已經存在並且是一個字元串, APPEND 命令將 value 追加到 key 原來的值的末尾。
setrange key offset value 用 value 參數覆寫給定 key 所儲存的字元串值,從偏移量 offset 開始。
getrange key start end 返回 key 中字元串值的子字元。
內部編碼
int:8個位元組的長整型。
embstr:小於等於44個位元組的字元串。
raw:大於44個位元組的字元串。
應用場景
緩存(例如可以將用戶信息序列化成json字元串存儲)、鎖(set nx、setnx)、計數器(incr、incrby、decr、decrby)等
2、hash (哈希)
hash 的值本身又是一個鍵值對結構,如下圖所示,這樣的結構特別適合用於存儲對象。
相關命令
(1)設置與獲取
hset key field value 將哈希表 key 中的欄位 field 的值設為 value 。
hget key field 獲取存儲在哈希表中指定欄位的值
hmset key field1 value1 [field2 value2 ] 同時將多個 field-value (域-值)對設置到哈希表 key 中。
hmget key field1 [field2] 獲取所有給定欄位的值
hgetall key 獲取在哈希表中指定 key 的所有欄位和值
hsetnx key field value 只有在欄位 field 不存在時,設置哈希表欄位的值。
使用hgetall時,如果哈希元素個數比較多,會存在阻塞Redis的可能。這時可以使用hscan命令,該命令會漸進式遍歷哈希結構
hscan key cursor [MATCH pattern] [COUNT count] 迭代哈希表中的鍵值對。
如果要獲取hash 表中所以的欄位或值,可以使用如下命令:
hkeys key 獲取所有哈希表中的欄位
hvals key 獲取哈希表中所有值
(2)自增
hincrby key field increment 為哈希表 key 中的指定欄位的整數值加上增量 increment 。
hincrbyfloat key field increment 為哈希表 key 中的指定欄位的浮點數值加上增量 increment 。
(3)其他命令
hlen key 獲取哈希表中欄位的數量
hexists key field 查看哈希表 key 中,指定的欄位是否存在。
hdel key field2 [field2] 刪除一個或多個哈希表欄位
當 hash 移除了最後一個元素之後,該數據結構自動被刪除,記憶體被回收。
內部編碼
·ziplist(壓縮列表):一塊連續的記憶體空間,元素之間沒有任何冗餘空隙,比較節省記憶體。
當哈希類型元素個數小於hash-max-ziplist-entries配置(預設512個),且所有值都小於hash-max-ziplist-value配置(預設64位元組)時使用。
·hashtable(哈希表):相對ziplist占用了更多的記憶體,但它的讀寫時間複雜度為O(1)。
應用場景
hash 結構也可以用來存儲用戶信息,不同於 string 結構每次都需要序列化和反序列化(存在一定開銷),hash 可以對每個欄位進行單獨操作,但是 hash 結構使用 hashtable 編碼時會消耗更多記憶體,請根據實際情況取捨。
3、list (列表)
list 列表是簡單的字元串列表,按照插入順序排序,每一個字元串就是一個元素,元素可以重覆。你可以從兩端對列表進行插入和彈出操作,還可以根據索引獲取元素或者指定範圍內的元素。存儲結構如下圖所示
相關命令
(1)添加元素
lpush key value1 [value2] 從列表左邊添加一個或多個元素
rpush key value1 [value2] 從列表右邊添加一個或多個元素
lpushx key value 從列表左邊添加一個或多個元素,列表不存在時操作無效
rpushx key value 從列表右邊添加一個或多個元素,列表不存在時操作無效
linsert key before|after pivot value 在列表中指定元素前或者後插入元素
(2)修改元素
lset key index value 通過索引設置列表元素的值
(3)查找元素
lindex key index 通過索引獲取列表中的元素
lrange key start stop 獲取列表指定範圍內的元素
llen key 獲取列表長度
(4)刪除元素
lpop key 移出並獲取列表左邊第一個元素
rpop key 移出並獲取列表右邊第一個元素
blpop key1 [key2 ] timeout 移出並獲取列表左邊第一個元素, 如果列表沒有元素會阻塞列表直到等待超時(s)或發現可彈出元素為止。
brpop key1 [key2 ] timeout 移出並獲取列表右邊第一個元素, 如果列表沒有元素會阻塞列表直到等待超時或發現可彈出元素為止。
rpoplpush source destination 移除列表的右邊第一個元素,並將該元素添加到另一個列表的左邊並返回
brpoplpush source destination timeout 移除列表的右邊第一個元素,並將該元素添加到另一個列表的左邊並返回; 如果列表沒有元素會阻塞列表直到等待超時或發現可彈出元素為止。
lrem key count value 根據參數 count 的值,移除列表中與參數 value 相等的元素
ltrim key start stop 對一個列表進行修剪(trim),就是說,讓列表只保留指定區間內的元素,不在指定區間之內的元素都將被刪除。
補充:
blpop和brpop是lpop和rpop的阻塞版本,如果列表為空時,它會等待timeout後返回,如果timeout=0,客戶端會被一直阻塞直到有新的元素添加進來。列表不為空時客戶端會立即返回。
lrem命令根據count的不同有三種情況:
·count>0,從左到右,刪除count個 value 元素。
·count<0,從右到左,刪除count絕對值個 value 元素。
·count=0,刪除所有與 value 相同的元素。
當列表彈出了最後一個元素之後,該數據結構自動被刪除,記憶體被回收。
內部編碼
·ziplist(壓縮列表):當列表的元素個數小於list-max-ziplist-entries配置(預設512個) , 同時列表中每個元素的值都小於list-max-ziplist-value配置時(預設64位元組) 時使用該編碼。
·linkedlist(鏈表):普通的雙向鏈表,帶有prev和next指針,占用了更多的記憶體,獲取某個節點的前置節點和後置節點的複雜度都是O(1)。
·quicklist(快速列表):Redis 3.2 版本提供,結合了 ziplist 和 linkedlist 兩者的優勢,之後 list 都採用該編碼。
應用場景
普通隊列(lpush+rpop)、消息隊列(lpush+brpop)、分頁(lrange)等。
4、set (集合)
set 是一種無序的集合,並且不允許有重覆元素。支持多個集合取交集、並集、差集。結構如下
相關命令
(1)添加
sadd key member1 [member2] 向集合添加一個或多個元素,返回添加成功的個數
(2)刪除
spop key 刪除並返回集合中的一個隨機元素,Redis從3.2版本開始支持[count]參數
srem key member1 [member2] 刪除集合中一個或多個元素
smove source destination member 將 member 元素從 source 集合移動到 destination 集合
當集合中最後一個元素刪除之後,數據結構自動刪除,記憶體被回收。
(3)獲取、查找
scard key 獲取集合的元素個數
smembers key 返回集合中的所有元素
srandmember key [count] 返回集合中一個或多個隨機數
sismember key member 判斷 member 元素是否是集合 key 的元素
sscan key cursor [MATCH pattern] [COUNT count] 迭代集合中的元素
(4)差集、並集、交集
sdiff key1 [key2] 返回給定所有集合的差集
sunion key1 [key2] 返回所有給定集合的並集
sinter key1 [key2] 返回給定所有集合的交集
sdiffstore destination key1 [key2] 返回給定所有集合的差集並存儲在 destination 中sinter
sunionstore destination key1 [key2] 所有給定集合的並集存儲在 destination 集合中
sinterstore destination key1 [key2] 返回給定所有集合的交集並存儲在 destination 中
內部編碼
·intset(整數集合): 一個整數集合, 占用記憶體較少,只能存儲整數類型的數據。當集合中的元素都是整數且元素個數小於set-maxintset-entries配置(預設512個) 時使用。
·hashtable(哈希表):當 intset 編碼無法滿足時使用。
應用場景
打標簽、投票、抽獎、社交(例如共同的好友、微博共同的關註)等。
5、zset (有序集合)
zset 和 set 不同的是每個元素都會關聯一個double類型的分數(score)。redis正是通過分數來為集合中的元素進行排序。有序集合的元素同樣不允許重覆,但分數(score)卻可以重覆。結構如下
相關命令
(1)添加、自增
zadd key score1 member1 [score2 member2] 向有序集合添加一個或多個元素,或者更新已存在元素的分數。被成功添加的新元素的數量,不包括那些被更新的、已經存在的元素。
從 Redis 3.0.2開始,zadd命令可以添加如下選項:
·nx: 元素不存在時才能設置成功。
·xx: 元素存在時才能設置成功。
·ch: 返回發生變化元素的數量(包括新添加的和被更新的元素)
·incr: 對 score 做增加, 等同於 zincrby 命令。
zincrby key increment member 有序集合中對指定元素的分數加上增量 increment
從 Redis 2.4 版本開始, zadd 命令每次可以添加多個元素
(2)統計數量
zcard key 獲取有序集合的元素數量
zcount key min max 計算在有序集合中指定區間分數的元素數量
zlexcount key min max 在有序集合中計算指定字典區間內元素數量
zlexcount命令說明:
元素名稱前需要加 [ 符號作為開頭, [ 符號與元素之間不能有空格
可以使用 - 和 + 表示得分最小值和最大值
min 和 max 不能反, max 放前面 min放後面會導致返回結果為0
計算數量時,參數 min 和 max 的位置也計算在內。
(3)查找
zscore key member 返回有序集中指定元素的分數值
zrangebylex key min max [LIMIT offset count] 通過字典區間返回有序集合的元素
zrank key member 返回有序集合中指定元素的索引
zrevrank key member 返回有序集合(按分數從高到低排序時)中指定元素的索引
zrange key start stop [WITHSCORES] 通過索引區間返回有序集合成指定區間內的元素
zrevrange key start stop [WITHSCORES] 通過索引區間返回有序集合成指定區間內的元素,分數從高到底
zrangebyscore key min max [WITHSCORES] [LIMIT offset count] 通過分數返回有序集合指定區間內的元素
zrevrangebyscore key max min [WITHSCORES] [LIMIT offset count] 通過分數返回有序集合指定區間內的元素,分數從高到低排序
參數說明:
預設情況下,min和max區間的取值使用閉區間(小於等於或大於等於),你也可以通過給參數前增加“(”符號來使用可選的開區間(小於或大於)。min和max也可以是-inf和+inf,代表無限小和無限大。
[LIMIT offset count]:offset代表查找的起始位置,count代表返回的元素個數
zscan key cursor [MATCH pattern] [COUNT count] 迭代有序集合中的元素(包括元素成員和元素分值)
首次迭代 設置 cursor 為0,再次迭代時以上次返回的游標為參數
(4)刪除
zrem key member [member ...] 刪除有序集合中的一個或多個元素
zremrangebylex key min max 刪除有序集合中給定的字典區間的所有元素
zremrangebyrank key start stop 刪除有序集合中給定的索引區間的所有元素
zremrangebyscore key min max 刪除有序集合中給定的分數區間的所有元素
zset 中最後一個元素被刪除後,數據結構自動刪除,記憶體被回收。
(5)交集
zunionstore destination numkeys key [key ...] 計算給定的一個或多個有序集的並集,並存儲在新的 key 中
zinsterstore destination numkeys key [key ...] 計算給定的一個或多個有序集的交集並將結果集存儲在新的有序集合 key 中
內部編碼
·ziplist(壓縮列表):當有序集合的元素個數小於zset-max-ziplistentries配置(預設128個) , 同時每個元素的值都小於zset-max-ziplist-value配置(預設64位元組) 時。
·skiplist(跳躍表): 當 ziplist 編碼無法滿足時使用。
應用場景
排行榜、時間軸、商品推薦等。
其他數據結構
Redis 除了上面五種基礎結構外,還有Bitmaps,HyperLogLog、GEO、Stream四種數據結構。
6、Bitmaps
Bitmaps 實際上不是一種數據結構,它就是字元串,但是它可以對字元串的位進行操作。可以把Bitmaps 當成一個位數組來看待,以字母a為例,它的ASCII碼是98,對應的二進位是01100001,Bitmaps 的結構如下:
相關命令
setbit key offset value 對 key 所儲存的字元串值,設置或清除指定偏移量上的位(bit)
gitbit key offset 對 key 所儲存的字元串值,獲取指定偏移量上的位(bit)。
bitcount key [start][end] 計算指定範圍內,被設置為 1 的比特位的數量。
bitpos key bit [start] [end] 返回點陣圖中第一個值為 bit(0或1) 的二進位位的位置。
bitop operation destkey key [key …] 對一個或多個保存二進位位的字元串 key 進行位元操作,並將結果保存到 destkey 上
operation 可以是 and、 or、 not、 xor這四種操作中的任意一種:
bitop and destkey key [key ...] ,對一個或多個 key 求邏輯並,並將結果保存到 destkey 。
bitop or destkey key [key ...] ,對一個或多個 key 求邏輯或,並將結果保存到 destkey 。
bitop xor destkey key [key ...] ,對一個或多個 key 求邏輯異或,並將結果保存到 destkey 。
bitop not destkey key ,對給定 key 求邏輯非,並將結果保存到 destkey 。
除了 not 操作之外,其他操作都可以接受一個或多個 key 作為輸入。
bitfield key [get type offset] [set type offset value] [incrby type offset increment] [overflow wrap|sat|fail]
該命令詳情請查看:
https://redis.io/commands/bitfield
或http://www.redis.cn/commands/bitfield.html
應用場景
通過數據結構我們發現 bitmaps 適用於存儲 bool 行為的數據,比如統計用戶一年的登錄天數,使用 setbit 命令記錄登錄(比如用戶a第一天登錄了 setbit a 0 1),使用 bitcount 命令統計數量(bitcount a 0 364)。時間越久用戶越多,節省存儲空間的效果就越明顯。
7、HyperLogLog
HyperLogLog 是 Redis 2.8.9 添加的數據結構,它是一種用來做基數統計的演算法,可以使用固定且很少的記憶體(每個 HyperLogLog 結構需要12K位元組再加上key本身的幾個位元組)來存儲集合的唯一元素。但是它統計的結果並不是一個精確值,而是一個帶有 0.81% 標準錯誤(standard error)的近似值。HyperLogLog 具有去重功能。
相關命令
pfadd key element [element ...] 添加指定元素到 HyperLogLog 中。
pfcount key [key ...] 返回給定 HyperLogLog 的基數估算值。
pfmerge destkey sourcekey [sourcekey ...] 將多個 HyperLogLog 合併為一個 HyperLogLog
題外話:命令的開頭 pf 是 HyperLogLog 數據結構發明人 Philippe Flajolet 的首字母縮寫。
應用場景
統計某個網站或某個頁面的UV(只統計總數,不需要絕對準確,也不用知道是誰訪問的)。
8、GEO
Redis 3.2 提供了GEO(地理信息定位) 功能,它的底層實現是zset。
相關命令
geoadd key longitude latitude member [longitude latitude member ...] 將指定的地理空間位置(緯度、經度、名稱)添加到指定的key中
有效的經度介於 -180 度至 180 度之間。
有效的緯度介於 -85.05112878 度至 85.05112878 度之間。
geopos key member [member ...] 從key里返回所有給定位置元素的位置(經度和緯度)
geodist key member1 member2 [unit] 返回兩個給定位置之間的距離。
參數unit:
m 表示單位為米(預設)。
km 表示單位為千米。
mi 表示單位為英里。
ft 表示單位為英尺。
georadius key longitude latitude radius m|km|ft|mi [withcoord] [withdist]
[withhash] [COUNT count] [asc|desc] [store key] [storedist key]
以給定的經緯度為中心, 返回鍵包含的位置元素當中, 與中心的距離不超過給定最大距離的所有位置元素。
可選參數:
ithcoord: 返回結果中包含經緯度。
withdist: 返回結果中包含離中心節點位置的距離。
withhash: 返回結果中包含geohash, 有關geohash後面介紹。
COUNT count: 指定返回結果的數量。
asc|desc: 返回結果按照離中心節點的距離做升序或者降序。
store key: 將返回結果的地理位置信息保存到指定鍵。
storedist key: 將返回結果離中心節點的距離保存到指定鍵。
georadiusbymember key member radiusm|km|ft|mi [withcoord] [withdist]
[withhash] [COUNT count] [asc|desc] [store key] [storedist key]
同上,只不過他是以指定的成員為中心。
geohash key member [member …] 返回一個或多個位置元素的 geohash 表示。
9、Stream
Stream 是 Redis 5.0 添加的數據結構,它是一個新的強大的支持多播的可持久化的消息隊列,借鑒了 Kafka 的設計。我們前面說到 List 結構,它也可以做消息隊列,但只支持點對點模式。Redis 有一個單獨模塊 PubSub(發佈訂閱) 支持消息多播,但是它不能持久化。Stream 不僅可以持久化,還支持消息分組、ACK(應答)等功能。由於本人沒有使用過該數據結構,更多內容請參考:https://redis.io/topics/streams-intro或http://www.redis.cn/topics/streams-intro.html
到這裡 Redis 的數據結構就介紹完了,更多使用請參考