首頁 資料庫 Redis redis可以做訊息隊列嗎

redis可以做訊息隊列嗎

Jul 05, 2019 pm 03:31 PM

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相關知識,請造訪

Redis使用教學欄位!

以上是redis可以做訊息隊列嗎的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
2 週前 By 尊渡假赌尊渡假赌尊渡假赌
倉庫:如何復興隊友
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
2 週前 By 尊渡假赌尊渡假赌尊渡假赌
倉庫:如何復興隊友
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱門文章標籤

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

如何在Redis群集中選擇一個碎片鍵? 如何在Redis群集中選擇一個碎片鍵? Mar 17, 2025 pm 06:55 PM

如何在Redis群集中選擇一個碎片鍵?

Redis查看版本有快捷方式嗎 Redis查看版本有快捷方式嗎 Mar 04, 2025 pm 05:59 PM

Redis查看版本有快捷方式嗎

Redis如何通過命令行查看版本 Redis如何通過命令行查看版本 Mar 04, 2025 pm 06:00 PM

Redis如何通過命令行查看版本

如何將Redis用於酒吧/子消息傳遞? 如何將Redis用於酒吧/子消息傳遞? Mar 17, 2025 pm 06:48 PM

如何將Redis用於酒吧/子消息傳遞?

Redis不同版本兼容性如何 Redis不同版本兼容性如何 Mar 04, 2025 pm 05:57 PM

Redis不同版本兼容性如何

Redis版本號是什麼樣的 Redis版本號是什麼樣的 Mar 04, 2025 pm 06:01 PM

Redis版本號是什麼樣的

如何在REDIS中實施緩存無效策略? 如何在REDIS中實施緩存無效策略? Mar 17, 2025 pm 06:46 PM

如何在REDIS中實施緩存無效策略?

如何將Redis用於工作隊列和背景處理? 如何將Redis用於工作隊列和背景處理? Mar 17, 2025 pm 06:51 PM

如何將Redis用於工作隊列和背景處理?

See all articles