stackExchange.redis的使用
阿新 • • 發佈:2017-08-16
shell bsp disabled dbr for 方式 shel point org 在StackExchange.Redis中最重要的對象是ConnectionMultiplexer類, 它存在於StackExchange.Redis命名空間中。
這個類隱藏了Redis服務的操作細節,ConnectionMultiplexer類做了很多東西, 在所有調用之間它被設計為共享和重用的。
不應該為每一個操作都創建一個ConnectionMultiplexer 。 ConnectionMultiplexer是線程安全的 , 推薦使用下面的方法。
在所有後續示例中 , 都假定你已經實例化好了一個ConnectionMultiplexer類,它將會一直被重用 ,
現在我們來創建一個ConnectionMultiplexer實例。它是通過ConnectionMultiplexer.Connect 或者 ConnectionMultiplexer.ConnectAsync,
傳遞一個連接字符串或者一個ConfigurationOptions 對象來創建的。
連接字符串可以是以逗號分割的多個服務的節點, 我們僅僅需要連接一個在本地計算機中的redis服務,redis服務的默認端口是6379.
using StackExchange.Redis;
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost");//127.0.0.1
// ^^^ store and re-use this!!!
註意 : ConnectionMultiplexer 實現了IDisposable接口當我們不再需要是可以將其釋放的 , 這裏我故意不使用 using 來釋放他。 簡單來講創建一個ConnectionMultiplexer是十分昂貴的 , 一個好的主意是我們一直重用一個ConnectionMultiplexer對象。
一個復雜的的場景中可能包含有主從復制 , 對於這種情況,只需要指定所有地址在連接字符串中(它將會自動識別出主服務器)
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("server1:6379,server2:6379");
假設這裏找到了兩臺主服務器,將會對兩臺服務進行裁決選出一臺作為主服務器來解決這個問題 , 這種情況是非常罕見的 ,我們也應該避免這種情況的發生。
現在你已經擁有了一個 ConnectionMultiplexer , 下面三件事情可能是你想要做的。
1. 訪問數據庫。(註意在使用集群的情況下,一個數據庫可能會分部在多個節點中)
2. 使用redis的發布訂閱功能
3. 維護和監控一臺服務器
訪問數據庫
訪問數據庫的操作非常簡單:
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官網。
StackExchange.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;
建議並非是你配置該選項的理由, 是否適合完全取決與你訂閱消息的代碼。
StackExchange.Redis 使用-同步 異步 即發即棄
訪問單個服務器
有時候需要為單個服務器指定特定的命令 。
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);
StackExchange.Redis 使用-配置
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
StackExchange.Redis 使用 - 事件
ConnectionMultiplexer 可以註冊如下事件
- ConfigurationChanged - 配置更改時
- ConfigurationChangedBroadcast - 通過發布訂閱更新配置時
- ConnectionFailed - 連接失敗 , 如果重新連接成功你將不會收到這個通知
- ConnectionRestored - 重新建立連接之前的錯誤
- ErrorMessage - 發生錯誤
- HashSlotMoved - 更改集群
- InternalError - redis類庫錯誤
stackExchange.redis的使用