文章目錄
- 前言
- 一、string字符串類型
- 二、List列表類型
- 三、 Hash表
- 四、 Set集合
- 五、 ZSet有序集合
- 六、 GEO地理空間
- 七、 HyperLogLog基數統計
- 八、Bitmap位圖
- 九、bitfield位域
- 十、 Stream流
- 10.1 隊列指令
- 10.2 消費組指令
- 10.3 ACK機制
前言
redis是k-v鍵值對進行存儲,key
的類型都是字符串,而數據類型是value
的數據類型
Tip:命令不區分大小寫,而key的值是區分大小寫的
Key常用命令
keys * //當前庫的所有key
exists key //判斷某個key是否存在,可以同時判斷多個key,返回幾就是存在幾個
type key //查看你的key是什么類型// 刪除
del key //是原子操作,刪除指定的key數據
unlink key //常用于多線程時,非阻塞刪除,僅僅將keys從keyspace元數據中刪除,沒真正的刪除,會在后續異步中操作// 過期時間
ttl key // 查看還有多少秒過期 -1表示永不過期 -2 表示已過期
expire key 秒 // 給key設置過期時間// 數據庫操作
move key dbindex [0-15] // 將當前數據庫的key移動到指定的數據庫中 redis默認是有16個數據庫的
select dbindex [0-15] // 切換數據庫[0-15],默認為0
dbsize // 查看當前數據庫key的數量flushdb // 清空當前庫
flushall // 清空16個數據庫 慎用
help @+數據類型
會出現命令提示 比如 help @string
一、string字符串類型
- string是redis最基本的類型,一個key對應一個value。
- string類型是二進制安全的,意思是redis的string可以包含任何數據,比如jpg圖片或者序列化的對象。
- string類型是Redis最基本的數據類型,一個redis中字符串value最多可以是512M
1. set命令
// 常用命令
set key value [NX|XX][GET][EX seconds|PX milliseconds|EXAT unix-time-seconds|PXAT unix-time-milliseconds|KEEPTTLJ// 設置過期時間,秒為單位
set key1 value1 EX 3 // 過期時間為3秒// 設置鍵存在時的鍵值(即覆蓋作用),并返回原來的值
set key1 value2 get// 將key1進行修改時,繼續使用之前的過期時間(因為默認修改時是直接設置為永不過期了)
set key1 value1 keepttl // 過期時間為3秒
SET命令有NX、XX、EX、PX以及KEEPTTL五個可選參數,
- NX:鍵不存在的時候設置鍵值(NX可以理解為not exit)
- XX:鍵存在的時候設置鍵值
- GET:返回指定鍵原本的值,若鍵不存在時返回nil
- EX seconds:以秒為單位設置過期時間
- PX milliseconds:以毫秒為單位設置過期時間
- EXAT timestamp:設置以秒為單位的UNIX時間戳所對應的時間為過期時間
- PXAT milliseconds-timestamp:設置以毫秒為單位的UNIX時間戳所對應的時間為過期時間
- KEEPTTL:保留設置前指定鍵的生存時間
2. mset同時設置多個鍵值對
MSET [key1] [value1] [key2] [value2] [key3] [value3] // 同時設置一個或多個鍵值對
MGET [key1] [key2] [key3] // 同時獲取多個key的值
MSETNX [key1] [value1] [key2] [value2] // 同時設置一個或多個 key-value 對 必須保證key都不存在才能成功
3. 獲取鍵的指定區間的值
GETRANGE [key] 0 -1 // 獲取這個key的值的全部
GETRANGE [key] 0 2 // 獲取這個key的值索引0到索引2之間的值
SETRANGE [key] 1 xxx // 設置指定區間范圍內的值// 獲取key1的0-3的值,類似于獲取字符串的子字符串
getrange key1 0 3// 將key1從1索引開始設置為aayy
setrange key1 aayy
4. 數值增減
key鍵對應的value類型必須為數字
INCR [key] // 遞增數字 +1
INCRBY [key] [increment] // 增加指定的整數 +increment
DECR [key] // 遞減數字 -1
DECRBY [key] [increment] // 減少指定的整數 -increment
5. 獲取字符串長度和內容相加
STRLEN [key] // 獲取key對應的值的長度
APPEND [key] [vale] // 添加字符串內容// 向key1中追加aaaa
append key1 aaaa
6. 分布式鎖
setnx/setex [key] [過期時間] [value] // 設置帶過期時間的key,動態設置
setnx [key] [value] // 只有在 key 不存在時設置 key 的值。
// 一般是兩個命令連用,寫成lua腳本連用,具體在Redis高級分布式鎖中使用
7. getset
getset [key] [value] // 給定 key 的值設為 value ,并返回 key 的舊值
// 類似于 set [key] [value] get
應用
- dy點贊某個視頻或商品,點一次加一次
- 使用incr key 獲得多少人喜歡
- 對于文章是否喜歡
- 使用incr key 獲得多少人喜歡
二、List列表類型
- 列表是簡單的字符串列表,按照插入順序排序。
- 可以添加一個元素到列表的頭部(左邊)或者尾部(右邊)它的底層實際是個雙端鏈表
- 最多可以包含2^32- 1個元素(4294967295,每個列表超過40億個元素)
- 單key多vlue
主要功能有push/pop
等,一般用在棧、隊列、消息隊列等場景
- left、right都可以插入添加;
- 如果鍵不存在,創建新的鏈表
- 如果鍵已存在,新增內容
- 如果鍵全移除,對應的鍵也就消失了
常見命令
lpush [key] [value] ... // 往 列表頭部(左邊)放入元素
Rpush [key] [value] ... // 往 列表(右邊)放入元素
lrange [key] 0 -1 // 從左邊開始遍歷列表 只能從左邊遍歷
lpop [key] // 最左邊的出棧 也就是lrange遍歷的第一個
rpop [key] // 最右邊的出棧 也就是lrange遍歷的最后一個
lindex [key] [index] // 通過索引值獲取值
llen [key] // 獲得元素個數
lrem [key] [num] [value] // 從左往右刪除 num個值為 value的值(因為list允許有重復的值)
lrem [key] 0 [value] // 從左往右刪除所有值為value的值
ltrim [key] [開始] [結束] // 截取指定范圍的值后再賦給[key],也就是刪除這個區間外的值
RPOPLPUSH [key1] [key2] //移除key1列表的最后一個元素(也即R端),并將該元素添加到另一個key2列表的第一個(L端)并返回這個元素的值
lset [key] [index] [value] //將key的第 index 個索引值改為value
linsert [key] before/after [value1] [value2] // 在list某個已有值的前后再添加具體值
應用場景
公眾號的訂閱的消息
- 關注的人發布文章,就會到本人的列表中 List,進行Ipush操作: lpush likearticle:id 文章id
- 查看自己訂閱的文章 lrange likearticle:id 0 9
三、 Hash表
- Hash是一個string類型的 field(字段)和 value(值)的映射表,Hash特別適合用于存儲對象。
- 它也是k-v 模式不變,但v是一個鍵值對 => Map<String,Map<Object,Object>>
- Redis 中每個hash可以存儲2個32-1鍵值對(40多億)|
常用命令
hset/hget/hmset/hmget/hgetall/hdel
hlen // 獲取在某個key內的全部數量
hexists [key] [k1] // 看key中是否有k1這個鍵
hkeys [key] // 獲取key里面的所有key
hvals [key] // 獲取key里面的所有value
hincrby [key] k1 [num] // key里面k1的值增長num 整數
hincrbyfloat [key] k1 [num] // key里面k1的值增長num 小數
hsetnx [key] k1 [value] // 不存在賦值,存在了無效\
四、 Set集合
- 單值多value,也就是無重復。集合成員是唯一的,這就意味著集合中不能出現重復的數據,集合對象的編碼可以是intset或者hashtable。
- Redis 的 Set 是String類型的無序集合。
- Redis 中Set集合是通過哈希表實現的,所以添加,刪除,查找的復雜度都是O(1)。
- 集合中最大的成員數為2^32- 1(4294967295,每個集合可存儲40多億個成員)
常用命令
SADD key [member ...] // 添加元素,有重復值時,自動去重
SMEMBERS key // 遍歷集合中所有元素
SISMEMBER key member // 判斷元素是否在集合中
SREM key [member ...] // 刪除元素
SCARD key // 獲取集合長度
SRANDMEMBER key m // 從set集合里面隨機取出m個元素展示,不會刪除 如果超過最大數量就全部取出 如果寫的值是負數,比如-3 ,表示需要取出3個,但是可能會有重復值
SPOP key m // 從集合中隨機彈出一個元素,會刪除
SMOVE key1 key2 value1 // 將key1的已存在的某個值value1遷移給key2,key1中value1便沒有了
集合運算
SDIFF keyA keyB // A - B 屬于A但不屬于B的元素構成的集合
SUNION keyA keyB // A U B 屬于A或者屬于B的元素合并后的
SINTER keyA keyB // A ∩ B 屬于A同時屬于B
SINTERCARD numkeys keyA keyB [LIMIT limit] // 不返回結果集,只返回結果的基數(即個數)
應用場景
抽獎小程序
- 將所有抽獎用戶
sadd key 用戶ID
- 顯示多少人參加
SCARD key
- 從set中任意選取N個中獎人
SRANDMEMBER key 2
隨機抽獎兩個人,元素不刪除SPOP key 2
隨機抽獎兩個人,元素會刪除
朋友圈點贊
- 新增點贊
SADD pub:msgID 點贊用戶Id1 點贊用戶Id2
- 取消點贊
SREM pub:msgID 點贊用戶Id
- 展現所有點贊過的用戶
SMEMBERS pub:msgID
- 點贊用戶統計
SCARD pub:msgID
- 判斷某個朋友是否對樓主點贊過
SISMEMBER pub:msgID 用戶Id
可能認識的人
- 求兩個人的差集
SDIFF user1 user2
五、 ZSet有序集合
- zset和 set一樣也是string類型元素的集合,且不允許重復的成員。
zset k1 score1 v1 score2 v2
- zset和set的區別,就是在set的基礎上加了一個score分數值,redis正是通過分數來為集合中的成員進行從小到大的排序。
- zset的成員是唯一的,但分數(score)卻可以重復。
- zset集合是通過哈希表實現的,所以添加,刪除,查找的復雜度都是O(1)。
- 集合中最大的成員數為2^32 -1
常用命令
ZADD key score member [score member ] // 添加元素
ZRANGE key start stop [WITHSCORES] // 返回元素分數從小到大的順序 返回索引從start到stop之間的所有元素,0 -1是返回全部
ZREVRANGE key 0 - 1 [WITHSCORES] // 反序,WITHSCORES參數表示顯示分數
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count] // 獲取指定分數范圍的元素,在min或max前加"("時,表示開區間 limit是返回限制,返回多少個
// 實例:ZRANGEBYSCORE key (60 90 limit 0 1 // 表示在key中篩選一個分數在(60,90]區間中的值ZSCORE key member // 獲取元素的分數
ZCARD key // 獲取集合中元素的數量
ZREM key 某score下對應的value值 // 刪除元素
ZINCRBY key increment member // 增加某個元素的分數
ZCOUNT key min max // 獲得指定分數范圍內的元素個數
ZRANK key value // 獲得value下標
ZREVRANK key values // 逆序獲得下標
ZMPOP numkeys key [key …] <MIN | MAX> [COUNT count] // 彈出元素,彈出后刪除
- numkeys 表示幾個key
- <MIN | MAX> 小 | 大
- [COUNT count] count num 彈出num個
在myzset集合中,有元素:(1,one),(2,two),(3,three)
以上命令意思是,在myzset這一個鍵中,取出最小的一個(分數,值)這樣的‘分數-值’對
應用場景
根據商品銷售對商品進行排序顯示
- 思路:定義商品銷售排行榜(sorted set集合),key為goods:sellsort,分數為商品銷售數量。
- 商品編號1001的銷量是9,商品編號1002的銷量是15
zadd goods:sellsort 9 1001 15 1002
- 有一個客戶又買了2件商品1001,商品編號1001銷量加2
zincrby goods:sellsort 2 1001
- 求商品銷量前10名
ZRANGE goods:sellsort 0 9 withscores
六、 GEO地理空間
Redis GEO主要用于存儲地理位置信息,并對存儲的信息進行操作,包括
- 添加地理位置的坐標。
- 獲取地理位置的坐標。
- 計算兩個位置之間的距離。
- 根據用戶給定的經緯度坐標來獲取指定范圍內的地理位置集合
經緯度去地圖上直接復制
// 多個經度(longitude)、緯度(latitude)、位置名稱(member) 添加到指定的key中
GEOADD key longitude latitude member [經度 緯度 名稱 ...]// 從鍵里面返回所有給定位置元素的位置(經度和緯度)
GEOPOS key member [...]GEODIST 返回兩個給定位置之間的距離。
GEORADIUS 以給定的經緯度為中心,返回與中心的距離不超過給定最大距離的所有位置元素。
GEORADIUSBYMEMBER 跟GEORADIUS類似// 返回一個或多個位置元素的Geohash表示
GEOHASH key member [...]
- GEORADIUS
應用場景 - 美團附近的飯店、酒店
- 高德地圖附近的店
七、 HyperLogLog基數統計
HyperLogLog是用來做基數統計的算法。
- 去重復統計功能的基數估計算法就是 HyperLogLog
- 基數:是一種數據集,去重復后的真實個數
- 基數統計:用于統計一個集合中不重復的元素個數,就是對集合去重復后剩余元素的計算
- 只需要花費12KB內存,就能記錄 2的64次方=18446744073709551616 個不同元素的基數
HyperLogLog的優點是,在輸入元素的數量或者體積非常非常大時,計算基數所需的空間總是固定且是很小的。
HyperLogLog類型的本質是string類型。但是,因為 HyperLogLog只會根據輸入元素來計算基數,而不會儲存輸入元素本身,所以HyperLogLog不能像集合那樣,返回輸入的各個元素。(即不能用get)
PFADD key element [element ...] // 添加指定元素到 HyperLogLog 中。
PFCOUNT key [key ...] // 返回給定HyperLogLog的基數估算值。
PFMERGE destkey sourcekey [sourcekey ...] // 將多個HyperLogLog合并為一個HyperLogLog
應用場景
- 統計某個網頁的UV、某個文章的UV
- UV Unique Visitor 獨立訪客,一般理解為客戶端IP,需要去重
- 用戶搜索網站關鍵詞數量
- 統計用戶每天搜索不同詞條個數
八、Bitmap位圖
由0和1狀態表現的二進制位的bit數組
- 用String類型作為底層數據結構實現的一種統計二值狀態(Y/N)的數據類型
- 位圖本質是
數組
,它是基于String數據類型的按位的操作。該數組由多個二進制位組成,每個二進制位都對應一個偏移量(我們稱之為一個索引)。 - 一個鍵對應的位圖類型應該是8的整數倍。
- Bitmap支持的最大位數是2^32位,它可以極大的節約存儲空間,使用512M內存就可以存儲多達42.9億的字節信息(2的32次方 = 4294967296)
常用命令
SETBIT key offset value // 將key鍵中的第offset的值設為value value只能是0或1 offset 從0開始
GETBIT key offset // 獲得第offset位的值
STRLEN key // 得出占多少字節 超過8位后自己按照8位一組一byte再擴容
BITCOUNT key // 得出該key里面含有幾個1
BITOP and destKey key1 key2 // 對一個或多個 key 求邏輯并,并將結果保存到 destkey
BITOP or destKey key1 key2 // 對一個或多個 key 求邏輯或,并將結果保存到 destkey
BITOP XOR destKey key1 key2 // 對一個或多個 key 求邏輯異或,并將結果保存到 destkey
BITOP NOT destKey key // 對key 求邏輯非,并將結果保存到 destkey
應用場景
做簽到很適合位圖
- 每天使用1個1億位的Bitmap約占12MB的內存(10^8/8/1024/1024),10天的Bitmap的內存開銷約為120MB,內存壓力不算太高。
- 在實際使用時,最好對Bitmap設置過期時間,讓Redis自動刪除不再需要的簽到記錄以節省內存開銷。
- 對于電影和廣告是否被點擊播放過也可以用位圖
九、bitfield位域
通過bitfield命令可以一次性操作多個比特位域(指的是連續的多個比特位),它會執行一系列操作并返回一個響應數組,這個數組中的元素對應參數列表中的相應操作的執行結果。
十、 Stream流
Redis Stream主要用于消息隊列(MQ,Message Queue)
實現消息隊列的三個方式
-
List實現消息隊列
- 常用來做異步隊列使用,將需要延后處理的任務結構體序列化成字符串塞進Redis的列表,另個線程從這個列表中輪詢數據進行處理。
-
Pub/Sub 發布訂閱,
- 但它有個缺點就是消息無法持久化,如果出現網絡斷開、Redis宕機等,消息就會被丟棄。簡單來說發布訂閱(pub/sub)可以分發消息,但無法記錄歷史消息。并且沒有ACK機制保證數據的可靠性
-
Stream流 (Redis版的MQ消息中間件+阻塞隊列)
- Redis Stream提供了消息的持久化和主備復制功能,可以讓任何客戶端訪問任何時刻的數據,并且能記住每一個客戶端的訪問位置,還能保證消息不丟失。
Stream底層結構
10.1 隊列指令
XADD // 添加消息到隊列末尾
XTRIM maxlen|minid len|id // 限制Stream的長度,如果已經超長會進行截取// maxlen 允許的最大長度,對流進行修剪限制長度,按id保留最大的len個// minid 允許的最小id,從某個id值開始比該id值小的將會被拋棄XDEL key ID // 刪除消息
XLEN key // 獲取Stream中的消息長度XRANGE key start end [count] // 獲取消息列表(可以指定范圍),忽略刪除的消息
XREVRANGE // 和XRANGE相比區別在于反向獲取,ID從大到小XREAD [COUNT count] [BLOCK milliseconds] key id // 獲取消息(阻塞/非阻塞),返回大于指定ID的消息
// count 最多讀取幾條消息,不指定時返回key中所有滿足的消息
// BLOCK是否已阻塞的方式讀取消息,默認不阻塞,如果milliseconds設置為0,表示永遠阻塞
// id $表示比最大ID還大的id;0-0表示從最小id獲取消息
XADD 添加消息
*
號表示服務器自動生成MessageID(類似mysq|里面主鍵auto_increment),后面順序跟著一堆業務key/value
- Redis對于ID有強制要求,
*
號的位置可以是自己指定的ID,但格式必須是時間戳-自增Id這樣的方式,且后續ID不能小于前一個ID
XRANGE 獲取消息
xrange - + 10 表示獲取10條ID從小到大的數據
XREAD 獲取消息(阻塞態)
Stream的基礎方法,使用xadd存入消息和xread循環阻塞讀取消息的方式可以實現簡易版的消息隊列,交互流程如下
10.2 消費組指令
創建消費組的目的:
讓組內的多個消費者共同分擔讀取消息,所以,我們通常會讓每個消費者讀取部分消息,從而實現消息讀取負載在多個消費者間是均衡分布的
XGROUP CREATE key GROUP ID //創建消費者組,消費者按組創建,id為$時表示從尾部消費,為0時表示從頭消費
XREADGROUP GROUP // 讀取消費者組中的消息XACK // ack消息,消息被標記為“已處理”
XPENDING key GROUP // 打印待處理消息的詳細信息(即已讀但未ack確認的消息)XGROUP SETID // 設置消費者組最后遞送消息的ID
XGROUP DELCONSUMER // 刪除消費者組
XCLAIM // 轉移消息的歸屬權(長期未被處理/無法處理的消息,轉交給其他消費者組進行處理)
XINFO // 打印Stream\Consumer\Group的詳細信息
XINFO GROUPS // 打印消費者組的詳細信息
XINFO STREAM // 打印Stream的詳細信息
XREADGROUP命令中
- stream中的消息—旦被消費組里的一個消費者讀取了,就不能再被該消費組內的其他消費者讀取了,即同一個消費組里的消費者不能消費同一條消息。
- 但不同消費組的消費者可以消費同一條信息。
XPENDING 打印待處理消息的詳細信息
10.3 ACK機制
基于Stream 實現的消息隊列,如何保證消費者在發生故障或宕機再次重啟后,仍然可以讀取未處理完的消息?
- Streams 會自動使用內部隊列(也稱為 PENDING List)留存消費組里每個消費者讀取的消息保底措施,直到消費者使用XACK命令通知Streams"消息已經處理完成"。
- 消費確認增加了消息的可靠性,一般在業務處理完成之后,需要執行
XACK
命令確認消息已經被消費完成。
下面抓圖所示: consumer2已讀取的消息的ID是1659430293537-0
一旦消息1659430293537-0
被consumer2處理了
consumer2就可以使用XACK
命令通知Streams,然后這條消息就會被刪除
此時回復命令:
XACK mystream groupC 1659430293537-0
表示已確認