如何在 Celery Worker 中正确连接 mongodb?

sor*_*tas 6 python mongodb celery pymongo celery-task

学习 Celery,阅读Celery 最佳实践,并有一个关于 Celery 数据库使用的非常简单的问题。

德尼·贝尔托维奇 说:

您不应将数据库对象(例如您的用户模型)传递给后台任务,因为序列化对象可能包含过时的数据。

那么,如果我想连接到工作人员中的数据库,正确的选择是什么:

@app.task
def add(x, y, collection):
    client = MongoClient('mongodb://localhost:27017/')
    db = client.wakawaka
    db[collection].insert_one({'sum':x+y})
    return True
Run Code Online (Sandbox Code Playgroud)

或者:

client = MongoClient('mongodb://localhost:27017/')
db = client.wakawaka

@app.task
def add(x, y, collection):
    db[collection].insert_one({'sum':x+y})
    return True
Run Code Online (Sandbox Code Playgroud)

UPD:我可以close()在每个任务结束时连接 mongodb,因此每次我需要某些东西时,任务都会连接到新的数据库,并且不会浪费资源。不过,我需要多次打开/关闭数据库连接吗?或者我可以连接一次并以某种方式刷新连接以检索新版本的数据库?

Olu*_*ule 4

由于事务是独立执行的,因此每个事务打开/关闭数据库连接可以避免因过时或不正确的数据而导致的错误。数据库事务的生命周期管理也得到了简化。

您可以在连接上下文管理器块中编写事务。这会处理关闭连接,因此无需显式关闭连接。它也是线程安全的。您还可以利用内置连接池在发生异常时重试。

@app.task
def add(x, y, collection):
    with MongoClient('mongodb://localhost:27017') as connection:
        db = connection.db
        db.collection.insert_one({'sum':x+y})
    return True
Run Code Online (Sandbox Code Playgroud)

请注意,如果您要更新多个文档,这不会维护数据更新的事务完整性。

从Mongodb 4.0.0和pymongo 3.7开始,它们开始支持多文档ACID事务。