APScheduler可能遇到的问题

uWsgi使用多进程模式启动Django项目,因此我们会有多个进程去执行这个定时任务,导致定时任务被重复执行。解决这个问题的方法,我们直接就会想到采用加锁的方式。第一个拿到锁的进程,执行定时任务,其余的进程由于拿不到锁,因此也就不会执行定时任务。下面给出两种加锁方案,分别适用于不同的场合。

redis分布式锁

def testaps():
    cache=get_redis_connection("default")
    key = f"APS_Lock"
    lock = cache.set(key, value=1, nx=True, ex=180)     # 180s之后锁自动消失,因此无需释放锁。
    if lock:
        scheduler = BackgroundScheduler()
        def my_job():
            print (time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())))
        scheduler.add_job(my_job, 'interval', seconds=10)
        scheduler.start()
    else:
        ...
testaps()   # 执行函数
当多个进程都执行testaps方法的时候,只有第一个拿到redis锁(这是个原子操作)的进程才能开启定时任务,其他的进程都无法开启定时任务,这样就可以保证定时任务只被执行一次。

文件锁

import atexit
import fcntl
 
def init():
    f = open("scheduler.lock", "wb")
    try:
        fcntl.flock(f, fcntl.LOCK_EX | fcntl.LOCK_NB)   # 加锁
        scheduler = BackgroundScheduler()
        def my_job():
            print (time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())))
        scheduler.add_job(my_job, 'interval', seconds=10)
        scheduler.start()
    except:
        pass
    def unlock():
        fcntl.flock(f, fcntl.LOCK_UN)   
        f.close()
    atexit.register(unlock)     # 释放锁
# atexit模块定义了清理函数的注册和反注册函数. 被注册的函数会在解释器正常终止时执行

init()  # 执行函数

atexit模块说明

https://docs.python.org/zh-cn/3/library/atexit.html

-------------------------------------------

个性签名:代码过万,键盘敲烂!!!

如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!

原文地址:https://www.cnblogs.com/weiweivip666/p/15770588.html