最近這幾天,一直在思考寫伺服器的時候怎麼做資料庫的讀寫服務,用什麼架構來做這個事情,現在終於有了一個大概的想法,用redis+mysql的方法。 目前業內有兩種思路,一種是full-mem模式,即全用redis存儲這種方式。另外一種是redis只存熱數據,大部分數據放到mysql里。具體選哪種還是要 ...
最近這幾天,一直在思考寫伺服器的時候怎麼做資料庫的讀寫服務,用什麼架構來做這個事情,現在終於有了一個大概的想法,用redis+mysql的方法。
目前業內有兩種思路,一種是full-mem模式,即全用redis存儲這種方式。另外一種是redis只存熱數據,大部分數據放到mysql里。具體選哪種還是要看具體的需求。
一般而言,純redis用於數據量比較小,讀寫極為頻繁的狀況,而redis+mysql結合是用於解決數據量比較大,而且冷數據比較多的情況。必定redis的價格還是蠻高的,一臺2G的redis節點阿裡雲只需要270一個月,而一臺256G的redis節點就要5W一個月,一年就是60W,用來發點獎金啥的都挺好的。
我決定暫時用redis+mysql結合的方式,redis中只存3天或7天以後用戶訪問過的數據,mysql中存儲其他的數據。大概思路如下:
啟動階段:
從mysql中讀取一部分常用的不會在伺服器運行過程中修改的配置表,根據實際需求初始化成各種redis的表,方便查詢。比如一個道具配置表的結構是:
CREATE TABLE `standard_item` ( `sn` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'sn', `id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '物品id', `name` varchar(50) NOT NULL DEFAULT '11' COMMENT '道具名', `type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '類型', `sub_type` smallint(5) unsigned NOT NULL DEFAULT '0', `quality` tinyint(4) NOT NULL DEFAULT '0' COMMENT '品質', `stacked_num` smallint(6) NOT NULL DEFAULT '0' COMMENT '堆疊數量', `use_num` smallint(6) NOT NULL DEFAULT '0' COMMENT '使用數量', `is_use` tinyint(4) NOT NULL DEFAULT '0', `price` smallint(6) NOT NULL DEFAULT '0', `effect` varchar(50) DEFAULT NULL, `version` int(10) NOT NULL DEFAULT '0' COMMENT '球員碎片對應的版本', PRIMARY KEY (`sn`), KEY `IX_Type` (`type`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=2478 DEFAULT CHARSET=utf8 COMMENT='標準物品表';
這個表在redis中存儲一般會是以standard_item:id為key的哈希表,但是策劃如果有需求根據type和quality查詢所有道具的話,我就應該在初始化的階段將standard_item多轉存出幾個standard_item:type:quality為主鍵的set來,以啟動時候預處理的時間來換取運行階段大量查詢的時間,或者避免用戶查詢的時候擊穿redis到mysql資料庫。
啟動完成以後,讀運算:
用戶請求伺服器===》 伺服器查詢redis是否有用戶緩存
===》如果有返回數據併進行對應運算
===》如果沒有,擊穿緩存層,訪問mysql資料庫讀取數據===》返回數據並保存至redis,標記3天後過期
啟動完成後,寫運算:
伺服器有寫請求===》將寫請求置入寫的隊列,解除數據的過期時間
寫數據的線程===》如果隊列中有需要寫的數據,就取出一條進行mysql寫操作===》寫入成功,標記redis數據3天後過期
===》寫入失敗,重寫至次數嘗試超過限定次數,寫日誌
===》如果隊列中沒有需要寫的數據,休眠一小會
明天按照這個思路試著做套資料庫讀寫機制試下。