緩存(Cache)
Redis的第一個應用場景是Redis作為緩存對象來加速Web應用的訪問。
在該場景下,有一些存儲于數(shù)據(jù)庫中的數(shù)據(jù)會被頻繁訪問,如果頻繁的訪問數(shù)據(jù)庫,數(shù)據(jù)庫負載會升高,同時由于數(shù)據(jù)庫IO比較慢,應用程序的響應會比較差。此時,如果引入Redis來存儲這些被頻繁訪問的數(shù)據(jù),就可以有效的降低數(shù)據(jù)庫的負載,同時提高應用程序的請求響應。
#會話存儲(Session)
使用Redis來存儲會話(Session)數(shù)據(jù),可以實現(xiàn)在無狀態(tài)的服務器之間共享用戶相關的狀態(tài)數(shù)據(jù)數(shù)據(jù)。
當用戶登錄Web應用時候,將會話數(shù)據(jù)存儲于Redis,并將唯一的會話ID(Session ID)返回到客戶端的Cookie中。當用戶再向應用發(fā)送請求時,會將此會話ID包含在請求中。無狀態(tài)的Web服務器,根據(jù)這個會話ID從Redis中搜索相關的會話數(shù)據(jù)來進一步請求處理。
這里需要注意的是,Redis是內(nèi)存數(shù)據(jù)庫,如果采用單實例部署。那么當Redis服務器故障重啟之后,所有的Session會話會消失,用戶不得不重新登錄來獲取新的Session。所以,當拿Redis來存儲Session的時候,建議采用主從的集群模式open in new window來部署。這樣,即使主服務器掛了,馬上有從庫接管流量,不影響用戶的使用。
#分布式鎖(Distributed Lock)
當我們在應用中部署了多個節(jié)點,這些節(jié)點需要操作同一個資源的時候會存在競爭。此時,我們可以使用Redis來作為分布式鎖,以協(xié)調(diào)多個節(jié)點對共享資源的操作。
這里主要是用Redis的原子操作命令:SETNX
,該命令僅允許key不存在的時候才能設置key。
下圖展示了一個簡單用例。Client 1通過SETNX
命令嘗試創(chuàng)建lock 1234abcd
。如果當前還沒有這個key,那么將返回1。Client 1獲得鎖,就可以執(zhí)行對共享資源的操作,操作完成之后,刪除剛剛創(chuàng)建的lock(釋放分布式鎖)。如果Client 1在執(zhí)行SETNX
命令的時候,返回了0,說明有其他客戶端占用了這key,那么等待一段時間(等其他節(jié)點釋放)之后再嘗試。
上面這個簡單實現(xiàn)雖然可以滿足很多用例,但它并不具備良好的容錯機制。如果要在生產(chǎn)上是用的話,更推薦采用一些更高質(zhì)量的分布式鎖實現(xiàn)。比如,Java平臺的話,可以選擇:Redisson.
#速率限制器(Rate Limiter)
由于Redis提供了計數(shù)器功能,所以我們可以通過該能力,配合超時時間,來實現(xiàn)速率限制器,最常見的場景就是服務端是用的請求限流。
一個基本的限速實現(xiàn)如下圖:
根據(jù)用戶id或者ip來作為key,使用INCR
命令來記錄用戶的請求數(shù)量。然后將該請求數(shù)量與允許的請求上限數(shù)量做比較,只有低于限制的時候,才會執(zhí)行請求處理。如果超過限制,就拒絕請求。
同時,請求數(shù)量的計數(shù)器需要設置一個時間窗口,比如:1分鐘。也就是沒過一分鐘時間,計數(shù)器將被清零,重新計數(shù)。所以,當一個時間窗口中被限流之后,等到下一個時間窗口,就能恢復繼續(xù)請求。以實現(xiàn)限制速率的效果。
除了時間窗算法之外,漏桶算法也能通過Redis來實現(xiàn)。
#排行榜(Rank/Leaderboard)
由于Redis提供了排序集合(Sorted Sets)的功能,所以很多游戲應用采用Redis來實現(xiàn)各種排行榜功能。
排序集合是唯一元素(比如:用戶id)的集合,每個元素按分數(shù)排序,這樣可以快速的按分數(shù)來檢索元素
#小結(jié)
Redis的應用非常廣泛,這里僅總結(jié)了一些常見的用法。除此之外,還有很多有意思的應用,這取決于業(yè)務場景。大家可以舉一反三。