PHP系列 | PDO::prepare(): send of 68 bytes failed with errno=32 Broken pipe


設計場景

1、開啟Redis的鍵空間過期事件(鍵過期發布任務),創建訂單創建一個過期的key,按照訂單號為key,設置過期時間。

2、通過Redis的訂閱模式(持久阻塞),獲取到訂單號進行組裝。

3、Redis通過訂閱模式獲取到已經過期的key,把該key加入think-queue 任務隊列(依賴於Redis的隊列,隊列配置推薦使用Redis存儲消息)。

4、開啟一個隊列的消費守護進程,進行消費。如果消費失敗,則任務隊里不會自動刪除

遇到的問題

cli 模式報錯

[2019-11-20T14:33:25+08:00][ error ] [8]PDO::prepare(): send of 68 bytes failed with errno=32 Broken pipe
error

 相關代碼

class RedisSubscribe
{
    public function subscribe()
    {
        $redis = BaseRedis::plocal();
        $redis->setOption(\Redis::OPT_READ_TIMEOUT, -1);
        $redis->psubscribe(array('__keyevent@1__:expired'), function ($redis, $pattern, $chan, $msg) {
            Log::info('[訂閱事件] 過期KEY ' . $msg);
            $flag = strstr($msg,":");
            if(empty($flag)){
                Log::error('[訂閱事件] 非法的消息類型 '.$msg);
                return false;
            }
            $originData = explode(':',$msg);
            $event_key = $originData[1]??'0';
            $event_status = $originData[0]??'0';
            if($event_status == RedisTaskQueue::ORDER_TIMEOUT_EVENT){
                Log::info('[訂閱事件] 訂單超時事件 '.$event_key);
                $order = PayOrderModel::get(['order_no' => $event_key]);
                    Log::info('[訂閱事件] 訂單 '.$event_key);
                    if ($order['status'] == 0) {
                        $updateData = [
                            'id' => $order['id'],
                            'status' => 2,
                            'notify_status' => 0,
                            'pay_time' => time(),
                            'remark' => '超時隊列事件'
                        ];
                        $res = PayOrderModel::update($updateData);
                        Log::info('[訂閱事件] 更新訂單 ' . json_encode($res));
                    }
            }
        });
    }
}

 問題就出現在以上代碼中查詢和更新數據庫問題

$order = PayOrderModel::get(['order_no' => $event_key]); 

問題分析,這里采用的Redis的訂閱模式,持久性的

解決辦法,通過任務隊列解決

$isPushed = redis_queue(RedisTaskQueue::QUEUE_EVENT, $data);

 把redis訂閱服務獲取到的信息,發布think-queue隊列中,在隊列中在進行處理數據庫相關操作  

第二天出錯

 

[2019-11-21T09:12:41+08:00][ error ] [隊列事件] 隊列執行失敗 SQLSTATE[HY000]: General error: 2006 MySQL server has gone away|#0 /home/www/web/wiot.tinywan.com/thinkphp/library/think/db/Connection.php(844): think\db\Connection->query('SELECT * FROM `...', Array, false, false)
#1 /home/www/web/www.tinywan.com/thinkphp/library/think/db/Query.php(3132): think\db\Connection->find(Object(think\db\Query))
#2 /home/www/web/www.tinywan.com/thinkphp/library/think/db/Query.php(3193): think\db\Query->find(NULL)

數據庫配置開啟需要斷線重連(第一次出錯的時候正式環境沒有開啟該配置參數

// 是否需要斷線重連
'break_reconnect' => false,  

  

 

參考:

https://github.com/RunnerLee/fastd-eloquent/issues/5  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM