Redis的持久化方式主要有2種:RDB和AOF,但各有不足,同時Redis沒有SQL支持,Redis本身提供的命令不足以實現大多數SQL查詢需求,對后期運營的分析需求支撐不足。此外,對於游戲來說,活躍玩家只占總玩家的很少一部分,所以冷熱數據分離也很有必要。因此我覺得Redis最好的持久化方案是備份到MySql之類的關系型數據庫中,Redis本身只作為一個內存緩存系統使用。
- 啟動過程:從數據庫里面把修改時間在過期時間內的記錄(熱數據)全部讀取寫入到Redis中,並設置過期時間。
- 讀取過程:先讀Redis,如果存在,則直接返回並更新過期時間(如果不存在過期時間則不更新),否則再去讀數據庫,讀取結果寫入到Redis中。如果數據庫中不存在,則也用記錄的key在Redis做一個不存在的標記,以避免之后再次查詢還需要去讀數據庫,拖慢速度。
- 寫入過程:直接寫入Redis(同時去掉過期時間),同時把key以當前時間為score寫入一個特定的sorted set(dirtylist)中。
- 持久化過程:持久化程序跟隨系統啟動,每隔一段時間獲取Redis的dirtylist中是否有元素,如果有元素則pop出來,通過key獲取記錄寫入數據庫,再把Redis中的key設置過期時間。
風險:
- 額外多了關系型數據庫這一個單點。如果數據庫發生了故障,則短時間內無法讀取冷數據,讀取熱數據和寫入都沒有問題。只要監控到位,反應及時,風險影響不大。
- 數據丟失的風險。如果Redis發生了故障,則會丟失寫入到Redis但還未持久化的記錄(dirtylist里面的記錄)。這一點無法避免,但單從游戲的角度來說,只要保證以事務為單位的持久化(比如說dirtylist同一時間的key,作為一個事務寫入到數據庫),出現問題可以通過短時間的回擋+補償解決問題。
這里只是記錄下一個思路,具體的問題和解決方案,等具體實踐了之后,再來補充。