Redis搶購(gòu)設(shè)計(jì)章

搶購(gòu)是如今很常見的一個(gè)應(yīng)用場(chǎng)景带迟,主要需要解決的問題有兩個(gè):

1 高并發(fā)對(duì)數(shù)據(jù)庫(kù)產(chǎn)生的壓力

2 競(jìng)爭(zhēng)狀態(tài)下如何解決庫(kù)存的正確減少(“超賣”問題)

對(duì)于第一個(gè)問題夕春,已經(jīng)很容易想到用緩存來處理?yè)屬?gòu)飘诗,避免直接操作數(shù)據(jù)庫(kù)虱肄,例如使用Redis谜叹。重點(diǎn)在于第二個(gè)問題,我們看看下面一種常規(guī)的實(shí)現(xiàn)代碼:


require('predis/src/Autoloader.php');

$redis = new Predis\Client(array(

'scheme' => 'tcp',

'host'? => '127.0.0.1',

'port'? => '6379'

));

//redis 登錄

$redis->auth('123456');

//庫(kù)存

$num = 10;

//用戶id

$user_id = $_SESSION['user_id'];

//檢查庫(kù)存

$len = $redis->llen('order:1');

if($len >= $num){

exit('已經(jīng)搶光了');

}

//把搶到的用戶存入到列表中

$result = $redis->lpush('order:1',$user_id);

if($result){

echo '搶到了';

}

?>

如果代碼正常運(yùn)行括堤,列表order:1中最多只能存儲(chǔ)10個(gè)用戶的id碌秸,因?yàn)閹?kù)存只有10個(gè)。

然而悄窃,在使用Apache AB工具模擬很多用戶并發(fā)請(qǐng)求時(shí)哮肚,最后發(fā)現(xiàn)order:1中總是超過10個(gè)用戶,也就是出現(xiàn)了“超賣”广匙。

問題就出在這一段代碼:

//檢查庫(kù)存

$len = $redis->llen('order:1');

if($len >= $num){

exit('已經(jīng)搶光了');

}

在搶購(gòu)進(jìn)行到一定程度,假如現(xiàn)在已經(jīng)有9個(gè)人搶購(gòu)成功恼策,又來了3個(gè)用戶同時(shí)搶購(gòu)鸦致,這時(shí)if條件將會(huì)被繞過,這三個(gè)用戶都能搶購(gòu)成功涣楷。而實(shí)際上只有一件庫(kù)存可以搶了分唾。

在高并發(fā)下,很多不是問題的狮斗,都成了問題绽乔。要解決“超賣”問題,核心在于保證檢查庫(kù)存時(shí)的操作是依次執(zhí)行的碳褒,形象的說就是把“多線程”轉(zhuǎn)成“單線程”折砸。即使有很多用戶同時(shí)到達(dá),也是一個(gè)個(gè)檢查并給與搶購(gòu)資格沙峻,一旦庫(kù)存搶盡睦授,后面的用戶就無法繼續(xù)了。

我們需要使用Redis的原子操作來實(shí)現(xiàn)這個(gè)“單線程”摔寨。首先我們把庫(kù)存存在goods:1這個(gè)列表中去枷,假設(shè)有10件庫(kù)存,就往列表中push10個(gè)數(shù)是复,這個(gè)數(shù)沒有實(shí)際意義删顶,僅僅代表一件庫(kù)存。搶購(gòu)開始后淑廊,每到來一個(gè)用戶逗余,就從goods:1中pop一個(gè)數(shù),表示用戶搶購(gòu)成功季惩。當(dāng)列表為空時(shí)猎荠,表示已經(jīng)被搶光了坚弱。因?yàn)榱斜淼膒op操作是原子的,即使有很多用戶同時(shí)到達(dá)关摇,也是依次執(zhí)行的荒叶。搶購(gòu)的示例代碼如下:


//搶購(gòu)

require('predis/src/Autoloader.php');

$redis = new Predis\Client(array(

'scheme' => 'tcp',

'host'? => '127.0.0.1',

'port'? => '6379'

));

$redis->auth('123456');

//用戶ID

$user_id = $_SESSION['user_id'];

$check = $redis->lpop('goods:1');

if(!$check){

exit('搶光了');

}

$result = $redis->lpush('order:1',$user_id);

if($result){

echo '搶購(gòu)成功';

}

?>


用戶搶購(gòu)成功后,我們將用戶ID存入了order:1列表中输虱。接下來我們可以引導(dǎo)這些用戶去完成訂單的其他步驟些楣,這里才涉及到與數(shù)據(jù)庫(kù)的交互。最終只有很少的人走到這一步宪睹,也就解決的數(shù)據(jù)庫(kù)的壓力問題愁茁。

為了檢測(cè)實(shí)際效果,我使用Apache AB工具模擬10亭病、20鹅很、1000個(gè)用戶并發(fā)進(jìn)行搶購(gòu),經(jīng)過大量的測(cè)試罪帖,最終搶購(gòu)成功的用戶始終為10促煮,沒有出現(xiàn)“超賣”。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末整袁,一起剝皮案震驚了整個(gè)濱河市菠齿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌坐昙,老刑警劉巖绳匀,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異炸客,居然都是意外死亡疾棵,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門痹仙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來陋桂,“玉大人,你說我怎么就攤上這事蝶溶∈壤” “怎么了?”我有些...
    開封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵抖所,是天一觀的道長(zhǎng)梨州。 經(jīng)常有香客問我,道長(zhǎng)田轧,這世上最難降的妖魔是什么暴匠? 我笑而不...
    開封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮傻粘,結(jié)果婚禮上每窖,老公的妹妹穿的比我還像新娘帮掉。我一直安慰自己,他們只是感情好窒典,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開白布蟆炊。 她就那樣靜靜地躺著,像睡著了一般瀑志。 火紅的嫁衣襯著肌膚如雪涩搓。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天劈猪,我揣著相機(jī)與錄音昧甘,去河邊找鬼。 笑死战得,一個(gè)胖子當(dāng)著我的面吹牛充边,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播常侦,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼浇冰,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了刮吧?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤掖蛤,失蹤者是張志新(化名)和其女友劉穎杀捻,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蚓庭,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡致讥,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了器赞。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片垢袱。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖港柜,靈堂內(nèi)的尸體忽然破棺而出请契,到底是詐尸還是另有隱情,我是刑警寧澤夏醉,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布爽锥,位于F島的核電站,受9級(jí)特大地震影響畔柔,放射性物質(zhì)發(fā)生泄漏氯夷。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一靶擦、第九天 我趴在偏房一處隱蔽的房頂上張望腮考。 院中可真熱鬧雇毫,春花似錦、人聲如沸踩蔚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)寂纪。三九已至席吴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間捞蛋,已是汗流浹背孝冒。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拟杉,地道東北人庄涡。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像搬设,于是被迫代替她去往敵國(guó)和親穴店。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

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