• 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): thinkdbConnection->query('SELECT * FROM `...', Array, false, false)
    #1 /home/www/web/www.tinywan.com/thinkphp/library/think/db/Query.php(3132): thinkdbConnection->find(Object(thinkdbQuery))
    #2 /home/www/web/www.tinywan.com/thinkphp/library/think/db/Query.php(3193): thinkdbQuery->find(NULL)

    数据库配置开启需要断线重连(第一次出错的时候正式环境没有开启该配置参数

    // 是否需要断线重连
    'break_reconnect' => false,  

      

    参考:

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

  • 相关阅读:
    OAccflow集成sql
    集成备注
    CCflow与基础框架组织机构整合
    Jeecg_Jflow整合记录
    Problem opening .cshtml files
    The document cannot be opened. It has been renamed, deleted or moved.
    js中!和!!的区别及用法
    hdu 4757 Tree(可持久化字典树)
    Tomcat 学习进阶历程之Tomcat架构与核心类分析
    BZOJ 3000(Big Number-Stirling公式求n!近似值)
  • 原文地址:https://www.cnblogs.com/tinywan/p/11898671.html
Copyright © 2020-2023  润新知