请问 django 的 models 的 singal 是否会不够稳定而导致遗漏?

2017-05-29 04:35:04 +08:00
 huisezhiyin
我在项目中使用了 receiver 来监测 django models(mysql)的 post_save 信号, 这个 receiver 发送一个异步任务至 celery,异步任务写入数据至 redis,最后由一个脚本取出数据来进行统计任务。

receiver 的写法如下:

@receiver(post_save, sender=test_models)
def record_processor(sender, instance, **kwargs):
tasks.test_task.apply_async(args=[instance.id])

异步任务(celery)如下:

@app.task(bind=True)
def record_test(self, test_models_id):
try:
test = test_models.objects.get(id=test_models_id)
except:
return
date = datetime.now().date()
key2 = "{0}:{1}".format(date, "test_num")
pipe = r.pipeline()
pipe.incr(key2)
pipe.expire(key2, expired_time)
pipe.execute()


但在整个项目工作过程中,只有约十分之一的数据发送到了 redis 中——异步任务没有报错提醒。我不确定是哪个环节出了问题(从经验来看似乎 django 中 sql 的 singal 发送会有些不够稳定),想询问一下可能的原因以及解决的方案
2129 次点击
所在节点    Python
6 条回复
shellfly
2017-05-29 09:25:14 +08:00
猜想大概有几种可能,可以逐一排除一下:
1. update 不发送 post_save 的 signal。代码里有的地方是直接 update 而不是调用的 save
2. save 放在了一个 transaction 里面。task 的代码是发送到 celery 上执行的,可能这时候 transaction 还没提交,objects.get 会报错,被你 catch,return 掉了
3. redis 里的 key 被其他地方重复使用。这个搜一下代码就知道了
4. 统计脚本有问题
Danfi
2017-05-29 10:55:56 +08:00
估计是数据还没保存到数据库任务就已经运行了 test_models.objects.get(id=test_models_id) ,然后获取不到数据
111111111111
2017-05-29 19:42:37 +08:00
receiver 和 task 里打个 log 看看
另外数据库是读写分离的么
huisezhiyin
2017-05-31 10:15:11 +08:00
已解决
因为使用了读写分离的缘故 导致这个信号的异步任务发起时没有从读库获取对应的信息 现在在异步任务里加一个 delay 应该就可以解决了
huisezhiyin
2017-05-31 10:15:30 +08:00
@111111111111 是的 应该是读写分离的缘故 读库速度较慢
wingyiu
2017-05-31 21:22:48 +08:00
更好的办法是用 canal 吧?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/364520

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX