• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • dedecms
  • ecshop
  • z-blog
  • UcHome
  • UCenter
  • drupal
  • WordPress
  • 帝国cms
  • phpcms
  • 动易cms
  • phpwind
  • discuz
  • 科汛cms
  • 风讯cms
  • 建站教程
  • 运营技巧
您的位置:首页 > CMS教程 >建站教程 > Laravel中用Observer事件致Redis队列异常问题

Laravel中用Observer事件致Redis队列异常问题

作者:站长图库 字体:[增加 减小] 来源:互联网

站长图库向大家介绍了Laravel异常问题,Observer事件,Redis队列异常等相关知识,希望对您有所帮助

下面带大家分享记录关于Laravel Observer 导致 Redis 队列异常问题,希望对大家有所帮助!

1、业务逻辑

新建某个模型之后,利用 Observer 模型事件 Created 推入异步短信发送队列

App\Http\Controllers\UsersController

public function store(User $user){    \DB::beginTransaction();     try{        $input = request()->validated();        $user->fill($input);        $user->save();        //do something......        //其他数据表操作         \DB::commit();    } catch ($e \Exception) {        \DB::rollBack();    } }

App\Observers\UserObserver

class UserObserver{    public function created (User $user)    {        dispatch(new SmsQueue($user));    }}


2、发现异常

业务部门反馈偶尔有用户收取不到短信通知,我便查看日志发现偶尔有错误异常:No query results for model [App\Models\User]. 表示找不到对应的模型

我敲不应该啊,我是在创建模型之后再进行队列调用……,遂对业务代码再进行仔细核查猜测应该是受事务影响。

验证猜想:

public function store(User $user){    \DB::beginTransaction();     try{        $input = request()->validated();        $user->fill($input);        $user->save();        //do something......        //其他数据表操作         sleep(3); //三秒之后再提交事务                    \DB::commit();    } catch ($e \Exception) {        \DB::rollBack();    } }

果然在等待三秒之后提交队列异常已是 100% 触发。


3、原因分析

$user->save() 这个方法创建数据成功,便会一并触发调度器,将模型事件一一执行。

在事件中推送模型至队列中,而队列进程在不间断消费队列中数据。

在大部分情况下 do something 处理速度正常的话,队列进程将会照常运行。

如果在 do something 阶段偶尔出现延迟,造成事务还未 commit 而队列已经开始消费新模型;故引发上述错误。

然后我在搜索 Github Issues 记录时,发现此问题在 2015 年的一个 Issue 已经有人提出,而在 Laravel 8.X 中终于新增了对事务模型事件的支持;learnku.com/docs/laravel/8.x/eloqu... ,在社区文档似乎并没有找到相关说明~

由于我的版本是 6.x 所以用不了这个新特性[哭唧唧]~~


4、解决异常

1. 修改 MySQL 事务隔离级别(不推荐)

这里涉及到 MySQL 的事务隔离级别,InnoDB 引擎的默认隔离级别是 REPEATABLE READ,关于各个级别的区别可以在 官方文档 找到。

将隔离级别切换到 READ UNCOMMITTED 即可解决此问题,但是为了防止出现更大的问题我劝你别用这种方式~

2. 增加事件监听

查看源码得知在事务完成之后,会调用对应的事件,所以只需增加对事件的监听即可。


Laravel中用Observer事件致Redis队列异常问题


新增类 App\Handlers\TransactionHandler

class TransactionHandler{    public array $handlers;     public function __construct()    {        $this->handlers = [];    }     public function add(\Closure $handler)    {        $this->handlers[] = $handler;    }     public function run()    {        foreach ($this->handlers as $handler) {            $handler();        }        $this->handlers = [];    }}

创建辅助函数 app/helpers.php

if (! function_exists('after_transaction')) {    /*     * 事务结束之后再进行操作     * */    function after_transaction(Closure $job)    {        app()->singletonIf(\App\Handlers\TransactionHandler::class, function (){            return new \App\Handlers\TransactionHandler();        });        app(\App\Handlers\TransactionHandler::class)->add($job);    }}

创建监听 App\Listeners\TransactionListener

namespace App\Listeners;use App\Handlers\TransactionHandler;class TransactionListener{    public function handle()    {        app(TransactionHandler::class)->run();    }}

绑定监听 App\Providers\EventServiceProvider

namespace App\Providers;use App\Listeners\TransactionListener;use Illuminate\Database\Events\TransactionCommitted;use Illuminate\Database\Events\TransactionRolledBack;use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; class EventServiceProvider extends ServiceProvider{    /**     * The event listener mappings for the application.     *     * @var array     */    protected $listen = [        TransactionCommitted::class => [            TransactionListener::class        ],        TransactionRolledBack::class => [            TransactionListener::class        ]    ];}

更改调用方式 App\Observers\UserObserver

class UserObserver{ &n
  


 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • Laravel中用Observer事件致Redis队列异常问题

相关文章

  • PhotoShop制作简单的炫光残破文字效果教程
  • 介绍Javascript实现定时器倒计时
  • PHP中preg_match函数使用详解(附代码实例)
  • Photoshop详细绘制金属质感的企业标志
  • PHP使用mysqli同时执行多条sql查询语句的实例
  • Photoshop改进UI设计的一些心得技巧
  • Photoshop制作超酷的树藤装饰立体字教程
  • 怎么用Zblog做优化?
  • Javascript怎样验证手机号码
  • Node.js怎么读写json文件?方法介绍

文章分类

  • dedecms
  • ecshop
  • z-blog
  • UcHome
  • UCenter
  • drupal
  • WordPress
  • 帝国cms
  • phpcms
  • 动易cms
  • phpwind
  • discuz
  • 科汛cms
  • 风讯cms
  • 建站教程
  • 运营技巧

最近更新的内容

    • php判断两个日期之间相差多少个月份的方法
    • 掌握PHP中对数组进行排序的正确姿势
    • 如何辨别网站是合法的链接来源还是链接工厂
    • Vue多个路由绑定同一组件造成created不执行的解决办法
    • DedeCMS关键词替换问题较完美解决方案
    • 浅谈Bootstrap中的自适应屏幕
    • 数据库优化的几种方式分别是什么
    • PHP如何将数组下标去掉
    • 利用画笔及描边路径制作漂亮的金色树叶字
    • PS制作超酷黑白像素文字效果

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有