Firebase - 实时数据库中 2 条路径的一个事务
Firebase - One transaction for 2 paths in real time database
我有一个具有以下结构的数据库:
现在可以对两幅画进行评分,然后更新评分。
但是可能会发生一幅画同时被多次评级的情况。因此我尝试使用嵌套事务(见下文)来避免竞争条件:
function pictureClicked(picture) {
const db = getDatabase();
const leftRef = ref(db, '/paintings/' + generateDbName(currentLeft));
const rightRef = ref(db, '/paintings/' + generateDbName(currentRight));
const winnerLeft = (picture === 'left') ? 1 : 0;
runTransaction(leftRef, (leftP) => {
if (leftP) {
runTransaction(rightRef, (rightP) => {
if (rightP) {
// Calculation of the new rating for each painting (Elo System)
const tRatingLeft = Math.pow(10, leftP.rating / 400);
const tRatingRight = Math.pow(10, rightP.rating / 400);
const expectedLeft = tRatingLeft / (tRatingLeft + tRatingRight);
const expectedRight = tRatingRight / (tRatingLeft + tRatingRight);
// Setting new rating
leftP.rating = leftP.rating + 32 * (winnerLeft - expectedLeft);
rightP.rating = rightP.rating + 32 * ((1 - winnerLeft) - expectedRight);
}
return rightP;
});
}
return leftP;
});
}
现在这个解决方案并没有真正奏效,而且我读到它不是解决这个问题的最佳方法。我找到的唯一解决方案是 运行 我数据库根目录上的事务,但我担心这会导致瓶颈,许多已启动的事务甚至不会写入数据库,因为事务只会重试25 次(或者我的担心是没有根据的?)。这个问题还有其他解决方案吗?
Firebase 实时数据库事务 运行 针对数据库中的单个路径。目前没有办法 运行 针对多路径的事务,因此常见的方法是 运行 针对最低级别共享路径的事务(在您的情况下为 /paintings
)。
这确实会导致更多争用,因为您有更多用户执行并发事务。
我有时使用的唯一替代方法是使用以下方法构建我自己的交易机制:
- 多路径更新,同时执行两个写入。
- 安全规则,只允许在我的用例中有意义的转换。
- 客户端重试,以便仍能正确处理争用或过时的数据。
即使对于简单的情况,这也是相当重要的,并且可能需要更改您的数据结构 and/or 为每个请求添加额外的值。但是,如果您克服了这些障碍,它将允许您 运行 跨多个路径进行“交易”。
我有一个具有以下结构的数据库:
现在可以对两幅画进行评分,然后更新评分。 但是可能会发生一幅画同时被多次评级的情况。因此我尝试使用嵌套事务(见下文)来避免竞争条件:
function pictureClicked(picture) {
const db = getDatabase();
const leftRef = ref(db, '/paintings/' + generateDbName(currentLeft));
const rightRef = ref(db, '/paintings/' + generateDbName(currentRight));
const winnerLeft = (picture === 'left') ? 1 : 0;
runTransaction(leftRef, (leftP) => {
if (leftP) {
runTransaction(rightRef, (rightP) => {
if (rightP) {
// Calculation of the new rating for each painting (Elo System)
const tRatingLeft = Math.pow(10, leftP.rating / 400);
const tRatingRight = Math.pow(10, rightP.rating / 400);
const expectedLeft = tRatingLeft / (tRatingLeft + tRatingRight);
const expectedRight = tRatingRight / (tRatingLeft + tRatingRight);
// Setting new rating
leftP.rating = leftP.rating + 32 * (winnerLeft - expectedLeft);
rightP.rating = rightP.rating + 32 * ((1 - winnerLeft) - expectedRight);
}
return rightP;
});
}
return leftP;
});
}
现在这个解决方案并没有真正奏效,而且我读到它不是解决这个问题的最佳方法。我找到的唯一解决方案是 运行 我数据库根目录上的事务,但我担心这会导致瓶颈,许多已启动的事务甚至不会写入数据库,因为事务只会重试25 次(或者我的担心是没有根据的?)。这个问题还有其他解决方案吗?
Firebase 实时数据库事务 运行 针对数据库中的单个路径。目前没有办法 运行 针对多路径的事务,因此常见的方法是 运行 针对最低级别共享路径的事务(在您的情况下为 /paintings
)。
这确实会导致更多争用,因为您有更多用户执行并发事务。
我有时使用的唯一替代方法是使用以下方法构建我自己的交易机制:
- 多路径更新,同时执行两个写入。
- 安全规则,只允许在我的用例中有意义的转换。
- 客户端重试,以便仍能正确处理争用或过时的数据。
即使对于简单的情况,这也是相当重要的,并且可能需要更改您的数据结构 and/or 为每个请求添加额外的值。但是,如果您克服了这些障碍,它将允许您 运行 跨多个路径进行“交易”。