烧瓶中的原子插入

时间:2020-10-24 17:43:21

标签: python flask sqlalchemy flask-sqlalchemy

我在Flask和SQLAlchemy中实现以下目的有一个问题:我有一种用Flask编写的博客应用程序,用户可以在其中编写文本块。因此,我有一个用户模型和一个文本块模型,这些文本块必须是唯一的。文本块可以从两个不同的客户端应用程序写入和发送,并且可以同时发生。我需要使时间块的插入和处理具有原子性,以便两个客户端应用程序不会同时插入和处理同一时间块。 型号:

class TextblockModel(db.Model):
    __tablename__ = "textblock"

    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
    text = db.Column(db.Text, default="", nullable=False)

    user = db.relationship("User", backref=db.backref("texts", lazy=True))

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255), nullable=False)
    email = db.Column(db.String(100), unique=True, nullable=False)
    password = db.Column(db.String(255))

对于两个客户端应用程序中的每一个,我都有一个发布端点:

def post1(self):
        blocks = insert_block_into_db(request.json, current_user, CLIENTAPP1)
        process_blocks(blocks)

def post2(self):
        blocks = insert_block_into_db(request.json, current_user, CLIENTAPP2)
        process_blocks(blocks)

我需要使文本块的插入和处理原子化。像这样:

def post1(self):
    with lock:
        blocks = insert_block_into_db(request.json, current_user, WEBAPP1)
        process_blocks(blocks)

def post2(self):
    with lock:
        blocks = insert_block_into_db(request.json, current_user, WEBAPP2)
        process_blocks(blocks)

但是我认为普通的Python锁不起作用,因为WSGI产生了多个用于请求处理的进程。此外,我不需要锁定所有内容,而只需锁定与当前用户相关的行。有谁知道我该如何解决?

1 个答案:

答案 0 :(得分:0)

如果您正在使用Gunicorn,则可以在preload_app = True中设置gunicorn.conf。这样可以确保在工作人员(即进程)之间共享锁。

与Web服务器无关的另一种解决方案是使用NamedAtomicLock。这是一个很棒的软件包,可创建操作系统全局锁。因此,可以在进程之间共享锁。锁在指定目录中创建一个空文件夹用作共享资源。由于创建和删除目录是根据POSIX标准的原子操作,因此该机制允许跨进程锁定。我不确定它是否适用于非UNIX计算机,例如Windows。