Redis學(xué)習(xí)筆記:String內(nèi)部編碼及其應(yīng)用場(chǎng)景

一古掏、概述

字符串類型是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葵蒂。

二交播、常用命令

  1. 設(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)分布式鎖的方法:

  1. 獲取值:
  • 獲取單個(gè)值:get key,如果獲取的鍵不存在擎厢,則返回nil(空)
  • 批量獲取值:mget key [key]...究流,批量操作命令可以提高開(kāi)發(fā)效率,學(xué)會(huì)合理使用批量操作动遭,有助于提高業(yè)務(wù)處理效率芬探,但是并不是說(shuō)批量操作是無(wú)節(jié)制的,如果key數(shù)量過(guò)多厘惦,很可能造成Redis阻塞或者網(wǎng)絡(luò)擁塞偷仿。
  1. 計(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í)行霞丧。

  1. 其他命令:
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)景:

  1. 緩存功能:
    使用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è)計(jì).png

實(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;
}
  1. 分布式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中集中獲取。

分布式session.png
  1. 計(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)題鼎文。

  1. 限速:

出于安全考慮(防腳本),很多應(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,限速
}
  1. 總結(jié):Redis的應(yīng)用場(chǎng)景非常廣,遠(yuǎn)不止以上列出的幾種澳眷,更多的功能設(shè)計(jì)仍需要結(jié)合業(yè)務(wù)去挖掘胡嘿。

感謝閱讀~~

參考資料:


《Redis開(kāi)發(fā)與運(yùn)維》付磊、張益軍[著]

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末钳踊,一起剝皮案震驚了整個(gè)濱河市衷敌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌拓瞪,老刑警劉巖缴罗,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異祭埂,居然都是意外死亡面氓,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)侧但,“玉大人矢空,你說(shuō)我怎么就攤上這事≠骱幔” “怎么了屁药?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)柏锄。 經(jīng)常有香客問(wèn)我酿箭,道長(zhǎng),這世上最難降的妖魔是什么趾娃? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任缭嫡,我火速辦了婚禮,結(jié)果婚禮上抬闷,老公的妹妹穿的比我還像新娘妇蛀。我一直安慰自己,他們只是感情好笤成,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布评架。 她就那樣靜靜地躺著,像睡著了一般炕泳。 火紅的嫁衣襯著肌膚如雪纵诞。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,146評(píng)論 1 297
  • 那天培遵,我揣著相機(jī)與錄音浙芙,去河邊找鬼。 笑死籽腕,一個(gè)胖子當(dāng)著我的面吹牛嗡呼,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播节仿,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼晤锥,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了廊宪?” 一聲冷哼從身側(cè)響起矾瘾,我...
    開(kāi)封第一講書(shū)人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎箭启,沒(méi)想到半個(gè)月后壕翩,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡傅寡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年放妈,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了北救。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡芜抒,死狀恐怖珍策,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情宅倒,我是刑警寧澤攘宙,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站拐迁,受9級(jí)特大地震影響蹭劈,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜线召,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一铺韧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧缓淹,春花似錦哈打、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至鹏溯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間淹仑,已是汗流浹背丙挽。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留匀借,地道東北人颜阐。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像吓肋,于是被迫代替她去往敵國(guó)和親凳怨。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353