一次对 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 协议》,转载必须注明作者和本文链接
如同
php artisan queue:work
监听队列,每次更新代码要重启