多设备并发更新Firebase单个文档遇计数递减错误及事务重复新增问题
Firebase 多设备并发更新计数及关联写入解决方案
问题根因说明
1. 并发更新仅递减1
初始实现未使用原子操作/事务,属于典型的脏写问题:两台设备几乎同时读取到相同的计数值,各自基于该值减1后写回,最终数值仅减少1,不符合预期。
2. 事务实现后关联表重复写入
Firestore 事务默认会在检测到修改冲突时自动重试最多5次,你将关联表新增记录的逻辑写在了事务执行块内部,事务每次重试都会重复执行写入逻辑,最终生成多条重复记录。
正确实现方案
核心原则
事务块内仅保留只读操作、目标计数文档的校验与修改逻辑,所有副作用操作(关联表写入、外部接口调用等)必须移到事务提交成功之后执行。
代码示例(Web SDK)
const countDocRef = db.collection('your_count_collection').doc('target_doc_id'); // 提前生成关联记录ID,避免多次执行生成不同ID const relatedDocRef = db.collection('your_related_collection').doc(); try { // 执行事务,仅处理计数校验与更新 const newCount = await db.runTransaction(async (transaction) => { const countDoc = await transaction.get(countDocRef); const currentCount = countDoc.data().count_field; // 前置校验:计数为0时终止操作 if (currentCount <= 0) { throw new Error('count has reached zero, operation denied'); } const updatedCount = currentCount - 1; transaction.update(countDocRef, { count_field: updatedCount }); return updatedCount; }); // 事务提交成功后再写入关联表 await relatedDocRef.set({ // 你的业务字段 update_time: new Date(), remaining_count: newCount }); } catch (err) { console.error('operation failed: ', err); }
高一致性可选方案
如果要求计数更新和关联写入强一致,避免事务成功后关联写入失败导致数据不一致,可将关联写入逻辑迁移到Firebase云函数的onUpdate触发器中:只要计数文档被成功修改,云函数自动生成关联记录,客户端仅需要执行事务更新计数即可,完全规避客户端侧的重复写入风险。
内容的提问来源于stack exchange,提问作者Avinash Yalgonde
相关产品推荐
相关产品推荐

