新手问题 Sidekiq RecordNotFound

karrra · 2015年12月17日 · 最后由 jimrokliu 回复于 2015年12月20日 · 2865 次阅读

google 了半天都说是 sidekiq 执行太快了,按照 github 上面的 trouble shooting 用了 after_commit 和 perform_in 来延迟执行但是还是偶尔会出现找不到对象,然后我在 idle 里面点了 retry all 过一会还是会抛一样错,可以确定数据库里面是有这些纪录的,请问这种情况要怎么排错比较好?

能不能给出 sidekiq 执行太快,after_commit 之后依然找不到对象的内容的 URL,我想围观一下。

实在不行可以设置延时任务,不要立即执行 sidekiq 任务,等几秒再去看数据库,如果还没有,那就应该是环境配置什么的问题了,跟 commit 无关

#2 楼 @alucardpj 我就是设置了延时任务,2 分钟之后才执行

#3 楼 @karrra 你给出的 Wiki 上说明了在 after_commit 的时候 enqueue 就没问题,会受影响的只有测试环境(且附带了解决方案)。难道 after_commit 在你这里也有问题?你用的数据库是什么?

#5 楼 @lgn21st 我用的 mysql,ucloud 的服务器

#6 楼 @karrra 说实话,我自己用 MySQL +InnoDB 很久,用 after_commit 拿到 id 然后 enqueue,从未遇到过你说的情况,看看其他人有没有办法。

#7 楼 @lgn21st 总之谢谢大神了,其实项目用到 sidekiq 的地方也不少,还是第一次遇到这个问题,各种费解

你是不是几个实例连的一个 redis

#9 楼 @zhang_soledad 不好意思,具体是指什么?不是很明白你的意思

after_commit是不会有问题的 你可能是多个项目都用了 sidekiq,共享一个 redis 的 db 你这个项目推进去的任务 被其他 client 取出来执行了

你的 Model 写入速度太慢了,Sidekiq 从数据库里读取还读不到这个记录。你可以加一个 memached,先将 Model 写入 memcached。

#12 楼 @jimrokliu 不存在 model 写入太慢这种情况,如果是支持事务的数据库,只有在 SQL 执行完 COMMIT 后,才会触发 after_commit 的 callback,楼主的问题我觉得不可能是 after_commit 的问题,或者只有见到代码,或者在实际项目中深入分析才能找到原因。

#13 楼 @lgn21st 我曾经遇到过这样的问题,用的是 mysql 的数据库,rails 的 after_commit 触发 sidekiq 执行时,如果我在 sidekiq 中增加一秒的延迟,是可以读到数据。也许这个 after_commit 是指 model 这层发送出 commit 的指令,后续 mysql 还要写事务日志,刷新内存缓冲区,在一个很小的窗口期,另外的 mysql client 是读不到这个值的。

#14 楼 @jimrokliu 当 model 发送 commit 指令,MySQL 执行之后,才会返回 id,在发送之前是拿不到的,这是否说明 COMMIT 已经被 MySQL 执行了?

#14 楼 @jimrokliu #15 楼 @lgn21st 这还要看数据库的隔离级别吧,MySQL 默认隔离级别应该是没问题的,但是采用更高级别的,那就可能还要等一等了,特别是 APP 服务器和数据库服务器之间网络延迟比较大的时候。

仔细看了一下日志,确实是 11 楼说的这种情况,主要是测试服务器上的项目比较多所以一直没在意,非常感谢 @zhang_soledad ,也谢谢其他各位大神的见解,又学会了很多🙏

#18 楼 @karrra 貌似多个 sidekiq 共享 redis 业不会有这个问题吧,sidekiq 要想利用系统的多颗 cpu 的话就要启动多个。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号