您好,登錄后才能下訂單哦!
這篇文章主要介紹了redis能不能用來做消息隊列,具有一定借鑒價值,需要的朋友可以參考下。希望大家閱讀完這篇文章后大有收獲。下面讓小編帶著大家一起了解一下。
應用場景:
例如秒殺。瞬時大量寫入訂單到數據庫,導致數據庫無法及時響應。此時可以采用Redis做消息隊列,把所有需要寫入的數據先寫入Redis消息隊列中,然后同時在服務器開啟php-cli進程循環讀取隊列中的數據,異步寫入數據庫。使用redis做消息隊列可能會出現消息丟失的情況,因為沒有消息接收的確認機制。大型程序,應該使用類似RabitMQ來做專業消息隊列。
1、使用publish/subscribe方式作為消息隊列
特點:一個消息發布者(生產者),可以對應多個消息訂閱者(消費者)。當消息發布到消息隊列的時候,所有消息訂閱者都可以收到消息。適用于分布式消息分發。client以阻塞的方式等待publish端的消息。多個消費者不能加快消息消費速度。
消息生產:
$params =json_encode(['x_uid' => $x_uid, 'phone' => $phone]); $redis->publish('test',$params); //test表示發布的頻道名字
消息消費(php-cli模式運行):
$redis = new Redis(); $redis->pconnect('127.0.0.1'); //必須用pconnect長連接 //設置redis連接永遠不超時。默認60s超時斷開連接 $redis->setOption(Redis::OPT_READ_TIMEOUT, -1); $redis->subscribe(array('test'), 'callback'); //test表示頻道名字,callback 回調函數名 functioncallback($redis, $chan, $msg){ //對收到的消息進行處理函數 $params = json_decode($msg,true); .... }
pconnect和connect區別:
connect:腳本結束之后連接就釋放了。
pconnect:腳本結束之后連接不釋放,連接保持在php-fpm進程中。
所以使用pconnect代替connect,可以減少頻繁建立redis連接的消耗。
2、使用list作為redis消息隊列
特點:一個消息生產者,對應一個消息消費者。多個消費者可以加快消息消費速度。
消息生產:
$redis =newRedis(); $redis->connect('127.0.0.1'); //將需要寫入數據庫的數據全部push到隊列(復雜數據可以先json編碼成字符串) $list = json_encode(['x_uid' => $x_uid, 'phone' => $phone, 'goods_id' => $goodsId, 'add_time' => time(), 'num_field' => $num_field]); $redis->lpush('winer',$list);
注意:brpop消費數據如果沒有成功寫入數據庫,會導致數據丟失。強烈要求生產數據時,二次備份到redis或文件中。
消息消費(php-cli模式運行):
注意:MySQL不主動關閉連接的情況下,一次連接最長八小時后自動斷開。
<?php //鏈接數據庫 $conn = mysqli_connect("localhost","root","root"); if(!$conn){ die("連接數據庫失敗:". mysqli_error()); } mysqli_select_db($conn,"api"); //字符轉換,讀庫 mysqli_query($conn,"set character set 'utf8'"); //寫庫 mysqli_query($conn,"set names 'utf8'"); //連接本地的 Redis 服務 $redis =newRedis(); $redis->connect('127.0.0.1',6379); //設置redis連接永遠不超時。默認60s超時斷開連接 $redis->setOption(Redis::OPT_READ_TIMEOUT,-1); echo 'Listening...'; $i =1; while(true){ $data = $redis->brpop('winer',0); // 0表示沒有接收到參數的情況下,永遠不超時斷開 $info = json_decode($data[1],true); $x_uid = $info['x_uid']; $phone = $info['phone']; $goods_id = $info['goods_id']; $add_time = $info['add_time']; $num_field = $info['num_field']; //將數組寫入數據庫、訂單 $sql = "insert into hd_hengda11_order (`x_uid`,`phone`,`goods_id`,`add_time`) values ($x_uid,$phone,$goods_id,$add_time)" $re = mysqli_query($conn,$sql); echo $i.'_ok||'; $i++; } ?>
其他:
秒殺場景防止商品超賣:
1、數據庫中設置商品數量為無符號型,即不允許負數。當更新商品數量到負數時,返回false。
2、商品數量存在Redis的list隊列中,每次搶購就pop刪除一個元素出隊列。
//存放商品數量的隊列 for($j =1; $j <=10; $j++){ /設置商品數量為10 $re =Redis::lpush(gooods_count,1); }
判斷商品數量邏輯
$count=Redis::lpop('gooods_count'); //$count = Redis::llen('gooods_count'); //llen判斷隊列長度 if(!$count){ return'已經搶光了哦'; }
感謝你能夠認真閱讀完這篇文章,希望小編分享redis能不能用來做消息隊列內容對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,遇到問題就找億速云,詳細的解決方法等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。