在StackExchange.Redis中最重要的對象是ConnectionMultiplexer類, 它存在於StackExchange.redis命名空間中。
這個類隱藏了Redis服務的操做細節,ConnectionMultiplexer類作了不少東西, 在全部調用之間它被設計爲共享和重用的。
不該該爲每個操做都建立一個ConnectionMultiplexer 。 ConnectionMultiplexer是線程安全的 , 推薦使用下面的方法。
在全部後續示例中 , 都假定你已經實例化好了一個ConnectionMultiplexer類,它將會一直被重用 ,
如今咱們來建立一個ConnectionMultiplexer實例。它是經過ConnectionMultiplexer.Connect 或者 ConnectionMultiplexer.ConnectAsync,
傳遞一個鏈接字符串或者一個ConfigurationOptions 對象來建立的。
鏈接字符串能夠是以逗號分割的多個服務的節點, 咱們僅僅須要鏈接一個在本地計算機中的redis服務,redis服務的默認端口是6379.mysql
using StackExchange.Redis;
...
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost");
// ^^^ store and re-use this!!!redis
注意 : ConnectionMultiplexer 實現了IDisposable接口當咱們再也不須要是能夠將其釋放的 , 這裏我故意不使用 using 來釋放他。 簡單來說建立一個ConnectionMultiplexer是十分昂貴的 , 一個好的主意是咱們一直重用一個ConnectionMultiplexer對象。
一個複雜的的場景中可能包含有主從複製 , 對於這種狀況,只須要指定全部地址在鏈接字符串中(它將會自動識別出主服務器)
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("server1:6379,server2:6379");sql
假設這裏找到了兩臺主服務器,將會對兩臺服務進行裁決選出一臺做爲主服務器來解決這個問題 , 這種狀況是很是罕見的 ,咱們也應該避免這種狀況的發生。shell
如今你已經擁有了一個 ConnectionMultiplexer , 下面三件事情多是你想要作的。數據庫
1. 訪問數據庫。(注意在使用集羣的狀況下,一個數據庫可能會分部在多個節點中)
2. 使用redis的發佈訂閱功能
3. 維護和監控一臺服務器windows
訪問數據庫
訪問數據庫的操做很是簡單:api
IDatabase db = redis.GetDatabase();緩存
GetDatabase 返回一個IDatabase接口。 注意 redis容許配置多個數據庫,能夠在調用GetDatabase() 時候指定數據庫.另外,若是你計劃使用異步的api , Task.AsyncState 必須擁有一個值 ,也能夠這樣指定。安全
int databaseNumber = ...
object asyncState = ...
IDatabase db = redis.GetDatabase(databaseNumber, asyncState);服務器
如今你已經擁有了一個 IDatabase 對象 , 他能夠對redis數據庫進行操做。全部的方法都有同步和異步兩個版本 , 按照微軟的命名約定 ,全部的異步方法都以Async結尾。
最簡單的操做 存儲和獲取一個值 。
string value = "abcdefg";
db.StringSet("mykey", value);
...
string value = db.StringGet("mykey");
Console.WriteLine(value); // writes: "abcdefg"
String前綴這裏表明的是Redis中的String類型 , 和.net中的String類型有很大的區別 , 儘管二者均可以保存字符串類型。而後 ,Redis容許鍵值爲二進制數據 , 示例以下:
byte[] key = ..., value = ...;
db.StringSet(key, value);
...
byte[] value = db.StringGet(key);
StackExchange.Redis 支持全部的 redis shell命令, 具體能夠參考redis官網。
使用Redis的發佈訂閱功能
redis另外一個常見的用途是發佈訂閱功能 。 它很是的簡單 ,當鏈接失敗時 ConnectionMultiplexer 會自動從新進行訂閱 。
ISubscriber sub = redis.GetSubscriber();
GetSubscriber 方法返回一個 ISubscriber 類型的實例 。發佈訂閱功能沒有數據庫的概念,咱們能夠爲其提供一個 async-state 。全部的訂閱都是全局的:
ISubscriber 實例不是他們的生命週期 , 發佈訂閱的特性在redis中被定義爲 「channels」 , 渠道不須要預先定義在數據庫中 。 訂閱操做須要一個渠道
名稱和一個回調函數來處理髮布的消息。
sub.Subscribe("messages", (channel, message) => {
Console.WriteLine((string)message);
});
你能夠發佈一個消息到指定的渠道中:
sub.Publish("messages", "hello");
他將會將 「hello」 這個消息發佈到全部訂閱了messages渠道的客戶端(幾乎是實時的)。 和以前同樣渠道的名稱和消息也能夠是二進制的。
指定消息發佈的順序(Message Order)
當使用 pub/sub API 時,你能夠指定消息是並行仍是有序的。
有序的意味着你不須要考慮線程安全的問題 ,同時也意味着消息會經過隊列徹底按照你發佈的順序來進行傳遞,這必然致使消息的延遲。
並行處理,不能保證消息是按照發布的順序來進行處理的,你的代碼也要保證當存在併發時程序運行正常,
消息的順序一般是可有可無的, 並行處理能夠得到更好的性能和擴展性。
爲確保安全,消息的傳遞默認是有序的。爲得到更好的性能強烈建議你使用並行操做 。 這是很是簡單的。
multiplexer.PreserveAsyncOrder = false;
建議並不是是你配置該選項的理由, 是否適合徹底取決與你訂閱消息的代碼。
訪問單個服務器
有時候須要爲單個服務器指定特定的命令 。
IServer server = redis.GetServer("localhost", 6379);
GetServer方法會接收一個EndPoint類或者一個惟一標識一臺服務器的鍵值對。GetServer 方法返回一個IServer對象。 方法也能夠是異步的只須要傳入一個async-state
可使用以下方法獲取全部可用的終結點:
EndPoint[] endpoints = redis.GetEndPoints();
使用IServer可使用全部的shell命令,好比:
DateTime lastSave = server.LastSave();
ClientInfo[] clients = server.ClientList();
若是報錯在鏈接字符串後加 ,allowAdmin=true;
同步 、異步、即發即棄
這是StackExchange.Redis的三種主要使用機制:
同步-在方法返回以前阻塞調用方(雖然會阻塞調用方,但毫不會阻塞其餘線程 ,StackExchange.Redis中的關鍵點是共享調用者之間的鏈接)
異步-在將來的某個時間點操做完成,會馬上返回一個 Task 或者 Task<T> : 以後能夠調用
.Wait() 阻塞當前線程,直處處理完成。
ContinueWith 添加一個回調函數
使用 await 這是一個高級特性簡化了操做
即發即棄-
在上面的示例中已經演示同步調用的方法 。
異步調用:
string value = "abcdefg";
await db.StringSetAsync("mykey", value);
...
string value = await db.StringGetAsync("mykey");
Console.WriteLine(value); // writes: "abcdefg"
即發即棄:經過配置 CommandFlags 來實現即發即棄功能,在該實例中該方法會當即返回,若是是string則返回null 若是是int則返回0.這個操做將會繼續在後臺運行,一個典型的用法頁面計數器的實現:
db.StringIncrement(pageKey, flags: CommandFlags.FireAndForget);
Configuration
redis有不少不一樣的方法來配置鏈接字符串 , StackExchange.Redis 提供了一個豐富的配置模型,當調用Connect 或者 ConnectAsync 時須要傳入。
var conn = ConnectionMultiplexer.Connect(configuration);
這裏的 configuration 參數能夠是:
1. 一個 ConfigurationOptions 實例
2. 一個字符串
第二種方式從根本上來講也是ConfigurationOptions。
經過字符串配置鏈接
最簡單的配置方式只須要一個主機名
var conn = ConnectionMultiplexer.Connect("localhost");
它將會鏈接到本地的redis服務器 , 默認6379端口 ,多個鏈接經過逗號分割 。 其餘選項在名稱的後面包含了一個 「= 」。 例如
var conn = ConnectionMultiplexer.Connect("redis0:6380,redis1:6380,allowAdmin=true");
能夠將一個字符串轉換爲ConfigurationOptions 或者 將一個ConfigurationOptions轉換爲字符串 。
ConfigurationOptions options = ConfigurationOptions.Parse(configString);
OR
string configString = options.ToString();
推薦的用法是將基礎信息保存在一個字符串中,而後在運行是經過ConfigurationOptions改變其餘信息。
string configString = GetRedisConfiguration();
var options = ConfigurationOptions.Parse(configString);
options.ClientName = GetAppName(); // only known at runtime
options.AllowAdmin = true;
conn = ConnectionMultiplexer.Connect(options);
也能夠指定密碼
var conn = ConnectionMultiplexer.Connect("contoso5.redis.cache.windows.NET,ssl=true,password=...");
配置選項
ConfigurationOptions 包含大量的配置選項,一些經常使用的配置以下:
abortConnect : 當爲true時,當沒有可用的服務器時則不會建立一個鏈接
allowAdmin : 當爲true時 ,可使用一些被認爲危險的命令
channelPrefix:全部pub/sub渠道的前綴
connectRetry :重試鏈接的次數
connectTimeout:超時時間
configChannel: Broadcast channel name for communicating configuration changes
defaultDatabase : 默認0到-1
keepAlive : 保存x秒的活動鏈接
name:ClientName
password:password
proxy:代理 好比 twemproxy
resolveDns : 指定dns解析
serviceName : Not currently implemented (intended for use with sentinel)
ssl={bool} : 使用sll加密
sslHost={string} : 強制服務器使用特定的ssl標識
syncTimeout={int} : 異步超時時間
tiebreaker={string}:Key to use for selecting a server in an ambiguous master scenario
version={string} : Redis version level (useful when the server does not make this available)
writeBuffer={int} : 輸出緩存區的大小
各配置項用逗號分割
自動和手動配置
在大部分的狀況下StackExchange.Redis 會自動的幫咱們配置不少選項。 好比 服務器類型,版本, 超時時間 , 主從服務器等..
儘管如此,有時候咱們須要在服務器上面排除一些命令, 這種狀況下有必要提供更多信息
ConfigurationOptions config = new ConfigurationOptions
{
EndPoints =
{
{ "redis0", 6379 },
{ "redis1", 6380 }
},
CommandMap = CommandMap.Create(new HashSet<string>
{ // EXCLUDE a few commands
"INFO", "CONFIG", "CLUSTER",
"PING", "ECHO", "CLIENT"
}, available: false),
KeepAlive = 180,
DefaultVersion = new Version(2, 8, 8),
Password = "changeme"
};
也可使用下面的字符串來設置:
redis0:6379,redis1:6380,keepAlive=180,version=2.8.8,$CLIENT=,$CLUSTER=,$CONFIG=,$ECHO=,$INFO=,$PING=
重命名命令
你能夠禁用或者重命名一個命令。 按照前面的示例這是經過 CommandMap 來完成的,不過上面使用Create( new HashSet<string> )來進行配置,咱們使用Dictionary<string,string>。設置null時表明禁用該命令
var commands = new Dictionary<string,string> {
{ "info", null }, // disabled
{ "select", "use" }, // renamed to SQL equivalent for some reason
};
var options = new ConfigurationOptions {
// ...
CommandMap = CommandMap.Create(commands),
// ...
}
也可使用下面的字符串來設置:
$INFO=,$SELECT=use
ConnectionMultiplexer 能夠註冊以下事件
ConfigurationChanged
- 配置更改時ConfigurationChangedBroadcast
- 經過發佈訂閱更新配置時ConnectionFailed
- 鏈接失敗 , 若是從新鏈接成功你將不會收到這個通知ConnectionRestored
- 從新創建鏈接以前的錯誤ErrorMessage
- 發生錯誤HashSlotMoved
- 更改集羣InternalError
- redis類庫錯誤