在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ Android/ 解決云同步的保存沖突
檢測常用的手勢
優(yōu)化layout的層級
用戶輸入
管理應(yīng)用的內(nèi)存
聯(lián)系人信息
開發(fā)輔助程序
Android多媒體
添加語音功能
顯示位置地址
提供向下與橫向?qū)Ш?/span>
支持游戲控制器
訪問可穿戴數(shù)據(jù)層
處理多點觸控手勢
全屏沉浸式應(yīng)用
為多線程創(chuàng)建管理器
數(shù)據(jù)保存
Intent的發(fā)送
更新Notification
優(yōu)化下載以高效地訪問網(wǎng)絡(luò)
打印
打包可穿戴應(yīng)用
接收從其他App傳送來的數(shù)據(jù)
發(fā)送與接收消息
建立靈活動態(tài)的UI
處理鍵盤輸入
Building a Work Policy Controller
建立測試環(huán)境
創(chuàng)建表盤
分享文件
顯示Notification進度
實現(xiàn)自適應(yīng)UI流(Flows)
使用設(shè)備管理策略增強安全性
使用能感知版本的組件
執(zhí)行網(wǎng)絡(luò)操作
建立文件分享
添加移動
更新你的Security Provider來對抗SSL漏洞利用
支持鍵盤導(dǎo)航
創(chuàng)建和監(jiān)視地理圍欄
發(fā)送并同步數(shù)據(jù)
使用BigView樣式
無線連接設(shè)備
提供向上導(dǎo)航與歷史導(dǎo)航
最小化定期更新造成的影響
實現(xiàn)向下的導(dǎo)航
支持不同的屏幕大小
Android 可穿戴應(yīng)用
添加動畫
顯示聯(lián)系人頭像
使用OpenGL ES顯示圖像
處理輸入法可見性
分享文件
保持設(shè)備喚醒
淡化系統(tǒng)Bar
使用NFC分享文件
保存到Preference
Android聯(lián)系人信息與位置信息
創(chuàng)建標準的網(wǎng)絡(luò)請求
使用Drawables
管理Bitmap的內(nèi)存使用
管理Activity的生命周期
按需加載視圖
傳輸資源
為可穿戴設(shè)備創(chuàng)建自定義UI
在一個線程中執(zhí)行一段特定的代碼
性能優(yōu)化
隱藏導(dǎo)航欄
創(chuàng)建目錄瀏覽器
為多種大小的屏幕進行規(guī)劃
View間漸變
使用觸摸手勢
高效加載大圖
使用CursorLoader在后臺加載數(shù)據(jù)
創(chuàng)建抽屜式導(dǎo)航(navigation drawer)
管理音頻焦點
創(chuàng)建后臺服務(wù)
創(chuàng)建功能測試
創(chuàng)建使用Material Design的應(yīng)用
停止與重啟Activity
添加一個簡便的分享功能
啟動Activity時保留導(dǎo)航
TV應(yīng)用清單
創(chuàng)建向后兼容的UI
?# 優(yōu)化自定義View
創(chuàng)建單元測試
在UI上顯示Bitmap
建立OpenGL ES的環(huán)境
構(gòu)建表盤服務(wù)
JNI Tips
建立搜索界面
實現(xiàn)自定義View的繪制
使用HTTPS與SSL
按需操控BroadcastReceiver
分享簡單的數(shù)據(jù)
繪制形狀
Android位置信息
創(chuàng)建并運行可穿戴應(yīng)用
執(zhí)行 Sync Adpater
獲取最后可知位置
創(chuàng)建 Android 項目
實現(xiàn)高效的導(dǎo)航
退出全屏的Activity
創(chuàng)建Card
兼容音頻輸出設(shè)備
同步數(shù)據(jù)單元
傳輸數(shù)據(jù)時避免消耗大量電量
保存到文件
緩存Bitmap
提供配置 Activity
調(diào)度重復(fù)的鬧鐘
實現(xiàn)輔助功能
重復(fù)的下載是冗余的
隱藏狀態(tài)欄
實現(xiàn)自定義的網(wǎng)絡(luò)請求
規(guī)劃界面和他們之間的關(guān)系
使用Sync Adapter傳輸數(shù)據(jù)
TV應(yīng)用內(nèi)搜索
響應(yīng)觸摸事件
使用Google Cloud Messaging(已廢棄)
控制相機
Android網(wǎng)絡(luò)連接與云服務(wù)
請求分享一個文件
處理TV硬件
響應(yīng)UI可見性的變化
使用網(wǎng)絡(luò)服務(wù)發(fā)現(xiàn)
指定輸入法類型
優(yōu)化電池壽命
創(chuàng)建TV應(yīng)用
獲取聯(lián)系人列表
拖拽與縮放
啟動與停止線程池中的線程
創(chuàng)建 Sync Adpater
使用 WiFi P2P 服務(wù)發(fā)現(xiàn)
開始使用Material Design
代理至新的APIs
使用include標簽重用layouts
使得View可交互
高效顯示Bitmap
創(chuàng)建企業(yè)級應(yīng)用
Fragments之間的交互
創(chuàng)建與執(zhí)行測試用例
綜合:設(shè)計我們的樣例 App
繪制表盤
建立簡單的用戶界面
自定義動畫
開發(fā)輔助服務(wù)
避免出現(xiàn)程序無響應(yīng)ANR(Keeping Your App Responsive)
使用ViewPager實現(xiàn)屏幕滑動
設(shè)計高效的導(dǎo)航
Android分享操作(Building Apps with Content Sharing)
提供向后的導(dǎo)航
保持向下兼容
創(chuàng)建TV播放應(yīng)用
縮放View
使用 WiFi 建立 P2P 連接
Android后臺任務(wù)
連接到網(wǎng)絡(luò)
為 Notification 添加頁面
使TV應(yīng)用是可被搜索的
添加Action Bar
使用Material的主題
啟動另一個Activity
顯示正在播放卡片
適配不同的系統(tǒng)版本
輕松錄制視頻
創(chuàng)建可穿戴的應(yīng)用
創(chuàng)建自定義的布局
重新創(chuàng)建Activity
使用CursorLoader執(zhí)行查詢?nèi)蝿?wù)
使用舊的APIs實現(xiàn)新API的效果
使用備份API
安全要點
Android入門基礎(chǔ):從這里開始
保存并搜索數(shù)據(jù)
根據(jù)網(wǎng)絡(luò)連接類型來調(diào)整下載模式
使用Tabs創(chuàng)建Swipe視圖
SMP(Symmetric Multi-Processor) Primer for Android
解析 XML 數(shù)據(jù)
使用 Volley 傳輸網(wǎng)絡(luò)數(shù)據(jù)
建立ActionBar
Android交互設(shè)計
使用Intent修改聯(lián)系人信息
增加搜索功能
輕松拍攝照片
定義形狀
測試你的Activity
在 Notifcation 中接收語音輸入
與其他應(yīng)用的交互
管理系統(tǒng)UI
追蹤手勢移動
Android界面設(shè)計
執(zhí)行 Android 程序
顯示確認界面
創(chuàng)建Lists與Cards
打印HTML文檔
創(chuàng)建TV應(yīng)用
為多屏幕設(shè)計
定義Shadows與Clipping視圖
使用Fragment建立動態(tài)UI
接收Activity返回的結(jié)果
布局變更動畫
定位常見的問題
自定義ActionBar的風(fēng)格
定義Layouts
發(fā)送簡單的網(wǎng)絡(luò)請求
啟動與銷毀Activity
與UI線程通信
非UI線程處理Bitmap
創(chuàng)建TV布局
提升Layout的性能
報告任務(wù)執(zhí)行狀態(tài)
判斷并監(jiān)測網(wǎng)絡(luò)連接狀態(tài)
兼容不同的設(shè)備
處理按鍵動作
優(yōu)化性能和電池使用時間
給其他App發(fā)送簡單的數(shù)據(jù)
Implementing App Restrictions
向后臺服務(wù)發(fā)送任務(wù)請求
展示Card翻轉(zhuǎn)動畫
管理ViewGroup中的觸摸事件
兼容不同的屏幕密度
通過藍牙進行調(diào)試
為可穿戴設(shè)備創(chuàng)建Notification
控制音量與音頻播放
獲取聯(lián)系人詳情
在表盤上顯示信息
提供向上的導(dǎo)航
滾動手勢動畫
幫助用戶在TV上找到內(nèi)容
創(chuàng)建TV導(dǎo)航
為索引指定App內(nèi)容
ActionBar的覆蓋疊加
Android Wear 上的位置檢測
保護安全與隱私的最佳策略
Ensuring Compatibility with Managed Profiles
解決云同步的保存沖突
獲取位置更新
創(chuàng)建List
測試程序
管理網(wǎng)絡(luò)的使用情況
為App內(nèi)容開啟深度鏈接
推薦TV內(nèi)容
建立一個Notification
管理音頻播放
設(shè)計表盤
拍照
處理控制器輸入動作
判斷并監(jiān)測設(shè)備的底座狀態(tài)與類型
處理查詢的結(jié)果
保存到數(shù)據(jù)庫
支持多個游戲控制器
創(chuàng)建 Stub Content Provider
使得ListView滑動順暢
處理數(shù)據(jù)層的事件
創(chuàng)建TV應(yīng)用的第一步
使得你的App內(nèi)容可被Google搜索
將 Notification 放成一疊
創(chuàng)建 Stub 授權(quán)器
暫停與恢復(fù)Activity
管理設(shè)備的喚醒狀態(tài)
Android圖像與動畫
打印照片
云同步
創(chuàng)建TV直播應(yīng)用
為Notification賦加可穿戴特性
提供一個Card視圖
建立請求隊列(RequestQueue)
適配不同的語言
創(chuàng)建詳情頁
測試UI組件
接收其他設(shè)備的文件
創(chuàng)建自定義View
建立第一個App
創(chuàng)建2D Picker
監(jiān)測電池的電量與充電狀態(tài)
打印自定義文檔
抽象出新的APIs
通知提示用戶
獲取文件信息
運用投影與相機視角
在IntentService中執(zhí)行后臺任務(wù)
多線程操作
創(chuàng)建一個Fragment
添加Action按鈕
在不同的 Android 系統(tǒng)版本支持控制器
維護兼容性
發(fā)送文件給其他設(shè)備
創(chuàng)建TV游戲應(yīng)用
創(chuàng)建自定義的View類
代碼性能優(yōu)化建議
Intent過濾
適配不同的屏幕

解決云同步的保存沖突

編寫:jdneo - 原文:http://developer.android.com/training/cloudsave/conflict-res.html

這篇文章將介紹當應(yīng)用使用Cloud Save service存儲數(shù)據(jù)到云端時,如何設(shè)計一個魯棒性較高的沖突解決策略。云存儲服務(wù)允許我們?yōu)槊恳粋€在Google服務(wù)上的應(yīng)用用戶,存儲他們的應(yīng)用數(shù)據(jù)。應(yīng)用可以通過使用云存儲API,從Android設(shè)備,iOS設(shè)備或者Web應(yīng)用恢復(fù)或更新這些數(shù)據(jù)。

云存儲中的保存和加載過程非常直接:它只是一個數(shù)據(jù)和byte數(shù)組之間序列化轉(zhuǎn)換,并將這些數(shù)組存儲在云端的過程。然而,當用戶有多個設(shè)備,并且有兩個以上的設(shè)備嘗試將它們的數(shù)據(jù)存儲在云端時,這一保存的行為可能會引起沖突,因此我們必須決定應(yīng)該如何處理這類問題。云端數(shù)據(jù)的結(jié)構(gòu)在很大程度上決定了沖突解決方案的魯棒性,所以務(wù)必小心地設(shè)計我們的數(shù)據(jù)存儲結(jié)構(gòu),使得沖突解決方案的邏輯可以正確地處理每一種情況。

本篇文章從一些有缺陷的解決方案入手,并解釋他們?yōu)楹尉哂腥毕?。之后會呈現(xiàn)一個可以避免沖突的解決方案。用于討論的例子關(guān)注于游戲,但解決問題的核心思想是可以適用于任何將數(shù)據(jù)存儲于云端的應(yīng)用的。

沖突時獲得通知

OnStateLoadedListener方法負責從Google服務(wù)器下載應(yīng)用的狀態(tài)數(shù)據(jù)?;卣{(diào)函數(shù)OnStateLoadedListener.onStateConflict用來給應(yīng)用在本地狀態(tài)和云端存儲的狀態(tài)發(fā)生沖突時,提供了一個解決機制:

@Override
public void onStateConflict(int stateKey, String resolvedVersion,
    byte[] localData, byte[] serverData) {
    // resolve conflict, then call mAppStateClient.resolveConflict()
 ...
}

此時應(yīng)用必須決定要保留哪一個數(shù)據(jù),或者它自己提交一個新的數(shù)據(jù)來表示合并后的數(shù)據(jù)狀態(tài),解決沖突的邏輯由我們自己來實現(xiàn)。

我們必須要意識到云存儲服務(wù)是在后臺執(zhí)行同步的。所以我們應(yīng)該確保應(yīng)用能夠在創(chuàng)建這一數(shù)據(jù)的Context之外接收回調(diào)。特別地,如果Google Play服務(wù)應(yīng)用在后臺檢測到了一個沖突,該回調(diào)函數(shù)會在下一次加載數(shù)據(jù)時被調(diào)用,通常來說會是在下一次用戶啟動該應(yīng)用時。

因此,我們的云存儲代碼和沖突解決代碼的設(shè)計必須是和當前Context無關(guān)的:也就是說當我們拿到了兩個彼此沖突的數(shù)據(jù),我們必須僅通過數(shù)據(jù)集內(nèi)獲取的數(shù)據(jù)去解決沖突,而不依賴于任何其它任何外部Context。

處理簡單情況

下面列舉一些解決沖突的簡單例子。對于很多應(yīng)用而言,用這些策略或者其變體就足夠解決大多數(shù)問題了:

新的比舊的更有效:在一些情況下,新的數(shù)據(jù)可以替代舊的數(shù)據(jù)。例如,如果數(shù)據(jù)代表了用戶所選擇角色的衣服顏色,那么最近的新的選擇就應(yīng)該覆蓋老的選擇。在這種情況下,我們可能會選擇在云存儲數(shù)據(jù)中存儲時間戳。當處理這些沖突時,選擇時間戳最新的數(shù)據(jù)(記住要選擇一個可靠的時鐘,并注意對不同時區(qū)的處理)。

一個數(shù)據(jù)好于其他數(shù)據(jù):在一些情況下,我們是可以有方法在若干數(shù)據(jù)集中選取一個最好的。例如,如果數(shù)據(jù)代表了玩家在賽車比賽中的最佳時間,那么顯然,在沖突發(fā)生時,我們應(yīng)該保留成績最好的那個數(shù)據(jù)。

進行合并:有可能通過計算兩個數(shù)據(jù)集的合并版本來解決沖突。例如,我們的數(shù)據(jù)代表了用戶解鎖關(guān)卡的進度,那么我們需要的數(shù)據(jù)就是兩個沖突數(shù)據(jù)的并集。通過這個方法,用戶的關(guān)卡解鎖進度就不會丟失了。這里的例子使用了這一策略的一個變形。

為更復(fù)雜的情況設(shè)計一個策略

當我們的游戲允許玩家收集可交換物品時(比如金幣或者經(jīng)驗點數(shù)),情況會變得更加復(fù)雜一些。我們來假想一個游戲,叫做“金幣跑酷”,游戲中的角色通過跑步不斷地收集金幣使自己變的富有。每個收集到的金幣都會加入到玩家的儲蓄罐中。

下面的章節(jié)將展示三種在多個設(shè)備間解決沖突的方案:有兩個看上去還不錯,可惜最終還是不能適用于所有情況,最后一個解決方案可以解決多個設(shè)備間的數(shù)據(jù)沖突。

第一個嘗試:只保存總數(shù)

首先,這個問題看上去像是說:云存儲的數(shù)據(jù)只要存儲金幣的數(shù)量就行了。但是如果就只有這些數(shù)據(jù)是可用的,那么解決沖突的方案將會嚴重受到限制。此時最佳的方案只能是在沖突發(fā)生時存儲數(shù)值最大的數(shù)據(jù)。

想一下表1中所展現(xiàn)的場景。假設(shè)玩家一開始有20枚硬幣,然后在設(shè)備A上收集了10個,在設(shè)備B上收集了15個。然后設(shè)備B將數(shù)據(jù)存儲到了云端。當設(shè)備A嘗試去存儲的時候,沖突發(fā)生了?!爸槐4婵倲?shù)”的沖突解決方案會存儲35作為這一數(shù)據(jù)的值(兩數(shù)之間最大的)。

表1. 值保存最大的數(shù)(不佳的策略)

事件 設(shè)備A的數(shù)據(jù) 設(shè)備B的數(shù)據(jù) 云端的數(shù)據(jù) 實際的總數(shù)
開始階段 20 20 20 20
玩家在A設(shè)備上收集了10個硬幣 30 20 20 30
玩家在B設(shè)備上收集了15個硬幣 30 35 20 45
設(shè)備B將數(shù)據(jù)存儲至云端 30 35 35 45
設(shè)備A嘗試將數(shù)據(jù)存儲至云端,發(fā)生沖突 30 35 35 45
設(shè)備A通過選擇兩數(shù)中最大的數(shù)來解決沖突 35 35 35 45

這一策略顯然會失?。和婕业慕饚艛?shù)從20變成35,但實際上玩家總共收集了25個硬幣(A設(shè)備10個,B設(shè)備15個),所以有10個硬幣丟失了。只在云端存儲硬幣的總數(shù)是不足以實現(xiàn)一個健壯的沖突解決算法的。

第二個嘗試:存儲總數(shù)和變化值

另一個方法是在存儲數(shù)據(jù)中包括一些額外的數(shù)據(jù),如:自上次提交后硬幣增加的數(shù)量(delta)。在這一方法中,存儲的數(shù)據(jù)可以用一個二元組來表示(T, d),其中T是硬幣的總數(shù),而d是硬幣增加的數(shù)量。

通過這樣的數(shù)據(jù)存儲結(jié)構(gòu),我們的沖突檢測算法在魯棒性上會有更大的提升空間。但是這個方法在某些情況下依然會存在問題。

下面是包含delta數(shù)值的沖突解決算法過程:

  • 本地數(shù)據(jù):(T, d)
  • 云端數(shù)據(jù):(T', d')
  • 解決后的數(shù)據(jù):(T'+d, d)

例如,當我們在本地狀態(tài)(T, d)和云端狀態(tài)(T', d)之間發(fā)生了沖突時,可以將它們合并成(T'+d, d)。這意味著我們從本地拿出delta數(shù)據(jù),并將它和云端的數(shù)據(jù)結(jié)合起來,乍一看,這種方法可以很好的計量多個設(shè)備所收集的金幣。

該方法看上去很可靠,但它在具有移動網(wǎng)絡(luò)的環(huán)境中難以適用:

  • 用戶可能在設(shè)備不在線時存儲數(shù)據(jù)。這些改變會以隊列形式等待手機聯(lián)網(wǎng)后提交。
  • 這個方法的同步機制是用最新的變化覆蓋掉任何之前的變化。換句話說,第二次寫入的變化會提交到云端(當設(shè)備聯(lián)網(wǎng)了以后),而第一次寫入的變化就被忽略了。

為了進一步說明,我們考慮一下表2所列的場景。在表2列出的一系列操作發(fā)生后,云端的狀態(tài)將是(130, +5),最終沖突解決后的狀態(tài)是(140, +10)。這是不正確的,因為從總體上而言,用戶一共在A上收集了110枚硬幣而在B上收集了120枚硬幣??倲?shù)應(yīng)該為250。

表2. “總數(shù)+增量”策略的失敗案例

事件 設(shè)備A的數(shù)據(jù) 設(shè)備B的數(shù)據(jù) 云端的數(shù)據(jù) 實際的總數(shù)
開始階段 (20, x) (20, x) (20, x) 20
玩家在A設(shè)備上收集了100個硬幣 (120, +100) (20, x) (20, x) 120
玩家在A設(shè)備上又收集了10個硬幣 (130, +10) (20, x) (20, x) 130
玩家在B設(shè)備上收集了115個硬幣 (130, +10) (125, +115) (20, x) 245
玩家在B設(shè)備上又收集了5個硬幣 (130, +10) (130, +5) (20, x) 250
設(shè)備B將數(shù)據(jù)存儲至云端 (130, +10) (130, +5) (130, +5) 250
設(shè)備A嘗試將數(shù)據(jù)存儲至云端,發(fā)生沖突 (130, +10) (130, +5) (130, +5) 250
設(shè)備A通過將本地的增量和云端的總數(shù)相加來解決沖突 (140, +10) (130, +5) (140, +10) 250

注:x代表與該場景無關(guān)的數(shù)據(jù)

我們可能會嘗試在每次保存后不重置增量數(shù)據(jù)來解決此問題,這樣的話在每個設(shè)備上第二次存儲的數(shù)據(jù)就能夠代表用戶至今為止收集到的所有硬幣。此時,設(shè)備A在第二次本地存儲完成后,數(shù)據(jù)將是(130, +110)而不是(130, +10)。然而,這樣做的話就會發(fā)生如表3所述的情況:

表3. 算法改進后的失敗案例

事件 設(shè)備A的數(shù)據(jù) 設(shè)備B的數(shù)據(jù) 云端的數(shù)據(jù) 實際的總數(shù)
開始階段 (20, x) (20, x) (20, x) 20
玩家在A設(shè)備上收集了100個硬幣 (120, +100) (20, x) (20, x) 120
設(shè)備A將狀態(tài)存儲到云端 (120, +100) (20, x) (120, +100) 120
玩家在A設(shè)備上又收集了10個硬幣 (130, +110) (20, x) (120, +100) 130
玩家在B設(shè)備上收集了1個硬幣 (130, +110) (21, +1) (120, +100) 131
設(shè)備B嘗試向云端存儲數(shù)據(jù),發(fā)生沖突 (130, +110) (21, +1) (120, +100) 131
設(shè)備B通過將本地的增量和云端的總數(shù)相加來解決沖突 (130, +110) (121, +1) (121, +1) 131
設(shè)備A嘗試將數(shù)據(jù)存儲至云端,發(fā)生沖突 (130, +110) (121, +1) (121, +1) 131
設(shè)備A通過將本地的增量和云端的總數(shù)相加來解決沖突 (231, +110) (121, +1) (231, +110) 131

注:x代表與該場景無關(guān)的數(shù)據(jù)

現(xiàn)在我們碰到了另一個問題:我們給予了玩家過多的硬幣。這個玩家拿到了211枚硬幣,但實際上他只收集了111枚。

解決辦法:

分析之前的幾次嘗試,我們發(fā)現(xiàn)這些策略存在這樣的缺陷:無法知曉哪些硬幣已經(jīng)計數(shù)了,哪些硬幣沒有被計數(shù),尤其是當多個設(shè)備連續(xù)提交的時候,算法會出現(xiàn)混亂。

該問題的解決辦法是將我們在云端的數(shù)據(jù)存儲結(jié)構(gòu)改為字典類型,使用字符串+整形的鍵值對。每一個鍵值對都代表了一個包含硬幣的“委托人”,而總數(shù)就應(yīng)該是將所有記錄的值加起來。這一設(shè)計的宗旨是每個設(shè)備有它自己的“委托人”,并且只有設(shè)備自己可以把硬幣放到它的“委托人”當中。

字典的結(jié)構(gòu)是:(A:a, B:b, C:c, ...),其中a代表了“委托人”A所擁有的硬幣,b是“委托人”B所擁有的硬幣,以此類推。

這樣的話,新的沖突解決策略算法將如下所示:

  • 本地數(shù)據(jù):(A:a, B:b, C:c, ...)
  • 云端數(shù)據(jù):(A:a', B:b', C:c', ...)
  • 解決后的數(shù)據(jù):(A:max(a,a'), B:max(b,b'), C:max(c,c'), ...)

例如,如果本地數(shù)據(jù)是(A:20, B:4, C:7)并且云端數(shù)據(jù)是(B:10, C:2, D:14),那么解決沖突后的數(shù)據(jù)將會是(A:20, B:10, C:7, D:14)。當然,應(yīng)用的沖突解決邏輯可以根據(jù)具體的需求而有所差異。比如對于有一些應(yīng)用,我們可能希望挑選最小的值。

為了測試新的算法,將它應(yīng)用于任何一個之前提到過的場景。你將會發(fā)現(xiàn)它都能取得正確地結(jié)果。

表4闡述了這一點,它使用了表3中所提到的場景。注意下面所列出的關(guān)鍵點:

在初始狀態(tài),玩家有20枚硬幣。該數(shù)據(jù)準確體現(xiàn)在了所有設(shè)備和云端中,我們用字典:(X:20)來代表它,其中X我們不用太多關(guān)心,初始化的數(shù)據(jù)是哪兒來對該問題沒有影響。

當玩家在設(shè)備A上收集了100枚硬幣,這一變化會作為一個字典保存到云端。字典的值是100是因為這就是玩家在設(shè)備A上收集的硬幣數(shù)量。在這一過程中,沒有要執(zhí)行數(shù)據(jù)的計算(設(shè)備A僅僅是將玩家所收集的數(shù)據(jù)匯報給了云端)。

每一個新的硬幣提交會打包成一個與設(shè)備關(guān)聯(lián)的字典并保存到云端。例如,假設(shè)玩家又在設(shè)備A上收集了100枚硬幣,那么對應(yīng)字典的值被更新為110。

最終的結(jié)果就是,應(yīng)用知道了玩家在每個設(shè)備上收集硬幣的總數(shù)。這樣它就能輕易地計算出實際的總數(shù)了。

表4. 鍵值對策略的成功應(yīng)用案例

事件 設(shè)備A的數(shù)據(jù) 設(shè)備B的數(shù)據(jù) 云端的數(shù)據(jù) 實際的總數(shù)
開始階段 (X:20, x) (X:20, x) (X:20, x) 20
玩家在A設(shè)備上收集了100個硬幣 (X:20, A:100) (X:20) (X:20) 120
設(shè)備A將狀態(tài)存儲到云端 (X:20, A:100) (X:20) (X:20, A:100) 120
玩家在A設(shè)備上又收集了10個硬幣 (X:20, A:110) (X:20) (X:20, A:100) 130
玩家在B設(shè)備上收集了1個硬幣 (X:20, A:110) (X:20, B:1) (X:20, A:100) 131
設(shè)備B嘗試向云端存儲數(shù)據(jù),發(fā)生沖突 (X:20, A:110) (X:20, B:1) (X:20, A:100) 131
設(shè)備B解決沖突 (X:20, A:110) (X:20, A:100, B:1) (X:20, A:100, B:1) 131
設(shè)備A嘗試將數(shù)據(jù)存儲至云端,發(fā)生沖突 (X:20, A:110) (X:20, A:100, B:1) (X:20, A:100, B:1) 131
設(shè)備A解決沖突 (X:20, A:110, B:1) (X:20, A:100, B:1) (X:20, A:110, B:1),total 131 131

清除你的數(shù)據(jù)

在云端允許存儲數(shù)據(jù)的大小是有限制的,所以在后續(xù)的論述中,我們將會關(guān)注如何避免創(chuàng)建過大的詞典。一開始,看上去每個設(shè)備只會有一條詞典記錄,即使是非常激進的用戶也不太會擁有上千種不同的設(shè)備(對應(yīng)上千條字典記錄)。然而, 獲取設(shè)備ID的方法很難,并且我們認為這是一種不好的實踐方式,所以我們應(yīng)該使用一個安裝ID,這更容易獲取也更可靠。這樣的話就意味著,每一次用戶在每臺設(shè)備安裝一次就會產(chǎn)生一個ID。假設(shè)每個鍵值對占據(jù)32字節(jié),由于一個個人云存儲緩存最多可以有128K的大小,因此最多可以存儲4096條記錄。

在現(xiàn)實場景中,你的數(shù)據(jù)可能更加復(fù)雜。在這種情況下,存儲數(shù)據(jù)的記錄條數(shù)也會進一步受到限制。具體而言則需要取決于實現(xiàn),比如可能需要添加時間戳來指明每條記錄是何時修改的。當你檢測到有一條記錄在過去幾個禮拜或者幾個月的時間內(nèi)都沒有被修改,那么就可以安全地將金幣數(shù)據(jù)轉(zhuǎn)移到另一條記錄中并刪除老的記錄。