應用場景:
例如秒殺。瞬時大量寫入訂單到資料庫,導致資料庫無法及時回應。此時可以採用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);
<?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++; } ?>
//存放商品数量的队列 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可以做訊息隊列嗎的詳細內容。更多資訊請關注PHP中文網其他相關文章!