為什么游戲行業(yè)喜歡用 PolarDB
為什么游戲行業(yè)喜歡用PolarDB
游戲行業(yè)痛點(diǎn)
在我看來, 不同行業(yè)對(duì)數(shù)據(jù)庫(kù)使用有巨大的差別. 比如游戲行業(yè)沒有復(fù)雜的事務(wù)交易場(chǎng)景, 他有一個(gè)非常大的blob 字段用于存儲(chǔ)角色的裝備信息, 那么大Blob 字段的更新就會(huì)成為數(shù)據(jù)庫(kù)的瓶頸, 比如在線教育行業(yè)需要有搶課的需求, 因此會(huì)有熱點(diǎn)行更新的場(chǎng)景, 對(duì)熱點(diǎn)行如何處理會(huì)成為數(shù)據(jù)庫(kù)的瓶頸, 比如SaaS 行業(yè), 每一個(gè)客戶有一個(gè)Database, 因此會(huì)有非常多的Table, 那么數(shù)據(jù)庫(kù)就需要對(duì)多表有很好的支持能力。
游戲行業(yè)和其他行業(yè)對(duì)數(shù)據(jù)庫(kù)的使用要求是不一樣的。
所以在支撐了大量游戲業(yè)務(wù)之后, 我理解游戲行業(yè)在使用自建MySQL 的時(shí)候有3個(gè)比較大的痛點(diǎn)
- 對(duì)備份恢復(fù)的需求
- 對(duì)寫入性能的要求
- 對(duì)跨region 容災(zāi)的需求
接下來會(huì)分別講述這三個(gè)痛點(diǎn)PolarDB 是如何解決的。
備份恢復(fù)
筆者和大量游戲開發(fā)者溝通中, 游戲行業(yè)對(duì)備份恢復(fù)的需求是極其強(qiáng)烈的. 比如在電商行業(yè), 是不可能存在將整個(gè)數(shù)據(jù)庫(kù)實(shí)例進(jìn)行回滾到一天之前的數(shù)據(jù), 這樣所有的用戶的購(gòu)買交易信息都丟失了。
但是, 在游戲行業(yè)中, 這種場(chǎng)景確實(shí)存在的, 比如在發(fā)版的時(shí)候, 游戲行業(yè)是有可能發(fā)版失敗, 這個(gè)在其他行業(yè)出現(xiàn)概率非常低, 如果發(fā)版失敗, 那么整個(gè)實(shí)例就需要回滾到版本之前. 因此每次發(fā)版的時(shí)候都需要對(duì)數(shù)據(jù)庫(kù)實(shí)例進(jìn)行備份. 因此當(dāng)我們玩游戲的時(shí)候, 看到大版本需要停服更新, 那么就有可能是因?yàn)楹笈_(tái)需要備份數(shù)據(jù)等等一系列操作了。
還有一種場(chǎng)景, 當(dāng)發(fā)生因?yàn)?漏洞, 參數(shù)配置錯(cuò)誤等等場(chǎng)景下, 這種緊急情況游戲就需要回滾到出問題前的版本, 這樣就需要對(duì)整個(gè)實(shí)例進(jìn)行回滾。
官方MySQL 由于是單機(jī)架構(gòu), 那么常見的備份方法是通過Xtrabackup 工具, 將數(shù)據(jù)備份到本地以后, 如果本地空間不夠, 就需要上傳到OSS 等遠(yuǎn)端存儲(chǔ)中. 通常通過Xtrabackup 備份工具都需要1h 左右, 如果需要將數(shù)據(jù)上傳到遠(yuǎn)端那么時(shí)間就更長(zhǎng)了。
PolarDB 是天然的計(jì)存分離的架構(gòu), 那么備份的時(shí)候通過底下分布式存儲(chǔ)的快照能力, 備份可以不超過30s, 將備份時(shí)間大大縮短了。
核心思路是采用Redirect-on-Write 機(jī)制, 每次創(chuàng)建快照并沒有真正Copy數(shù)據(jù), 只有建立快照索引, 當(dāng)數(shù)據(jù)塊后期有修改(Write)時(shí)才把歷史版本保留給Snapshot, 然后生成新的數(shù)據(jù)塊, 被原數(shù)據(jù)引用(Redirect)。
另外一種場(chǎng)景是, 在游戲行業(yè)中, 有可能某一個(gè)玩家的裝備被盜號(hào)了, 那么玩家就會(huì)找游戲的運(yùn)營(yíng)人員投訴, 運(yùn)營(yíng)人員會(huì)找到游戲運(yùn)維人員, 幫忙查詢玩家的歷史數(shù)據(jù)。
筆者之前就遇到某著名游戲多個(gè)玩家被盜號(hào), 然后運(yùn)維人員經(jīng)常需要通過PolarDB 按時(shí)間的還原的能力恢復(fù)出某多個(gè)不同時(shí)間點(diǎn)的實(shí)例, 用來查詢這個(gè)玩家的具體裝備信息, 同時(shí)由于玩家對(duì)盜號(hào)的時(shí)間也不準(zhǔn)確, 經(jīng)常有時(shí)候需要還原出多個(gè)實(shí)例才可以。
針對(duì)這樣的場(chǎng)景, PolarDB 推出了Flashback Query, 就可以在當(dāng)前實(shí)例查詢出任意時(shí)間點(diǎn)的歷史數(shù)據(jù). 具體原理見文章 Flashback Query
整體而言, PolarDB 建立了一套非常完善的備份恢復(fù)能力, 從庫(kù)=>表=>行三個(gè)維度滿足的游戲行業(yè)對(duì)備份恢復(fù)的需求。
寫入性能
游戲行業(yè)使用數(shù)據(jù)庫(kù)的方式也與其他行業(yè)有較大區(qū)別, 是一種非常弱Schema 的使用方式, 其他行業(yè)通常對(duì)業(yè)務(wù)經(jīng)常抽象, 建立表結(jié)構(gòu), 每個(gè)字段盡可能小, 不建議有大字段, 有大字段盡可能進(jìn)行拆封等等.但是在游戲行業(yè)中, 由于需要滿足游戲快速迭代發(fā)展的需求, 玩家的裝備信息結(jié)構(gòu)非常復(fù)雜, 因此常見的做法是將玩家裝備等級(jí)信息保存在一個(gè)大的blob字段中, 這個(gè)blob字段通過proto_buf 或者 json 進(jìn)行編解碼, 每次在獲得裝備或者升級(jí)以后, 就進(jìn)行整個(gè)字段更新, 在游戲開服初期玩家數(shù)據(jù)長(zhǎng)度較短, 而隨著游戲版本更新版本, 游戲劇情, 運(yùn)營(yíng)活動(dòng)的增多, 相對(duì)于游戲開服初期的數(shù)KB, blob字段的長(zhǎng)度可能會(huì)膨脹到數(shù)百KB, 甚至達(dá)到MB級(jí)別, 因此可能只是獲得一個(gè)裝備, 就需要向數(shù)據(jù)庫(kù)寫入數(shù)百KB 大小的數(shù)據(jù), 這樣的寫放大其實(shí)非常不合理。
目前也有像MongoDB 這樣的文檔數(shù)據(jù)庫(kù), 讓用戶寫入的時(shí)候僅僅更新某個(gè)字段, 從而減少寫放大. 但是這樣影響了用戶的使用習(xí)慣, 需要用戶在業(yè)務(wù)邏輯上進(jìn)行修改, 這是快速發(fā)展的游戲行業(yè)所不能接受的, 所以筆者看到盡管有客戶因?yàn)閷懭雴栴}轉(zhuǎn)向了MongoDB, 但是其實(shí)不多。
PolarDB 針對(duì)這樣的情況盡可能滿足用戶的使用習(xí)慣, 在數(shù)據(jù)庫(kù)內(nèi)核層面優(yōu)化數(shù)據(jù)庫(kù)的寫入能力. 通過 partition redo log, redo log cache, undo log readahead, early lock release, no blob latch 等等能力將寫入能力充分優(yōu)化。
具體原理可以參考我們內(nèi)核月報(bào) 和之前的文章PolarDB-cloudjump針對(duì)游戲場(chǎng)景, 我們修改了 sysbench 工具, 模擬游戲行業(yè)中大Blob 更新的workload, 放在 game-sysbench 工具中, 后續(xù)我們還會(huì)將更多行業(yè)比如Saas, 電商等等行業(yè)的workload 放在這個(gè)工具中。
在game_blob_update workload 中, 如果玩家的平均裝備信息是 300kb, 我們對(duì)比了PolarDB VS aurora VS 自建MySQL 的數(shù)據(jù)PolarDB 8.0 相對(duì)有最高的QPS 1877.44, 峰值QPS最高可以到2000, CPU bound場(chǎng)景PolarDB的性能大概是Aurora的5.7倍, 是自建 MySQL 本地盤的3倍. IO bound場(chǎng)景PolarDB的性能是Aurora的15倍。
CPU bound場(chǎng)景:
DB | 并發(fā)數(shù)據(jù) | QPS |
PolarDB 8.0 | 5 | 1877.44 |
MySQL 8.0 本地盤 | 4 | 600.22 |
Aurora 8.0 | 200 | 328.47 |
IO bound場(chǎng)景:
DB | 并發(fā)數(shù)據(jù) | QPS |
PolarDB 8.0 | 200 | 1035.30 |
MySQL 8.0 本地盤 | 200 | 610 |
Aurora 8.0 | 200 | 69.15 |
跨region 容災(zāi)
目前游戲行業(yè)紛紛出海, 包含了游戲服和平臺(tái)服. 用戶在自建MySQL/RDS 的場(chǎng)景中, 用戶可能需要在另外一個(gè)region 建立一個(gè)新的實(shí)例, 然后通過同步工具或者DTS 進(jìn)行跨region 備份. 用戶需要處理region 錯(cuò)誤場(chǎng)景如何進(jìn)行切換等等。
筆者認(rèn)為對(duì)數(shù)據(jù)庫(kù)而言, 穩(wěn)定性 > 易用性 > 性能.在這個(gè)場(chǎng)景中, 用戶如果使用云廠商的話, 使用的是云廠商提供的原子能力, 自己通過組裝這些原子能力實(shí)現(xiàn)容災(zāi)的需求, 而PolarDB 針對(duì)這樣場(chǎng)景提出來PolarDB GlobalDataba 的解決方案, 將跨region 的容災(zāi)放在解決方案中, 提供了一個(gè)更加易容的解決方案, 從而用戶可以關(guān)注自身的業(yè)務(wù)邏輯, 而不需要處理這些容災(zāi)的場(chǎng)景。
在具體跨region 的同步場(chǎng)景方案中, PolarDB 是通過多通道物理復(fù)制能力, 從而保證跨region 的容災(zāi)在1s 以內(nèi)。