轉載:https://mp.weixin.qq.com/s/exE_UmZDeeWZKGNhbOFJMQ 作者|張輝清、楊麗編輯|雨多田光 文末有 demo 下載 Redis的使用難嗎?不難,Redis用好容易嗎?不容易。Redis的使用雖然不難,但與業務結合的應用場景特別多、特別緊,用好並不容易。 ...
轉載:https://mp.weixin.qq.com/s/exE_UmZDeeWZKGNhbOFJMQ
作者|張輝清、楊麗編輯|雨多田光
文末有 demo 下載
Redis的使用難嗎?不難,Redis用好容易嗎?不容易。Redis的使用雖然不難,但與業務結合的應用場景特別多、特別緊,用好並不容易。我們希望通過一篇文章及Demo,即可輕鬆、快速入門並學會應用。一、Redis 簡介
Redis是一個開源的Key-Value存儲,但又不僅僅是Key-Value存儲,用官網上的話來說,Redis是一個數據結構存儲,可用作資料庫、緩存和消息中間件。相對於傳統的Key-Value存儲Memcached來說,Redis具有如下特點:
-
速度快
-
豐富的數據結構,除String之外,還有List、Hash、Set、Sorted Set
-
單線程,避免了線程切換和鎖的性能消耗
-
原子操作
-
可持久化(RDB與AOF)
-
發佈/訂閱
-
支持Lua腳本
-
分散式鎖
-
事務
-
主從複製與高可用(Redis Sentinel)
-
集群(3.0版本以上)
二、Redis 數據結構
1、String
這是最簡單的Redis類型。如果只使用這種類型,Redis就像一個可持久化的Memcached伺服器。
2、List
Redis的List是基於雙向鏈表實現的,可以支持反向查找和遍歷。
常用案例:聊天系統、社交網路中獲取用戶最新發表的帖子、簡單的消息隊列、新聞的分頁列表、博客的評論系統。
3、Hash
Hash是一個String類型的field和value之間的映射表,請見下圖,類似於.NET中的Hashtable和Dictionary。主要用來存儲對象,可以避免序列化的開銷和併發修改控制的問題。
4、Set
Set也是一個列表,不過它的特殊之處在於它是可以自動排重的:當需要存儲一個列表數據,而又不希望出現重覆的時候,Set是一個很好的選擇(比如ID的集合)。並且Set提供了判斷某個成員是否在一個Set集合內的介面,這也是List所沒有的。
5、Sorted Set
Sorted Set和Set的使用場景類似,區別是Sorted Set會根據提供的score參數來進行自動排序。當你需要一個有序的並且不重覆的集合列表,那麼就可以選擇Sorted Set數據結構。常用案例:游戲中的排行榜。
三、 Redis 重要特性
以下特性請重點看管道和事務。
1、管道
Redis管道是指客戶端可以將多個命令一次性發送到伺服器,然後由伺服器一次性返回所有結果。管道技術在批量執行命令的時候可以大大減少網路傳輸的開銷,提高性能。
2、事務
Redis事務是一組命令的集合。一個事務中的命令要麼都執行,要麼都不執行。如果命令在運行期間出現錯誤,不會自動回滾。
管道與事務的區別:管道主要是網路上的優化,客戶端緩衝一組命令,一次性發送到伺服器端執行,但是並不能保證命令是在同一個事務裡面執行;而事務是原子性的,可以確保命令執行的時候不會有來自其他客戶端的命令插入到命令序列中。
3、分散式鎖
分散式鎖是控制分散式系統之間同步訪問共用資源的一種方式。在分散式系統中,常常需要協調他們的動作,如果不同的系統或是同一個系統的不同主機之間共用了一個或一組資源,那麼訪問這些資源的時候,往往需要互斥來防止彼此干擾來保證一致性,在這種情況下,便需要使用到分散式鎖。
4、地理信息
從Redis 3.2版本開始,新增了地理信息相關的命令,可以將用戶給定的地理位置信息(經緯度)存儲起來,並對這些信息進行操作。
四、 使用方法
步驟1、在需要使用Redis的項目中引用FxCommon.dll和Redis.dll。
步驟2、在App.config或Web.config文件中添加如下配置:
<add key="RedisServerIP" value="redis:[email protected]:4125"/>
<!-- 提供的 Redis 環境是單機版配置。如果 Redis 是主從配置,則還需設置 RedisSlaveServerIP-->
<!--<add key="RedisSlaveServerIP" value="redis:[email protected]:4125"/>-->
<!--Redis 資料庫。如果不需要指定 Redis 資料庫,就配置預設值 0-->
<add key="RedisDefaultDb" value="0"/>
步驟 3、使用 PooledRedisClientManager 類創建 Redis 連接池:
// 讀取 Redis 主機 IP 配置信息
string[] redisMasterHosts = ConfigurationManager.ConnectionStrings["RedisServerIP"].ConnectionString.Split(',');
// 如果 Redis 伺服器是主從配置,那麼還需要讀取 Redis Slave 機的 IP 配置信息
string[] redisSlaveHosts = null;
var slaveConnection = ConfigurationManager.ConnectionStrings["RedisSlaveServerIP"];
if (slaveConnection != null && !string.IsNullOrWhiteSpace(slaveConnection.ConnectionString))
{
string redisSlaveHostConfig = slaveConnection.ConnectionString;
redisSlaveHosts = redisSlaveHostConfig.Split(',');
}
// 讀取 RedisDefaultDb 配置
int defaultDb = 0;
string defaultDbSetting = ConfigurationManager.AppSettings["RedisDefaultDb"];
if (!string.IsNullOrWhiteSpace(defaultDbSetting))
{
int.TryParse(defaultDbSetting, out defaultDb);
}
var redisClientManagerConfig = new RedisClientManagerConfig
{
MaxReadPoolSize = 50,
MaxWritePoolSize = 50,
DefaultDb = defaultDb
};
// 創建 Redis 連接池
Manager = new PooledRedisClientManager(redisMasterHosts, redisSlaveHosts, redisClientManagerConfig)
{
PoolTimeout = 2000,
ConnectTimeout = 500
};
步驟4、通過PooledRedisClientManager的實例獲取Redis客戶端,然後就可以開始通過Redis客戶端的API進行操作。
五、其它
5.1、 Redis Key命名規範
Redis Key命名規範:AppID:KeyName。
可能有很多人習慣用英文狀態的點號來作為AppID和KeyName的分隔符,而筆者建議使用冒號作為AppID和KeyName的分隔符,其原因是:這麼寫會使Redis Key會以AppID作為分類顯示在Redis Desktop Manager中,方便你能夠快速查到要查閱的Redis Key對應的Redis Value值,請見下圖:
但如果使用英文狀態的點號來作為分隔符的話,那麼在Redis Desktop Manager中,Redis Key就不會被分類了,請見下圖:
5.2、常見應用問題
-
緩存穿透處理:什麼是緩存穿透?當根據Redis key在緩存中查詢後,不存在對應Value,就應該會在後端系統如DB中去查找,該Key的併發請求量一旦變大,那麼就會對DB造成很大的壓力。解決辦法有:a.前端風險控制,將惡意穿透情況排除在外;b.對查詢結果為空的情況依然進行緩存,但緩存時間會設置得很短,一般是幾分鐘。
-
緩存雪崩處理:什麼是緩存雪崩?當緩存伺服器重啟或者大量緩存集中在某一個時間段失效,這樣在失效的時候,也會給後端系統(比如DB)帶來很大壓力。解決辦法有:後端連接數限制,錯誤閾值限制,超時處理,緩存失效時間均勻分佈,前端永不失效及後端主動更新。
-
緩存時長:策略定位複雜,需要多維度的計算。
-
緩存失效:按時失效,事件失效,後端主動更新。
-
緩存Key:Hash、規則、首碼+Hash,異常情況可人工干預。
-
Lua腳本:服務端批量處理及事務能力,有條件邏輯的可擴展腳本。使用它的好處有:減少網路開銷、原子操作、可復用。
-
Limit:可滑動時間視窗,如應用於Session,Memcached需每次傳Key和Value。
六、Demo 下載及更多資料
-
RedisDemo下載地址:
-
RedisDesktopManage下載地址:
-
Redis官網:
-
ServiceStack.Redis客戶端:
-
Redis命令大全: