一次对 horizon 是否缓存的误判,导致怀疑 Redis 有 BUG,最终自己解决的经历

  • 由于我在 《使用 Supervisor 管理 horizon,每次部署新的代码不需要做任何事》 一文中,对horizon是否缓存产生了理解上的偏差,当时测试的结果是修改了代码后,然后立刻就可以看到变化,不需要重新启动horizon。这个观念导致我在后面写完 《Laravel 5.7 以队列方法发送邮件(三种场景)》 后,发现了一个BUG:就是每次注册新用户,redis队列发送注册邮件,消息提示那里都新增一个计数。后来再一测试,发现重置邮件,重新发送邮件,都会新增一个计数。
  • 仔细检查了代码,发现涉及到 notification_count 的地方只有一句,就是在我在 《此节复写 trait 中的 notify 方法,会导致框架自带的「重新发送邮件」的功能失效,建议在 user model 类中新增一个 topicNofity 方法单独处理即可》 中新建的 topicNotify 方法,而此方法只会在 回复主题时才会调用呀。我又打了断点,结果根本就不会停下来。说明根本就没有执行到这里呀。
  • 那还有什么地方会自动变化 notification_count 呢?于是开始看源码,一层层看下去,最后终于发现是在 \Predis\Connection\StreamConnection::write 中改变了的,代码如下:

    /**
        * Performs a write operation over the stream of the buffer containing a
        * command serialized with the Redis wire protocol.
        *
        * @param string $buffer Representation of a command in the Redis wire protocol.
        */
    protected function write($buffer)
    {
        $socket = $this->getResource();
    
        while (($length = strlen($buffer)) > 0) {
            $written = @fwrite($socket, $buffer);
    
            if ($length === $written) {
                return;
            }
    
            if ($written === false || $written === 0) {
                $this->onConnectionError('Error while writing bytes to the server.');
            }
    
            $buffer = substr($buffer, $written);
        }
    }
  • 这是什么鬼。。。
  • 开始怀疑是不是redis有BUG了。。。
  • 后来又试了下,发现将.env中的QUEUE_CONNECTION改为sync,结果就不会出现这个BUG了。改回redis,又出现这个BUG了。难道真的是redis有问题?不可能啊。。。
  • 后来灵机一动,将数据库的 notification_count字段改为 notification_count1,果然就出错了,然后我去看错误日志。。结果发现有这么一句:
    #8 /home/vagrant/Code/larabbs/app/Models/User.php(32): Illuminate\\Database\\Eloquent\\Model->increment('notification_co...')
  • 这不就是调用了increment么?但是调用的行数不对啊,我现在的代码是在75行。。于是终于真相大白了!
  • 于是重启horizon: sudo supervisorctl restart laravel_horizon
  • 再注册发送邮件,没有出现提示了。检查数据库的notification_count 也没有自动+1!果然就是缓存的代码啊!!
  • 原来:每次部署新的代码需要重启,是在涉及到redis的情况下才需要的,如果 QUEUE_CONNECTION为sync,那么就是不用redis,自然就不会出现这个问题了。。

    以后遇到类似bug,首先要看自己代码问题,如果不是看到的代码问题,那么很可能就是缓存的问题!

本作品采用《CC 协议》,转载必须注明作者和本文链接
日拱一卒
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
讨论数量: 1

如同php artisan queue:work 监听队列,每次更新代码要重启

6年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
未填写
文章
92
粉丝
87
喜欢
152
收藏
121
排名:72
访问:11.3 万
私信
所有博文
社区赞助商