Redis中的Key
- Redis中的key是二進制安全的,可以使用任意二進制序列作爲key,即如字符串或者圖片的內容都可以作爲key,注意:空字符串在Redis中也被認爲是有效的key。
- key不宜過長,一是從存儲角度來講比較耗費內存,而且在查找key時對key進行比較將會增加開銷。
- 推薦使用中劃線或冒號將描述字段分隔,整體作爲key,如:“student:id”、“student:age”。
- key的最大容量爲512M。
基本命令
- 獲得一個符合匹配規則的鍵名列表
> keys pattern [? / * /[] ]
其中pattern爲正則表達式,返回符合相應規則的key的列表
- 判斷一個鍵是否存在
> exiests key
- 獲取key所對應的value的數據結構類型
> type key
基本數據類型-String
1. 基本賦值、取值操作
1.1 賦值
> set user:name eric
OK
set命令可以帶參數,
NX:只在key不存在時,才進行賦值操作;
XX:只在key已存在時,才進行賦值操作。
1.2 批量賦值
mset命令用於set多個key的value
> mset user:name eric user:age 18
OK
1.3 取值
> get user:name
"eric"
1.4 批量取值
mget命令用於批量取值,參數爲多個key,返回value列表
> mget user:name user:age
1) "eric"
2) "18"
2. 字符串操作
2.1 字符串拼接
> append user:name 1122
(integer) 8
> get user:name
"eric1122"
2.2 字符串截取
命令getrange key start end,獲取開始結束索引之間的子字符串
> getrange user:name 1 6
"ric112"
2.3 獲取長度
strlen命令用戶獲取key對應的value的長度
> strlen user:name
integer) 8
> strlen user:age
(integer) 2
3. 數值操作
注意到上述創建的key中的value的類型是相同的,都是string,如下:
> type user:name
string
> type user:age
string
但是使用OBJECT ENCODING命令進一步查看value的編碼類型:
> object encoding user:name
"raw"
> object encoding user:age
"int"
string類型針對以int爲編碼格式的value支持數值操作。
3.1 增加
incr key ,對key的value增加1
incrby key increment,增加指定的整數
> incr user:age
(integer) 19
> incrby user:age 10
(integer) 29
> get user:age
"29"
3.2 減少(與加類似)
3.3 二進制安全
爲什麼說Redis是二進制安全的?我們先來看下面的例子:
> set num 99
OK
> strlen num
(integer) 2
此時,如果將num自增1,再使用strlen來獲取num的長度,結果會是什麼呢?
> incr num
(integer) 100
> strlen num
???
此時num的value爲100,那麼此時獲取這個value的長度,結果是多少呢?
答案是:3
如果把num加1000呢?此時value的長度是多少?
> incrby num 1000
(integer) 1100
> get num
"1100"
> strlen num
???
num的value是1100,編碼類型爲int,那麼長度是多少?java中整型長度爲4個字節,Redis中是怎樣的?1100由幾個字節能夠表示?
程序運行的答案是:4
爲什麼?
因爲Redis是二進制安全的,所謂二進制安全就是指傳輸給我的數據的二進制是什麼樣,我就按什麼樣保存,不會對數據進行再編碼、序列化等操作。本質上數據都以字節數組的形式存儲與獲取,這也就意味着不會有溢出或者亂碼問題。
所以“100”這個字符串的長度爲3,“1100”的長度就是4。
4.Bitmap
Bitmap不是一個實際的數據類型,只是一系列位操作的命令,Redis將Bitmap歸屬於String類型。因爲String最大長度爲512M,所以Bitmap最多能表示232位。
4.1 賦值與取值
setbit和getbit命令用來設置/獲取二進制的具體某位的值,命令格式如下:
setbit/getbit key [offset value]
其中offset爲二進制的具體位數,value是將該位置爲1或0。
> setbit key 1 1
(integer) 1
> getbit key 1
(integer) 1
> get key
"@"
> strlen key
(integer) 1
上述setbit命令將一個字節的第1位賦值爲1,此時key對應的value爲01000000,getbit命令獲取該二進制數的第1位,爲1;01000000對應的ASSIC碼爲“@”,即value爲“@”。
此時,執行以下命令:
> setbit key 9 1
(integer) 0
> strlen key
(integer) 2
將第9位置爲1,Redis會自動向後補一個字節,變爲兩個字節(即01000000 01000000),value的第9位即第二個字節的第1位被置爲1。故現在value的長度爲2。
4.2 Bit位統計
命令: bitcount key [start end]用來統計value中有多少位爲“1”;
其中start代表開始字節的索引值,end代表結束字節的索引值(注意此處爲字節的索引,而不是二進制位的索引)。
如下:
#此時key的值爲 01000000 01000000
> bitcount key 0 1
(integer) 2
> bitcount key 1 1
(integer) 1
第一條命令從第0個字節開始到第1個字節結束,統計“1”的個數,結果爲2;
第二條命令其實就是統計第1個字節中“1”的個數,所以結果爲1。
4.3 Bit位查找
命令:bitpos key bit [start end]用來查找指定字節範圍中第一個bit位的索引;
其中,bit爲需要查找的值可爲0或1,start、end分別代表查找範圍中的開始、結束字節的索引。
如下:
#key的值爲 01000000 01000000
> bitpos key 1 1 1
(integer) 9
> bitpos key 1 0 1
(integer) 1
第1個字節中第一個“1”的位索引爲9,第0個到第1個字節範圍內第一個“1”的位索引爲1。
4.4 Bit位操作
命令:bitop operation destkey key [key …]
#創建k1,將第1位和第7位分別置爲1,即01000001,即字符“A”
> setbit k1 1 1
(integer) 0
> setbit k1 7 1
(integer) 0
> get k1
"A"
#創建k2,將第1位和第6位分別置爲1,即01000010,即字符“B”
> setbit k2 1 1
(integer) 0
> setbit k2 6 1
(integer) 0
> get k2
"B"
(1)與操作–and
#將k1和k2相與,結果應爲:01000000,即字符“@”,結果保存至destkey
> bitop and andkey k1 k2
(integer) 1
> get andkey
"@"
(2)或操作–or
#將k1和k2相與,結果應爲:01000011,即字符“C”,結果保存至destkey
> bitop or orkey k1 k2
(integer) 1
> get orkey
"C"
簡單應用場景
Redis針對數據提供了上述的各種運算方法,客戶端進行處理時,直接調用Redis的數據處理方法即可,同時數據又是存儲在Redis內部的,這種行爲被稱爲“計算向數據移動”。
數值計算操作應用場景
一個典型的場景就是秒殺,用戶通過訪多個客戶端進行商品秒殺,可以抽象爲:客戶端通過Redis進行數值的自增,增加到商品的最大數量時,秒殺結束。
因爲Redis的業務處理過程是單線程的,所以多個客戶端的請求不會存在線程安全問題,也就不會出現商品過買的問題。
類似場景還有,統計多客戶端用戶訪問服務端的次數,比如記錄用戶操作日誌等業務。
Bitmap應用場景
假設有以下需求:電信運營商給用戶提供了掌上營業廳服務,現在局方想要統計每個用戶在一年內的掌上營業廳登錄情況,在哪些天登錄了,一共有多少天登錄?
方案一:使用數據庫,記錄每一個用戶的登錄情況。用戶每登錄一次,則增加一條記錄,記錄包含登錄當天的日期。然後一年中一共有多少天登錄通過SQL語句來查詢。
問題:一個用戶在一年中有多少天登錄,就會產生多少條記錄,這裏還要注意到電信運營商的用戶數基本是千萬級的,這樣這張表就會變的龐大無比,本方案不可行。
方案二:使用Redis的Bitmap來存儲用戶登錄信息
#用戶eric分別在第2天、第4天和第365天登錄了系統,將登錄信息存儲到Bitmap中
> setbit eric 1 1
(integer) 0
> setbit eric 3 1
(integer) 0
> setbit eric 364 1
(integer) 0
此時用於存儲用戶eric登錄信息的數據大小爲:
> strlen eric
(integer) 46
46字節
每個用戶使用46個字節就可以統計其一年的登錄情況,與數據庫的方案相比,更具有可行性。
獲取用戶登錄情況:
# Redis提供了雙向索引,-1代表最後一個元素
> bitcount eric 0 -1
(integer) 3
當然,實際場景下如果確實有千萬級以上的活躍用戶,系統壓力也還是很大的,這裏的例子僅僅是對方案一數據庫存儲進行優化。
小結
本文大致介紹了Redis中key的概念和幾個關於key的命令,然後着重介紹了Redis基本數據類型中的String,分爲字符串、數值、和Bitmap。分別列舉了針對各數據類型的處理命令,突出了計算向數據移動的特點。最後還介紹了幾個實用場景,經過本次介紹,想必大家對Redis的String有了一個基本的瞭解了吧。