一古掏、概述
字符串類型是Redis最基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)损话,Redis中的鍵都是字符串類型,其他幾種數(shù)據(jù)結(jié)構(gòu)都是在字符串基礎(chǔ)之上構(gòu)建的冗茸;
字符串類型的值實(shí)際可以是字符串(如簡(jiǎn)單的字符串席镀、JSON、XML)夏漱,數(shù)字(整型豪诲、浮點(diǎn)數(shù)),也可以是二進(jìn)制(圖片挂绰、音頻屎篱、視頻),但是值的最大不能超過(guò)512MB葵蒂。
二交播、常用命令
- 設(shè)置值:
set key value [ex seconds] [px milliseconds] [nx | xx]
set命令選項(xiàng)說(shuō)明:
- ex seconds:為鍵設(shè)置秒級(jí)過(guò)期時(shí)間
- px milliseconds:為鍵設(shè)置毫秒級(jí)過(guò)期時(shí)間
- nx:鍵必須不存在時(shí),才可以設(shè)置成功践付,用于添加
- xx:與xx相反秦士,鍵必須存在,才可以設(shè)置成功永高,用于更新
同時(shí)隧土,Redis也提供了 setex 和 setnx兩個(gè)命令,其作用與ex命爬,nx選項(xiàng)一樣曹傀,但在實(shí)際應(yīng)用中需要注意,當(dāng)同時(shí)用到ex和nx機(jī)制時(shí)饲宛,要盡可能地使用set ex nx的組合命令皆愉,而不能拆分成兩條setex 和setnx,根據(jù)Redis性能測(cè)試報(bào)告:how fast is redis,Redis執(zhí)行一條指令的并發(fā)量約為7w幕庐,當(dāng)同時(shí)使用setnx和setex而不使用set ex nx組合命令時(shí)久锥,Redis的并發(fā)量相當(dāng)于減少了一半,這點(diǎn)是應(yīng)用當(dāng)中的細(xì)節(jié)部分翔脱,需要銘記奴拦。
當(dāng)然媒鼓,setmx和setex也有其優(yōu)點(diǎn)和對(duì)應(yīng)的應(yīng)用場(chǎng)景届吁,以setnx為例,由于Redis的單線程命令處理機(jī)制绿鸣,如果多個(gè)客戶端同時(shí)執(zhí)行setnx key value疚沐,根據(jù)setnx的特性,只有一個(gè)客戶端能設(shè)置成功潮模,setnx可以作為分布式鎖的一種實(shí)現(xiàn)方案亮蛔,Redis官方廢除了使用setnx實(shí)現(xiàn)分布式鎖的方法:
- 獲取值:
- 獲取單個(gè)值:get key,如果獲取的鍵不存在擎厢,則返回nil(空)
- 批量獲取值:mget key [key]...究流,批量操作命令可以提高開(kāi)發(fā)效率,學(xué)會(huì)合理使用批量操作动遭,有助于提高業(yè)務(wù)處理效率芬探,但是并不是說(shuō)批量操作是無(wú)節(jié)制的,如果key數(shù)量過(guò)多厘惦,很可能造成Redis阻塞或者網(wǎng)絡(luò)擁塞偷仿。
- 計(jì)數(shù):
incr key:用于對(duì)值做自增操作,返回結(jié)果分為3種情況:
- 值不是整數(shù)宵蕉,返回錯(cuò)誤酝静;
- 值是整數(shù),返回自增后的結(jié)果羡玛;
- 鍵不存在别智,按照值為0自增,返回結(jié)果為1稼稿;
例如薄榛,對(duì)一個(gè)不存在的鍵執(zhí)行Incr操作,返回結(jié)果為1渺杉;
除了自增命令外蛇数,Redis還提供了decr(自減)、incrby(自增指定數(shù)字)是越、decrby(自減指定數(shù)字)耳舅、incrbyfloat(自增浮點(diǎn)數(shù)):
decr key
incrby key increment
decrby key decrement
incrbyfloat key increment
在Java里面可以使用CAS(compare and swap)機(jī)制來(lái)實(shí)現(xiàn)計(jì)數(shù)功能,但會(huì)有一定的CPU開(kāi)銷(線程安全,通過(guò)硬件上的阻塞來(lái)實(shí)現(xiàn)軟件上的非阻塞浦徊,再次基礎(chǔ)上可以拓展出AQS機(jī)制)馏予,在Redis中不存在CPU開(kāi)銷問(wèn)題,因?yàn)镽edis是單線程架構(gòu)盔性,任何命令都在Redis服務(wù)端上順序執(zhí)行霞丧。
- 其他命令:
del key:刪除key;
mset key value [key value ...]:批量設(shè)置鍵值冕香;
append key value:向字符串尾部追加值蛹尝;
strlen key:字符串長(zhǎng)度;
getset key value:設(shè)置并返回原值悉尾;
setrange key offeset value:設(shè)置指定位置的字符突那;
getrange ket start end:獲取部分字符串
三、內(nèi)部編碼
字符串類型的內(nèi)部編碼有3種:
- int:8個(gè)字節(jié)的長(zhǎng)整型构眯;
- embstr:小于等于39個(gè)字節(jié)的字符串愕难;
- raw:大于39個(gè)字節(jié)的字符串;
Redis會(huì)根據(jù)當(dāng)前值的類型和長(zhǎng)度決定使用哪種內(nèi)部編碼實(shí)現(xiàn)惫霸。
四猫缭、應(yīng)用場(chǎng)景
Redis字符串應(yīng)用場(chǎng)景非常廣泛,這里列舉幾個(gè)比較常見(jiàn)的應(yīng)用場(chǎng)景:
- 緩存功能:
使用Redis作為緩存在業(yè)界應(yīng)用非常地廣泛壹店,常常與memcache做比較猜丹,關(guān)于其選型,可參考該文章:技術(shù)選型:Redis還是memcache
Redis作為緩存設(shè)計(jì)的架構(gòu)圖大致如下茫打,Redis作為緩存層居触,MySQL最為存儲(chǔ)層,絕大部分請(qǐng)求的數(shù)據(jù)都是從Redis中獲取老赤,用于Redis具有支撐高并發(fā)的特性轮洋,所以緩存通常能加速讀寫(xiě)和降低后端壓力。
實(shí)現(xiàn)思路:首先定義一個(gè)方法用于獲取用戶的基礎(chǔ)信息抬旺,當(dāng)請(qǐng)求到來(lái)時(shí)弊予,優(yōu)先從Redis中獲取用戶信息,如果命中緩存則直接返回結(jié)果开财,如果不命中緩存汉柒,則從MySQL中獲取數(shù)據(jù),同時(shí)將結(jié)果寫(xiě)入Redis緩存中责鳍,并添加過(guò)期時(shí)間碾褂,一種可能的實(shí)現(xiàn)(偽代碼)如下:
public UserInfo getUserInfo(long id){
userRediskey = "user:info:" +id;
value = redis.get(userRediskey);
UserInfo userInfo;
if(value != null){
userInfo = deserialize(value);
}else{
userInfo = mysql.get(id);
if(userInfo != null){
redis.setnx(userRediskey,3600,serialize(userInfo));
}
}
return userInfo;
}
- 分布式session共享:
在分布式應(yīng)用中,一個(gè)亟需解決的問(wèn)題便是session的一致性問(wèn)題历葛,分布式web服務(wù)將用戶的session信息(如:登錄信息)保存在各自服務(wù)器上正塌,這樣會(huì)造成一個(gè)問(wèn)題,出于負(fù)載均衡的考慮,分布式服務(wù)會(huì)將用戶的訪問(wèn)均衡到不同的服務(wù)器上乓诽,用戶刷新一次訪問(wèn)可能會(huì)發(fā)現(xiàn)需要重新登錄帜羊,這個(gè)問(wèn)題對(duì)于用戶來(lái)說(shuō)是不可容忍的。
為解決這個(gè)問(wèn)題鸠天,可以使用Redis將用戶的session進(jìn)行集中管理讼育,如下圖所示,在這種模式下稠集,只要保證Redis是高可用和擴(kuò)展性的奶段,每次用戶更新或者查詢登錄信息都直接從Redis中集中獲取。
- 計(jì)數(shù)器:
Redis還可以作為計(jì)數(shù)的基礎(chǔ)工具巍杈,實(shí)現(xiàn)快速計(jì)數(shù)忧饭、查詢緩存的功能,同時(shí)數(shù)據(jù)可以異步落地到其他數(shù)據(jù)源筷畦,如視頻播放量、文章閱讀量的記錄刺洒,一種可能的簡(jiǎn)單實(shí)現(xiàn)如下:
public long incrVideoCounter(long id){
key = "video:playCount:" + id;
return redis.incr(key);
}
實(shí)際上鳖宾,一個(gè)真實(shí)的計(jì)數(shù)系統(tǒng)還要考慮:防作弊、不同維度計(jì)數(shù)逆航、數(shù)據(jù)持久化等問(wèn)題鼎文。
- 限速:
出于安全考慮(防腳本),很多應(yīng)用會(huì)在每次進(jìn)行登錄時(shí)因俐,會(huì)讓用戶輸入手機(jī)驗(yàn)證碼拇惋,從而確定是否是用戶本人,短信接口會(huì)限制用戶每分鐘獲取驗(yàn)證碼的頻率抹剩,如一分鐘內(nèi)不超過(guò)5次撑帖,一種可能的實(shí)現(xiàn)如下:
iphoneNum = "138xxxxx";
key = "shortMsg:limit:" +phoneNum;
//set key value EX 60 NX
isExists = redis.set(key,1,"EX 60","NX");
if(isExists != null || redis.incr(key)<=5){
//pass,通過(guò)
}else{
//wait,限速
}
- 總結(jié):Redis的應(yīng)用場(chǎng)景非常廣,遠(yuǎn)不止以上列出的幾種澳眷,更多的功能設(shè)計(jì)仍需要結(jié)合業(yè)務(wù)去挖掘胡嘿。
感謝閱讀~~
參考資料:
《Redis開(kāi)發(fā)與運(yùn)維》付磊、張益軍[著]