全局KV數(shù)據(jù)并發(fā)讀寫
?迷你世界?發(fā)布時間: 2023-02-23 10:40:12
全局KV數(shù)據(jù)并發(fā)讀寫,主要保證了多個玩家同時對一個KEY進行讀寫操作時的唯一性,確保讀寫成功,并且獲取最新值。
應(yīng)用場景 包括但不僅限于宗門系統(tǒng),拍賣行系統(tǒng),搶購系統(tǒng)等,開發(fā)者可根據(jù)自己的業(yè)務(wù)需要,選擇使用。
普通的setDataListBykey?和getDataListByKey接口已經(jīng)滿足KV數(shù)據(jù)的絕大多數(shù)存取需求,但是當(dāng)需要實現(xiàn)全服共同宗門系統(tǒng)(全局屬性,例如總?cè)藬?shù)和貢獻值等)、全服共同拍賣行(售賣物品的剩余數(shù)量)等大型跨游戲房間功能的時候,容易出現(xiàn)數(shù)據(jù)的彼此覆蓋,沒法保證全局唯一性。
?
為保證全局唯一性,我們特意設(shè)計了全新的UpdateDataListByKey接口。使用該接口,開發(fā)者僅需自己處理一個回調(diào)函數(shù),在函數(shù)中處理自己的數(shù)據(jù)的邏輯。接口底層會自動重試,直至數(shù)據(jù)修改成功。
?
若遇到?jīng)_突、失敗的情況,接口會自動回傳最新的數(shù)據(jù)值,并調(diào)用開發(fā)者的回調(diào)函數(shù),按照開發(fā)者自己設(shè)定的邏輯進行更新數(shù)據(jù),確保了數(shù)據(jù)不出錯,不會被其他玩家覆蓋。
?
callback函數(shù)示例說明
?
UpdateDataListByKey
參數(shù)及類型:
libvarname:string表的腳本引用名
key:string需要更新的表中的key
callback:function更新操作中的返回函數(shù)
返回值及類型:
ErrorCode.OK
該方法的主要作用:安全更新表中某個key下的值,并發(fā)存取數(shù)據(jù),確保Key下的值唯一性
具體使用案例如下:

local callback = function (ret,key,value)
?-- ret 0 很遺憾,數(shù)據(jù)沖突了,
?-- 需要根據(jù)帶回來的最新value進行邏輯處理后返回給底層重試
?if ret == 0 then
? ? ?print("有沖突,這是數(shù)據(jù)庫里最新的值" , value)
? ? ?--邏輯處理,開發(fā)者可根據(jù)自己的邏輯,進行增加/減少相應(yīng)的數(shù)值。如實例中是,值+1,則每次都累加1,獲取到服務(wù)器中最新的值,進行+1
? ? ?value = value + 1
? ? ?--返回給底層重試
? ? ?return value ?-- ret 2 修改成功啦
?elseif ret == 2 then
? ? ?print("成功,更新后的值 " , value)
?endendlocal ret = CloudSever:UpdateDataListByKey('list','score',callback)if ret == ErrorCode.OK thenend

普通KV存儲 VS 全局KV數(shù)據(jù)并發(fā)讀寫
普通KV存儲set操作時,執(zhí)行速度更快一些。直接保存key對應(yīng)的數(shù)據(jù),只會有寫入時的每分鐘請求次數(shù)限制。但是在多服同時對同一個KEY進行寫數(shù)據(jù)的時候容易造成數(shù)據(jù)不一致。
?
全局KV數(shù)據(jù)并發(fā)讀寫(UpdateDataListByKey)執(zhí)行更慢,因為修改之前會讀取最新的值,然后嘗試寫入。因此該接口同時受到讀取和寫入的每分鐘請求次數(shù)限制。另外,它第一次操作某個key時,因為數(shù)據(jù)不存在會返回空值,此時依然是在callback里面處理,并提交首次有效數(shù)據(jù)給底層。
?
注意事項
1.UpdateDataListByKey接口無需事先設(shè)置key對應(yīng)的數(shù)據(jù),因為數(shù)據(jù)都在callback里面提交,從無到有的第一次數(shù)據(jù)也是這里提交。這樣才能避免同時對同一個KEY的數(shù)據(jù)操作時,彼此沖突覆蓋問題;
?
2.非必要慎用UpdateDataListByKey接口,性能降低。只有業(yè)務(wù)場景,必須要對同一個key的數(shù)據(jù)進行寫操作時,保證唯一性、正確性的場景和功能時,才推薦使用該接口;
?
3.使用UpdateDataListByKey修改過的數(shù)據(jù),請勿使用普通setDataListBykey接口去設(shè)置新值,因為會直接覆蓋掉原來數(shù)據(jù),沒法保證唯一、正確性,而且有可能導(dǎo)致其它問題;
?
4.對同一個key,禁止混用普通setDataListBykey和UpdateDataListByKey去存數(shù)據(jù);
?
5.此接口只在云服有效,不要單機或聯(lián)機測試這個接口;
?
6.每個key只能設(shè)置一個回調(diào),設(shè)置后不能隨意修改;
?
7.新接口全程無緩存,Update提交的數(shù)據(jù)不能用CloudSever:getlistCache()獲取,直接用getDataListByKey()獲取當(dāng)前最新的數(shù)據(jù);
?
8.Update接口操作的數(shù)據(jù),其set操作只能在callback里面,并采用返回最新value進行修改,千萬別基于自己調(diào)用get拿到的數(shù)據(jù)進行操作,容易導(dǎo)致數(shù)據(jù)覆蓋,出錯。