Django如何防止定时任务并发浅析
前言
django提供了commands类,允许我们编写命令行脚本,并且可以通过pythonmanage.py拉起。
了解commands
具体djangocommands如何使用,大家参考官方文档即可: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-*-
importfcntl
importos
fromapps.settingsimportCRON_LOCK_DIR
#尝试加锁
deftry_lock(name):
defdecorator(func):
defwrap(*args,**kwargs):
os.makedirs(CRON_LOCK_DIR,exist_ok=True)
withopen('{}/{}'.format(CRON_LOCK_DIR,name),'w')asfd:
try:
fcntl.lockf(fd,fcntl.LOCK_EX|fcntl.LOCK_NB)#加锁
func(*args,**kwargs)
fcntl.lockf(fd,fcntl.LOCK_UN)#解锁
except:#加锁异常跳过
pass
returnwrap
returndecorator
其中CRON_LOCK_DIR是文件锁的父目录,下面放了若干锁文件。
对Commands的handle方法指定锁文件名即可:
classCommand(BaseCommand):
@try_lock('check_order')#指定锁文件的名字
defhandle(self,*args,**options):
pass
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对毛票票的支持。