Hi,
敝人使用node.js+socket.io由多人多間網路聊天室開始建立遊戲系統。一開始存放房間設定(例如:用戶列表、可否加入、最多幾人等等)是使用JavaScript物件寫的,而這種做法在多服務器負載均衡下會出問題。曾經考慮過memcache,發現它無法進行修改操作(協定只有set/del...,不支援update)。redis也不適用,理由與memcache同。其他的要不慢了一點(e.g. MySQL -- 有人加入或離開房間都要query一次,不是速度挺慢的嗎?)、要不無法輕易伸縮。故請推薦符合創讀改刪、分散式鍵值儲存庫。
另,有甚麼第三方開源軟件可以套在memcache前面讓它支援CRUD的也行。不想輕易放棄memcache的原因是Amazon ElastiCache。
也許用 key-value 時 value 的部份,
不要放那麼多 要更動 的資料,
若是放 hash 通常只是用來讀出來而已。
用 redis 來模擬會類似這樣子操作:
初始化一個room
<pre class="c" name="code">sadd game:init poker:token:ABCDEFGHI
set poker:token:ABCDEFGHI someinfo
expire poker:token:ABCDEFGHI 30000
set poker:token:ABCDEFGHI:slots 4
因為 poker:token:ABCDEFGHI 超過時間 expire 掉,
key 會不見,系統裡會留一些 poker:token:ABCDEFGHI:* 的key,
所以要 game:init 的目的,
就是去掃 poker:token:ABCDEFGHI 這 key 在不在,
不在的話,把 poker:token:ABCDEFGHI:* 給清掉。
slots 數目、 users 拉出來各成個 key。
一個user加入時,加入到list並更動slots數(如果一個user佔一個slot的話):
<pre class="c" name="code">sadd poker:token:ABCDEFGHI:users user1
decr poker:token:ABCDEFGHI:slots
在 poker:token:ABCDEFGHI 未 expire 且 poker:token:ABCDEFGHI:slots 是 0 時,
<pre class="c" name="code">smove game:init game:start
如果要知道 poker:token:ABCDEFGHI 剩多少時間:
<pre class="c" name="code">ttl poker:token:ABCDEFGHI
這種會用到因時間而區分狀態的情況,
就會利用 redis 裡的 Sets, expire, incr, decr 的特性。
如果要偵測user是否斷線,一個user的session為一key:
<pre class="c" name="code">expire user:user1:sesion:xxxxx 120
有任何動作都作這個動作。
只要超過兩分鐘沒作到這動作,key會消失掉就算斷線。
分數也可設這樣的 key 來做累計:
<pre class="c" name="code">incrby user:user1:sesion:xxxxx:score 5
若要同時做該 user 的有史以來的總累計可再加上:
<pre class="c" name="code">incrby user:user1:total:score 5
當然這些是 score 是在線時在 redis 裡進行,
離線後 redis 仍存有一堆資料,
那時可再看若太大量久未存取變動的score資料,
再選擇放到傳統的資料庫裡。
user上線,再拉到redis做累計。
@twtw:那redis如何在Amazon AWS達成分散式架構?
目前自己未用到數據大量的情況,
而欠缺相關的經驗。
而 redis 目前最多只有 replication 主從架構,
cluster 還只有規格而已 Redis cluster Specification (work in progress)
雖然如此,仍有用 Scale redis 的例子:
1,000,000 daily users and no cache
新浪微博開放平台redis實踐
這篇也提了怎麼擴展的方式:
Scaling Redis