网络编程
位置:首页>> 网络编程>> Python编程>> Django如何防止定时任务并发浅析

Django如何防止定时任务并发浅析

作者:鱼儿  发布时间:2021-10-23 01:09:54 

标签:django,定时,并发

前言

django提供了commands类,允许我们编写命令行脚本,并且可以通过python manage.py拉起。

了解commands

具体django commands如何使用,大家参考官方文档即可:https://docs.djangoproject.com/en/2.2/howto/custom-management-commands/

一个坑

使用时遇到一个坑:在commands运行中的异常并不会打印到屏幕上,它要求我们必须抛出CommandError类型的异常才能被打印到屏幕中,具体参考:https://docs.djangoproject.com/en/2.2/howto/custom-management-commands/#command-exceptions

文件锁防并发

我们通常利用Crontab拉起定时任务,那么就会面临一个常见问题,如何避免前一次没结束而后一次再次启动的问题。

通常都是用文件锁来搞定这个事情,我做了一个简单的装饰器来包装Commands的handle方法,定义一套元类或者类装饰器都可以达到同样的目的,这里就不炫技了。


# -*- coding: utf-8 -*-
import fcntl
import os
from apps.settings import CRON_LOCK_DIR

# 尝试加锁
def try_lock(name):
 def decorator(func):
   def wrap(*args, **kwargs):
     os.makedirs(CRON_LOCK_DIR, exist_ok=True)
     with open('{}/{}'.format(CRON_LOCK_DIR, name), 'w') as fd:
       try:
         fcntl.lockf(fd, fcntl.LOCK_EX | fcntl.LOCK_NB) # 加锁
         func(*args, **kwargs)
         fcntl.lockf(fd, fcntl.LOCK_UN) # 解锁
       except: # 加锁异常跳过
         pass
   return wrap
 return decorator

其中CRON_LOCK_DIR是文件锁的父目录,下面放了若干锁文件。

对Commands的handle方法指定锁文件名即可:


class Command(BaseCommand):
 @try_lock('check_order') # 指定锁文件的名字
 def handle(self, *args, **options):
   pass

来源:https://yuerblog.cc/2019/05/13/django-防止定时任务并发/

0
投稿

猜你喜欢

手机版 网络编程 asp之家 www.aspxhome.com