Cloud Firestore文档锁定

pwr*_*ray 4 database locking transactions firebase google-cloud-firestore

要确保在共享设置中独占使用Cloud Firestore文档,是否足以在事务中读取,然后写入字段(例如"lockedBy")?

Dan*_*ath 11

悲观与乐观

Cloud Firestore中没有本机独占锁定.由于系统设计为在大型分布式系统(例如,1000个移动电话用户或Kubernetes集群)中运行,因此它基于乐观锁定模式.

这意味着当您执行读写事务时,如果您在提交事务之前写入了您读取的文档,则事务将失败,因此客户端可以回滚.

构建自己的 - 移动SDK和安全规则

我将假设你是从移动SDK开始进入的,并将在下一节中介绍服务器客户端.

您可以使用单独的文档在此基础上构建独占锁.例如,假设您要对集合中的文档实现独占锁定critical_data.

为此,我们将使用一个名为的单独集合mutex_critical_data,其中的文档内部是互斥,用于集合中具有相同id的文档critical_data.

在您可以访问调用的文档之前doc_id,critical_data您将要执行写入事务以owner向您设置互斥字段.我假设你正在使用Firebase Auth,所以你==用户的auth id auth_id.这可以是唯一标识用户或进程的id.

完成文档后,删除互斥文档以便其他人可以使用它.

为了确保它是独占的而其他人无法窃取它,您需要在安全规则定义中添加一些检查.

// In the match section that sets the document id to 'doc_id'
function mutex_exists ()
{
    return exists(/databases/$(database)/documents/mutex_critical_data/$(doc_id));
}

function mutex_owner ()
{
    return get(/databases/$(database)/documents/mutex_critical_data/$(doc_id)).data;
}

function user_owns_mutex () {
    return mutex_owner().owner == request.auth.uid;
}

allow write: if not(mutex_exists()) || user_owns_mutex;
Run Code Online (Sandbox Code Playgroud)

您还可以使用规则来强制执行互斥锁,方法是通过拥有互斥锁来预测对资源的写入.

构建自己的 - 服务器客户端

请记住,安全规则适用于Mobile/Web SDK访问,不适用于服务器客户端.由于服务器客户端被视为可信环境,而不是由规则强制执行排他性逻辑,因此您需要在互斥锁上执行读写事务.

租约不是锁

最后一点,如果你建立这个,我强烈建议寻找独家租约而不是独家锁.

租约就像锁,但如果租约在规定时间之前没有(或不允许)续租,它会自动到期.这意味着如果客户端没有回来(例如,客户端崩溃),其他人最终将能够在没有管理员操作的情况下获得租约.

概念是相同的,但您不是仅设置所有者,而是在字段中设置租约时间.如果租约大于xx租约,则租约的时间长度在哪里,业主不再认为.在租约到期之前,您可以选择允许所有者通过设置新的租约时间来续订租约.