Firebase事务中transaction.get()即时返回结果的原理探究
Firestore事务中transaction.get()“即时获取”的原理
首先明确:Firestore不会提前预加载数据库(或部分数据)副本,transaction.get()的同步即时感,完全来自它的乐观锁事务执行机制,具体拆解如下:
事务的执行逻辑是「尝试-校验-重试」循环:
当你调用db.runTransaction时,Firestore会把你的事务代码块(也就是那个lambda)提交执行。只有当代码块执行到transaction.get(ref)这一行时,才会触发对应文档的读取——如果本地缓存有该文档的最新版本,直接同步返回;没有的话就从服务端拉取最新数据,拉取完成后再继续执行下一行代码。不需要提前知晓要读取的文档:
Firestore用的是乐观锁机制,它不会在事务开始前锁定或预加载任何数据。事务执行过程中,你按需调用transaction.get()读取指定文档,Firestore会记录这些文档的版本号。当你的代码块执行完所有逻辑(比如修改数据准备提交),Firestore会检查这些文档的版本号是否和读取时一致:- 如果一致,说明没有其他客户端修改过,直接提交事务里的写入操作;
- 如果不一致,就自动重试整个代码块(重试次数默认有上限),重试时会重新读取这些文档的最新数据,再执行你的逻辑。
关于“同步”的说明:
你看到的val data = transaction.get(ref)是同步调用,指的是在事务的单次尝试内,这个get操作会阻塞到拿到数据才继续执行下一行,所以你感觉是“即时完成”。但整个runTransaction方法本身是异步的(底层是异步调度),只是代码块内部的逻辑是同步串行的。
举个简单的流程例子:
- 第一次尝试执行事务代码块,先读
exampledoc,再读exampledoc2,然后修改数据准备提交; - Firestore检查这两个文档的版本是否没变,没变就提交成功;
- 如果期间有其他客户端改了
exampledoc,Firestore就会重试整个代码块,重新读取两个文档的最新数据,再执行你的逻辑。
内容的提问来源于stack exchange,提问作者Gabriel Maia Gondim
相关产品推荐
相关产品推荐

