考慮以下幾點:火力地堡交易錯誤
function useCredits(userId, amount){
var userRef = firebase.database().ref().child('users').child(userId);
userRef.transaction(function(user) {
if (!user){
return user;
}
user.credits -= amount;
return user;
}, NOOP, false);
}
function notifyUser(userId, message){
var notificationId = Math.random();
var userNotificationRef = firebase.database().ref().child('users').child(userId).child('notifications').child(notificationId);
userNotificationRef.transaction(function(notification) {
return message;
}, NOOP, false);
}
這些都是從同一個節點JS過程調用。
用戶看起來是這樣的:
{
"name": 'Alex',
"age": 22,
"credits": 100,
"notifications": {
"1": "notification 1",
"2": "notification 2"
}
}
當我跑我的壓力測試中,我注意到,有時傳遞給userRef交易更新功能的用戶對象是不是隻有以下完整的用戶:
{
"notifications": {
"1": "notification 1",
"2": "notification 2"
}
}
這顯然會導致錯誤,因爲user.credits不存在。
可疑傳遞給userRef事務的update函數的用戶對象與userNotificationRef事務的更新函數返回的數據相同。
爲什麼會出現這種情況?如果我在用戶父位置上運行這兩個事務,這個問題就會消失,但這是一個不太理想的解決方案,因爲我然後有效地鎖定並讀取了整個用戶對象,這在添加一次寫入通知時是多餘的。
我不知道交易有這樣的問題...... +1。你如何建議重新設計這個「增值」操作而不需要交易? – qxz
非常感謝您的詳細回覆 - 理解。看起來交易有些失敗 - 在我看來,客戶不應該擔心所有這些考慮因素。您如何建議在不使用Firebase交易的情況下對銀行賬戶餘額進行建模?如果沒有一個強大的方法來處理這個使用交易,那麼我覺得這是一個嚴重的限制。另一個問題是能夠在事務上更新某個值,並同時自動更新其他位置。 – user3391835
這是所有來之不易的經歷,重點在*難*。只要你牢記上述注意事項,事務對於簡單的增量可能就不錯了。另一種方法是將「+ N」條目推送到日誌中,並讓服務器定期使用事務處理它們,這應該更加健壯並且最終保持一致。客戶端可以讀取最後的聚合值並記錄,以便即時計算當前值。深度原子更新是可能的,但不能是事務性的 - 再次,基於日誌的設計是您的朋友。 – Piotr