redis入門

這篇文章是我個(gè)人對(duì)redis的一些理解,可以幫助大家系統(tǒng)的認(rèn)識(shí)redis纸泄。本文的目標(biāo)讀者是使用過redis条篷,但對(duì)redis了解不深的朋友。文章內(nèi)容以redis為主芦倒,也會(huì)少量提到memcached艺挪。文章從redis的設(shè)計(jì)目的、工作模式兵扬、應(yīng)用場(chǎng)景等方面闡述麻裳,最后會(huì)講解一些具體的應(yīng)用場(chǎng)景,還會(huì)夾帶一些代碼作為“干貨”器钟。

鑒于本人水平有限津坑,文中如有不準(zhǔn)確的內(nèi)容,敬請(qǐng)斧正傲霸。

redis是什么

redis是一種內(nèi)存型的數(shù)據(jù)存儲(chǔ)器疆瑰,使用場(chǎng)景

  • 數(shù)據(jù)庫(kù)
  • 緩存
  • 消息代理(message broker)

同memcached對(duì)比
memcached是分布式的內(nèi)存對(duì)象緩存系統(tǒng),設(shè)計(jì)意圖為通過緩解數(shù)據(jù)庫(kù)壓力來加快web應(yīng)用的響應(yīng)速度昙啄。

上面的描述分別被放在了redis和memcached的官網(wǎng)首頁(yè)最顯眼的位置穆役,這也回答了redis和memcached的本質(zhì)區(qū)別。

redis的工作模式

redis的工作模式為單進(jìn)程梳凛,這意味著redis只能利用到一個(gè)cpu內(nèi)核耿币。
redis對(duì)請(qǐng)求的處理是串行的,對(duì)于同時(shí)涌進(jìn)來的多個(gè)請(qǐng)求伶跷,redis首先把請(qǐng)求存入隊(duì)列掰读,按請(qǐng)求到達(dá)的先后順序串行處理秘狞。

了解單進(jìn)程和串行這兩個(gè)特點(diǎn)叭莫,有助于我們使用redis時(shí)“揚(yáng)長(zhǎng)避短”。

之前有同事提到過烁试,為何redis不適合存儲(chǔ)大塊的數(shù)據(jù)雇初?從redis的工作模式我們可以窺知一二:大塊的數(shù)據(jù)意味著需要較長(zhǎng)的io時(shí)間,包括內(nèi)存io和網(wǎng)絡(luò)的io减响,cpu資源在io過程中是一直被占用的靖诗,這會(huì)阻塞其它請(qǐng)求郭怪,從而影響redis的整體性能。

數(shù)據(jù)類型

大家對(duì)redis的數(shù)據(jù)類型已經(jīng)比較熟悉了刊橘,主要有以下5種鄙才。

  • string
  • list
  • hash
  • set
  • sorted set

各種數(shù)據(jù)類型的常用操作

string

  • set,get促绵,setnx攒庵,setex,psetex
  • 拼接
  • 增加败晴、減少(整數(shù)型字符串)
  • 位操作

list

  • 入列浓冒,出列(這兩個(gè)命令都有阻塞模式)
  • 按排位獲取部分元素

hash

  • 設(shè)置某個(gè)索引
  • 獲取某個(gè)索引
  • 增加/減少某個(gè)索引的值(整數(shù)型字符串)
  • 獲取所有索引的值

set

集合是一個(gè)數(shù)學(xué)概念,啰嗦提一下:集合中的元素都是唯一的

  • 加入元素
  • 刪除元素
  • 檢查元素是否在集合
  • 獲取集合中的元素?cái)?shù)量
  • 取差集/并集/交集
  • 元素轉(zhuǎn)移(從集合a移至集合b)

zset

有序集合尖坤,每個(gè)元素都有一個(gè)分值稳懒,用于對(duì)元素進(jìn)行排序

  • 取交集/并集
  • 獲取一個(gè)元素的rank
  • 獲取分值在某個(gè)范圍內(nèi)的元素?cái)?shù)量
  • 獲取分值在某個(gè)范圍內(nèi)的元素
  • 按rank范圍獲取元素

redis事務(wù)

redis事務(wù)和我們熟悉的mysql事務(wù)有所區(qū)別,它們的相同在于都是對(duì)一個(gè)或一組命令的打包執(zhí)行慢味,不同的地方在于redis事務(wù)不可回滾场梆。

redis的事務(wù)具有原子性,一個(gè)事務(wù)的執(zhí)行有兩種結(jié)果

  • 完全執(zhí)行
  • 完全不執(zhí)行

一些不可抗力因素除外纯路,如服務(wù)掛掉辙谜,服務(wù)器斷電。redis事務(wù)是一個(gè)獨(dú)立的請(qǐng)求感昼,執(zhí)行過程中會(huì)阻塞其它請(qǐng)求装哆。

實(shí)現(xiàn)redis事務(wù)有以下兩種方式

  • multi-exec
  • lua腳本

multi-exec

127.0.0.1:6380[1]> set counter1 1
OK
127.0.0.1:6380[1]> set counter2 2
OK
127.0.0.1:6380[1]> set counter3 3
OK
127.0.0.1:6380[1]>
127.0.0.1:6380[1]>
127.0.0.1:6380[1]> multi
OK
127.0.0.1:6380[1]> incr counter1
QUEUED
127.0.0.1:6380[1]> sadd counter2 1
QUEUED
127.0.0.1:6380[1]> incr counter3
QUEUED
127.0.0.1:6380[1]> exec
1) (integer) 2
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
3) (integer) 4

從上面的事務(wù)執(zhí)行輸出可以看到,我們的sadd執(zhí)行出錯(cuò)了定嗓,原因是操作的數(shù)據(jù)類型不正確蜕琴,但redis沒有中止整個(gè)事務(wù),而是繼續(xù)往下執(zhí)行宵溅。redis這么做是有道理的凌简,見參考文獻(xiàn)1

multi-exec和watch的組合可以實(shí)現(xiàn)類似于mysql事務(wù)的功能恃逻,如果被watch的key在事務(wù)執(zhí)行前被修改了雏搂,redis會(huì)放棄執(zhí)行事務(wù)。

lua腳本

和multi-exec相比寇损,lua腳本的優(yōu)勢(shì)在于靈活性凸郑,也可以減少一定的網(wǎng)絡(luò)時(shí)間消耗(為什么?)矛市。

鑒于redis的工作模式芙沥,不建議用lua腳本實(shí)現(xiàn)耗時(shí)較長(zhǎng)的事務(wù)。
下面模擬了lua腳本的執(zhí)行阻塞其它請(qǐng)求的場(chǎng)景,大家可以親自試一下而昨。

client 1

eval "local i=0; while(i<1000000) do redis.call('keys', '*'); i=i+1; end" 0

client 2

incr counter

redis的實(shí)際應(yīng)用

類型:string
命令:setnx name alice |set name alice NX
返回true則鎖定成功救氯,否則鎖定失敗
了解了redis的工作模式,就知道為什么用redis實(shí)現(xiàn)鎖是如此容易了歌憨。用memcache也可以實(shí)現(xiàn)鎖着憨,但代碼層面要復(fù)雜一些,參見memcached.cas务嫡。

事件隊(duì)列

類型:zset
命令:zadd享扔,zrangebyscore,zrem
適合存儲(chǔ)一些需要順序處理的事件植袍,將事件的score值設(shè)為時(shí)間戳或自增id即可惧眠。為什么用list不可以?

計(jì)數(shù)器

類型:string
命令:incr

抽獎(jiǎng)限額

類型:string
命令:incrby
某活動(dòng)的現(xiàn)金紅包每天最多只能發(fā)送10000元于个。下面是這段邏輯的偽代碼氛魁,如果能夠舉一反三,這段代碼將大有用武之地厅篓。大家可以用并發(fā)測(cè)試工具測(cè)試這段代碼秀存,如果發(fā)現(xiàn)了bug,或者能有更好的實(shí)現(xiàn)方式羽氮,請(qǐng)不要告訴我 -_-

$key = 'max_amount';
$amountLimit = 10000;

if (!$currAmount = Redis::get($key)) {
    $currAmount = 9990;          // 從持久化數(shù)據(jù)庫(kù)獲取當(dāng)前已發(fā)放金額
    // 初始化
    Redis::setnx($key, $currAmount);
}

if ($currAmount >= $amountLimit) {
    // 超出限額退出
}

// 抽獎(jiǎng)金額
$rewardAmount = 10;
if ($rewardAmount > $amountLimit - $currAmount) {
    $rewardAmount = $amountLimit - $currAmount;
}
if (Redis::incrby($key, $rewardAmount) > $amountLimit) {
    // 超出限額退出
} else {
    // 成功抽獎(jiǎng)
}

初始化為何用setnx或链,用set可以嗎?
最后為何使用incrby档押,不用可以嗎澳盐?

總結(jié)

文章內(nèi)容不多,所謂的干貨更少令宿,這和作者的水平有關(guān)叼耙,也和文章的定位有關(guān)。細(xì)心的朋友可能發(fā)現(xiàn)了粒没,文中有一些內(nèi)容是帶有問號(hào)的筛婉,有興趣的朋友可以加以思考。

如果這篇文章能幫到你癞松,不妨點(diǎn)個(gè)贊爽撒;如果能給我一些具體的反饋,那就完美了响蓉。

參考文獻(xiàn)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末硕勿,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子厕妖,更是在濱河造成了極大的恐慌首尼,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件言秸,死亡現(xiàn)場(chǎng)離奇詭異软能,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)举畸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門查排,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人抄沮,你說我怎么就攤上這事跋核。” “怎么了叛买?”我有些...
    開封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵砂代,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我率挣,道長(zhǎng)刻伊,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任椒功,我火速辦了婚禮捶箱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘动漾。我一直安慰自己丁屎,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開白布旱眯。 她就那樣靜靜地躺著晨川,像睡著了一般。 火紅的嫁衣襯著肌膚如雪删豺。 梳的紋絲不亂的頭發(fā)上础爬,一...
    開封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音吼鳞,去河邊找鬼看蚜。 笑死,一個(gè)胖子當(dāng)著我的面吹牛赔桌,可吹牛的內(nèi)容都是我干的供炎。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼疾党,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼音诫!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起雪位,我...
    開封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤竭钝,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體香罐,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡卧波,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了庇茫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片港粱。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖旦签,靈堂內(nèi)的尸體忽然破棺而出查坪,到底是詐尸還是另有隱情,我是刑警寧澤宁炫,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布偿曙,位于F島的核電站,受9級(jí)特大地震影響羔巢,放射性物質(zhì)發(fā)生泄漏遥昧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一朵纷、第九天 我趴在偏房一處隱蔽的房頂上張望炭臭。 院中可真熱鬧,春花似錦袍辞、人聲如沸鞋仍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)威创。三九已至,卻和暖如春谎懦,著一層夾襖步出監(jiān)牢的瞬間肚豺,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工界拦, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留吸申,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓享甸,卻偏偏與公主長(zhǎng)得像截碴,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蛉威,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容