为了账号安全,请及时绑定邮箱和手机立即绑定

请教各位一个问题,求解答:先提交事务还是先触发事件?跪求!

请教各位一个问题,求解答:先提交事务还是先触发事件?跪求!

动漫人物 2019-10-08 13:20:14
/***创建一个用户和用户的关联数据*@paramarray$userData*@paramarray$userFinanceData*@returnUserModel*@throws\Exception*/publicfunctionregister($userData,$userFinanceData){$db=UserModel::query()->getConnection();try{$db->beginTransaction();$user=UserModel::create($userData);$userFinanceData['user_id']=$user->id;FinanceAccountModel::create($userFinanceData);//事件触发放在这里1?$db->commit();}catch(\Exception$exception){$db->rollBack();throw$exception;}//事件触发放在这里2?event(newUserCreatedEvent($user));return$user;}如果放在[1]处,那么如果数据库事务提交失败,事件却发出去了。导致事件消费者取不到该用户的数据。如果放在[2]处,那么如果事件触发失败(例如redis连接错误),用户却创建成功了,但是创建用户后需要做的一些事情没有做,导致用户数据不完整。怎么做才好?
查看完整描述

2 回答

?
慕妹3242003

TA贡献1824条经验 获得超6个赞

这种问题,你没法避免的,分布式事务的问题。有一种可以参考下你在数据库表里面建立一个事件表,就是要发的事件,随事务一起提交。提交完后,你再去发了,发完记得在数据库的记录上做一个标记了,一个状态是新建未发送,一个是已发送。另外,还得有一个线程池去扫那个表,去发那些发失败的。接受事件的地方,还得做幂等。如果要更可靠的话,事件表的标记在加一个已处理,反正要就是比较麻烦了,要考虑的很多
                            
查看完整回答
反对 回复 2019-10-08
?
富国沪深

TA贡献1790条经验 获得超9个赞

给一个方案,用户数据增加一个step字段,表示生成过程的整个步骤,每完成一步改一下,然后定时查看数据库里没有完成的数据,然后继续执行,可以保证最终一致性。这样设计的一个要求是,事件触发的处理程序是幂等的,同一个事件,只会触发一次或者说触发多次不会有副作用
//生成用户
$db->beginTransaction();
$user=UserModel::create($userData);
$user->step=1;
$db->commit();
//触发事件
$db->beginTransaction();
event(newUserCreatedEvent($user));
$user->step=2;
$db->commit();
定时任务
//获取生成3分钟后还没发通知的用户数据
$sql='select*formuserwherestatus=1andaddtime...
//重新发送
event(newUserCreatedEvent($user));
$user->step=2;
$db->commit();
                            
查看完整回答
反对 回复 2019-10-08
  • 2 回答
  • 0 关注
  • 257 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信