游戏开发常遇到数据一致性BUG,怎么解?
本文分享自華為云社區(qū)《華為云GaussDB(for Redis)揭秘第24期:游戲一致性BUG怎么解》,作者:高斯Redis官方博客 。
關(guān)于游戲與一致性
最近在跟一些游戲客戶交流,聊到了容易讓人“踩坑”的數(shù)據(jù)一致性問題,常見BUG有“背包道具丟失”、“一個玩家同時加入兩個公會”等等。這類問題往往藏得比較深,等到游戲上線后期才發(fā)現(xiàn),會比較難解決。
其實(shí),只要前期做好數(shù)據(jù)庫選型和架構(gòu)設(shè)計(jì),一致性問題是可以避免的。本文將聚焦兩大主要場景,對數(shù)據(jù)一致性問題進(jìn)行詳細(xì)剖析。
場景一:讀寫分離引起的數(shù)據(jù)不一致問題
在游戲行業(yè),MySQL很多時候都是首選的“主數(shù)據(jù)庫”。然而游戲業(yè)務(wù)也有很多高并發(fā)場景,當(dāng)上千RPS的MySQL不夠用時,為了提升吞吐,就可能會做讀寫分離、分庫分表。
但如果需要更高吞吐能力,MySQL可能會無法滿足,這時可以引入Redis,利用NoSQL的強(qiáng)擴(kuò)展性,承載上萬,甚至是數(shù)十萬RPS。同樣的,Redis也可以做讀寫分離。
1.讀寫分離引發(fā)的BUG
- 背包道具丟失(MySQL做主數(shù)據(jù)庫場景)
BUG描述:玩家在游戲地圖A購買道具,隨后立刻切換地圖,進(jìn)入游戲地圖B,結(jié)果打開背包竟發(fā)現(xiàn)道具丟失。
根因分析:前一個地圖的購買行為寫入主節(jié)點(diǎn),而新地圖中打開背包時查詢了從節(jié)點(diǎn)。由于主從同步有延時,導(dǎo)致沒查到最新數(shù)據(jù)。
- 關(guān)注好友后漏發(fā)Hi~(Redis做主數(shù)據(jù)庫場景)
BUG描述:在某個游戲地圖中遇到美女玩家,關(guān)注對方后,本應(yīng)自動發(fā)送預(yù)定義招呼語,對方卻遲遲沒有收到。
根因分析:好友鏈這種業(yè)務(wù)很適合用Redis做主數(shù)據(jù)庫(提供靈活的hash/set/zset)。但是社區(qū)版Redis天然弱一致,原理同上,由于臟讀發(fā)生,讀寫分離必踩坑。
2. 如何解決?
做讀寫分離的初衷,其實(shí)還是對算力水平擴(kuò)展有訴求,同時也是不想讓那些“Slave”們閑置浪費(fèi)(畢竟算力成本也是錢吶)。
其實(shí),數(shù)據(jù)庫不止MySQL一種,緩存也不止Redis一種。
華為云GaussDB(for Redis)作為企業(yè)級定位的KV數(shù)據(jù)庫,已經(jīng)在很多業(yè)務(wù)場景被用作 “主數(shù)據(jù)庫”了,單實(shí)例存儲TB級數(shù)據(jù)是家常便飯。
GaussDB(for Redis)可以根除讀寫分離的一致性問題,原因如下:
1)支持36個節(jié)點(diǎn),全都可讀可寫(全員Master,算力別浪費(fèi))
2)數(shù)據(jù)強(qiáng)一致(無需主從分離,并發(fā)訪問任一節(jié)點(diǎn)都無臟讀)
3)單實(shí)例承載數(shù)百萬QPS(高吞吐需求從來不是事)
很顯然,高斯Redis完全可以滿足“既要、又要”的業(yè)務(wù)訴求,讓游戲遠(yuǎn)離讀寫分離之“坑”。
【有人可能會說,對不起,我是土豪,Slave就只用于高可用,我的業(yè)務(wù)不讀它,這樣總不會踩坑了吧?其實(shí),隱患還是存在的!】
場景二:主從切換引起的數(shù)據(jù)不一致問題
請時刻注意,你使用的數(shù)據(jù)庫,不論是MySQL還是Redis,他們都是高可用的。而高可用意味著,當(dāng)主節(jié)點(diǎn)故障時,它們會發(fā)生主從切換。
1. 主從切換引發(fā)的BUG
BUG描述:暑假做活動,全服玩家參與搶購100件稀有裝備(官方公告:每件都是全服僅有)。后來在公會PK時,持有“屠龍刀”的玩家A遇到了持有“屠龍刀”的玩家B……發(fā)生了“撞刀”。
根因分析:活動期間,業(yè)務(wù)使用了一套Redis主從做搶購,創(chuàng)建一個Redis隊(duì)列存稀有裝備。活動期間請求量高,Redis發(fā)生了主從切換。于是BUG就這樣發(fā)生了:本來隊(duì)列已經(jīng)pop掉了“屠龍刀”,但是由于主從同步延遲,從節(jié)點(diǎn)頂上來后,其中隊(duì)列內(nèi)的“屠龍刀”此時還沒有被pop掉!活動繼續(xù),于是隨后兩個玩家同時擁有了“屠龍刀”。
2. 如何解決?
開源Redis主從切換導(dǎo)致的此類BUG其實(shí)很常見,業(yè)務(wù)以為訪問的數(shù)據(jù)是穩(wěn)定的,但其實(shí)社區(qū)版Redis隨時可能“突變”(主從切換)導(dǎo)致業(yè)務(wù)讀到舊數(shù)據(jù)。
解決辦法還是一樣——做正確的數(shù)據(jù)庫選型,使用華為云GaussDB(for Redis)。
為什么說GaussDB(for Redis)沒有這類問題:
1)數(shù)據(jù)強(qiáng)一致存儲,故障場景業(yè)務(wù)不會發(fā)生臟讀
2)故障秒級恢復(fù)(社區(qū)版Redis啟動慢,需加載全量數(shù)據(jù),故障恢復(fù)慢)
3)存算分離架構(gòu),容忍N(yùn)-1分片故障(社區(qū)版Redis只要故障1對分片,業(yè)務(wù)無法恢復(fù))
使用高斯Redis,完全不用擔(dān)心臟讀發(fā)生。
結(jié)語
其實(shí)在很多業(yè)務(wù)場景,如果不希望出現(xiàn)臟讀導(dǎo)致業(yè)務(wù)BUG,那么華為云的高斯Redis的確是最佳數(shù)據(jù)庫選型。另外,高斯Redis自帶了冷熱數(shù)據(jù)交換能力,本身也是一個兼顧了性能與成本的降本方案,像是游戲公司常用的protobuf序列化數(shù)據(jù),高斯Redis能實(shí)現(xiàn)500G到160G的數(shù)據(jù)壓縮(案例數(shù)據(jù)),輕松節(jié)省70%存儲空間。
高斯Redis既能為游戲業(yè)務(wù)保駕護(hù)航,又省心省力省錢,何樂而不為!
附錄
- 本文作者:華為云數(shù)據(jù)庫GaussDB(for Redis)團(tuán)隊(duì)
- 更多產(chǎn)品信息,歡迎訪問官方博客:bbs.huaweicloud.com/blogs/248875
點(diǎn)擊關(guān)注,第一時間了解華為云新鮮技術(shù)~
總結(jié)
以上是生活随笔為你收集整理的游戏开发常遇到数据一致性BUG,怎么解?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: P3356 火星探险问题
- 下一篇: 采购前辈的教导