同步Firebase数据库访问

时间:2018-10-22 13:23:09

标签: firebase firebase-realtime-database google-cloud-functions

我有一个Firebase数据库实例,我想为某个节点添加一个计数器。

每次用户执行特定操作时,我都想增加节点值。如何做到这一点而不会出现同步问题?如何使用Google函数来做到这一点?

例如:

database{
node {
counter : 0
}

}

在某些时间,3个不同的用户在计数器上读取该值,然后尝试增加它。由于它们在完全相同的时间读取,所以它们全部读取为“ 0”并递增为“ 1”,但是执行结束时所需的值应该为“ 3”,因为它被读取了3次。

=================更新=================

@renaud指出要使用事务来保持已保存数据的同步,但是我还有另一种情况,我还需要在读取端进行同步:

例如 用户读取了实际值,因此它会执行不同的操作,并通过增加一个值来完成...

在像enviorement这样的sql中,我会编写一个执行该操作的过程,因为无论用户如何处理信息,我总是通过增加一个来完成

如果我确实理解@renaud回答正确,那么在这种情况下,4个同时读取数据库的不同用户将获得0作为当前值,然后在事务更新时最终存储的值将为4,但是在客户端,每个人只是读0

1 个答案:

答案 0 :(得分:2)

在这种情况下,您必须使用事务,请参见https://firebase.google.com/docs/database/web/read-and-write#save_data_as_transactionshttps://firebase.google.com/docs/reference/js/firebase.database.Reference#transaction

交易将“确保与其他同时写入同一位置的客户端没有冲突。”

在Cloud Function中,您可以按照以下方式编写代码,例如:

....
const counterRef = admin
  .database()
  .ref('/node/counter');

return counterRef
  .transaction(current_value => {
    return (current_value || 0) + 1;
  })
  .then(counterValue => {
    if (counterValue.committed) {
      //For example update another node in the database 
      const updates = {};
      updates['/nbrOfActionsExecuted'] = counterValue.snapshot.val();
      return admin
        .database()
        .ref()
        .update(updates);
    }
  })

或者如果您只想更新计数器,则只需执行以下操作(由于事务返回了Promise,如上面提到的第二个链接中所述):

exports.testTransaction = functions.database.ref('/path').onWrite((change, context) => {
  const counterRef = admin
    .database()
    .ref('/node/counter');

  return counterRef
    .transaction(current_value => {
      return (current_value || 0) + 1;
    });
});

请注意,在第二种情况下,我以Realtime Database触发器作为触发器的示例。