基本使用
StackExchange.Redis 中核心對象是在 StackExchange.Redis
命名空間中的 ConnectionMultiplexer
類,這個對象隱藏了多個服務器的詳細信息。
因為ConnectionMultiplexer
要做很多事,它被設計為在調用者之間可以共享和重用。
你不應該在執行每一個操作的時候就創建一個 ConnectionMultiplexer
. 它完全是線程安全的,并準備好這種用法(多線程)。
在后續所有的例子中,我們假設你有一個ConnectionMultiplexer
類的實例保存以重用。
但現在,讓我們來先創建一個。 這是使用 ConnectionMultiplexer.Connect
或 ConnectionMultiplexer.ConnectAsync
完成的,傳遞配置字符串或ConfigurationOptions
對象。
配置字符串可以采用逗號分隔的一系列節點的形式,所以讓我們在默認端口(6379)上連接到本地機器上的一個實例:
using StackExchange.Redis;
...
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost");
// ^^^ store and re-use this!!!
請注意,ConnectionMultiplexer
實現了 IDisposable
接口而且可以在不再需要的時候處理釋放掉。
這是故意不展示使用 using
語句用法,因為你想要只是簡單地使用一個ConnectionMultiplexer
的情況是極少見的 ,因為想法是重用這個對象。
更復雜的情況可能涉及主/從設置; 對于此用法,只需簡單的指定組成邏輯redis層的所有所需節點(它將自動標識主節點)
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("server1:6379,server2:6379");
如果它發現兩個節點都是主節點,則可以可選地指定可以用于解決問題的仲裁密鑰,然而幸運地是這樣的條件是非常罕見的。
一旦你有一個 ConnectionMultiplexer
,你可能有3個主要想做的事:
- 訪問一個 redis 數據庫(注意,在集群的情況下,單個邏輯數據庫可以分布在多個節點上)
- 使用 redis 的的 發布/訂閱 功能
- 訪問單獨的服務器以進行維護/監視
使用 redis 數據庫
訪問redis數據庫非常簡單:
IDatabase db = redis.GetDatabase();
從 GetDatabase
返回的對象是一個成本很低的通道對象,不需要存儲。
注意,redis支持多個數據庫(雖然“集群”不支持),這可以可選地在調用 GetDatabase
中指定。
此外,如果您計劃使用異步API,您需要 Task.AsyncState
有一個值,也可以指定:
int databaseNumber = ...
object asyncState = ...
IDatabase db = redis.GetDatabase(databaseNumber, asyncState);
一旦你有了'IDatabase',它只是一個使用 redis API 的情況。
注意,所有方法都具有同步和異步實現。
根據微軟的命名指導,異步方法都以 ...Async(...)
結尾,并且完全是可以等待的 await
等。
最簡單的操作也許是存儲和檢索值:
string value = "abcdefg";
db.StringSet("mykey", value);
...
string value = db.StringGet("mykey");
Console.WriteLine(value); // writes: "abcdefg"
需要注意的是,這里的 String...
前綴表示 redis 的 String 類型,盡管它和 .NET 的字符串類型 都可以保存文本, 它們還是有較大差別的。
然而,redis 還允許鍵和值使用原始的二進制數據,用法和字符串是一樣的:
byte[] key = ..., value = ...;
db.StringSet(key, value);
...
byte[] value = db.StringGet(key);
覆蓋所有redis數據類型的所有 [redis數據庫命令](http://redis.io/commands)的都是可以使用的。
使用 redis 發布/訂閱
redis的另一個常見用法是作為 發布/訂閱消息分發工具;
這也很簡單,并且在連接失敗的情況下, ConnectionMultiplexer
將處理重新訂閱所請求的信道的所有細節。
ISubscriber sub = redis.GetSubscriber();
同樣,從 GetSubscriber
返回的對象是一個不需要存儲的低成本的通道對象。
發布/訂閱 API沒有數據庫的概念,但和之前一樣,我們可以選擇的提供一個異步狀態。
注意,所有訂閱都是全局的:它們不限于 ISubscriber
實例的生命周期。
redis中的 發布/訂閱 功能使用命名的“channels”; channels 不需要事先在服務器上定義(這里有一個有趣的用法是利用每個用戶的通知渠道類驅動部分的實時更新)
如在.NET中常見的,訂閱采用回調委托的形式,它接受通道名稱和消息:
sub.Subscribe("messages", (channel, message) => {
Console.WriteLine((string)message);
});
另外(通常在一個單獨的機器上的一個單獨的進程),你可以發布到該通道:
sub.Publish("messages", "hello");
這將(實際上瞬間)將“hello”寫到訂閱進程的控制臺。 和之前一樣,通道名和消息都可以是二進制的。
有關順序和并發消息處理的使用文檔說明,請參見 發布/訂閱消息順序 。
訪問單獨的服務器
出于維護目的,有時需要發出服務器特定的命令:
IServer server = redis.GetServer("localhost", 6379);
GetServer
方法會接受一個 EndPoint
終結點或者是一個可以唯一標識一個服務器的鍵/值對。
像之前介紹的那樣, GetServer
方法返回的是一個不需要被存儲的輕量級的通道對象,并且可以可選的指定 async-state(異步狀態)。
需要注意的是,多個可用的節點也是可以的:
EndPoint[] endpoints = redis.GetEndPoints();
一個 IServer
實例是可以使用服務器命令的 Server commands,例如:
DateTime lastSave = server.LastSave();
ClientInfo[] clients = server.ClientList();
同步 vs 異步 vs 執行后不理
StackExchange.Redis有3種主要使用機制:
同步 - 適用于操作在方法返回到調用者之前完成(注意,盡管這可能阻止調用者,但它絕對不會阻止其他線程:StackExchange.Redis的關鍵思想是它積極地與并發調用者共享連接)
Asynchronous - where the operation completes some time in the future, and a
Task
orTask<T>
is returned immediately, which can later:異步 - 操作在將來完成一些時間,并且立即返回一個
Task
或 'Task<T>' 對象,也可以稍后再返回:是可以等待的(阻塞當前線程,直到響應可用)
.Wait()
可以增加一個后續的回調 (TPL 中的
ContinueWith
)awaited 可等待的(這是簡化后者的語言級特性,同時如果答復已經知道也立即繼續)
執行后不理 - 適用于你真的對這個回復不感興趣,并且樂意繼續不管回應
同步的用法已經在上面的示例中展示了。這是最簡單的用法,并且不涉及 TPL。
對于異步使用,關鍵的區別是方法名稱上的 Async
后綴,以及(通常)使用“await”語言特性。例如:
string value = "abcdefg";
await db.StringSetAsync("mykey", value);
...
string value = await db.StringGetAsync("mykey");
Console.WriteLine(value); // writes: "abcdefg"
執行后不理 的用法可以通過所有方法上的可選參數 CommandFlags flags
(默認值為 null
)來訪問使用。
這種用法中,方法會立即方法一個默認值(所以通常返回一個 String
的方法總是返回 null
,而一個通常返回一個 Int64
的方法總是返回 0
)。
操作會在后臺繼續執行。這種情況的典型用例可能是增加頁面瀏覽數量:
db.StringIncrement(pageKey, flags: CommandFlags.FireAndForget);
查看原文
More
作者水平有限,若有疏漏或錯誤還望提醒,十分感謝。
您可以在這里 提出問題 。