StackExchange.Redis 免費、支持異步、用的最多
常用對象
源碼地址:https://github.com/StackExchange/StackExchange.Redis 用vs2017打開
ConnectionMultiplexer
中文意思 連接復用器
注釋:Represents an inter-related group of connections to redis servers 表示一群相互關聯的redis服務,就相當於一個對redis數據庫操作的類。
使用注意事項:ConnectionMultiplexer實例是線程安全的,被設計為共享重用,也就是設計為單例(創建一個這種實例是很昂貴的,沒有池化)。這里有個和 ServiceStack.Redis 大的區別是沒有默認的連接池管理了。沒有連接池自然有其利弊,最大的好處在於等待獲取連接的等待時間沒有了,也不會因為連接池里面的連接由於沒有正確釋放等原因導致無限等待而處於死鎖狀態。缺點在於一些低質量的代碼可能導致服務器資源耗盡。不過提供連接池等阻塞和等待的手段是和作者的設計理念相違背的。StackExchange.Redis這里使用管道和多路復用的技術來實現減少連接
方法:
Connect

// // 摘要: // Create a new ConnectionMultiplexer instance public static ConnectionMultiplexer Connect(string configuration, TextWriter log = null); // // 摘要: // Create a new ConnectionMultiplexer instance public static ConnectionMultiplexer Connect(ConfigurationOptions configuration, TextWriter log = null);
創建一個ConnectionMultiplexer實例,
Configure
根據現有配置重新配置當前連接。
Close
關閉所有連接並釋放與此對象關聯的所有資源
Dispose
釋放對象相關聯的所有資源。
GetCounters
獲取與此服務器相關的匯總統計信息。
GetDatabase
在redis中獲得與數據庫的一個數據庫。默認為-1 (ConfigurationOptions可以指定默認數據庫)。0表示第一個數據庫,1表示第二個數據庫。
源碼中如下
GetEndPoints
獲取所有的rendis實例服務。
GetServer
GetServer方法會接收一個EndPoint類或者一個唯一標識一台服務器的鍵值對
有時候需要為單個服務器指定特定的命令
使用IServer可以使用所有的shell命令,比如:
DateTime lastSave = server.LastSave();
ClientInfo[] clients = server.ClientList();
如果報錯在連接字符串后加 ,allowAdmin=true;
GetSubscriber
訂閱一個頻道。
ISubscriber sub = ConnectionMultiplexer.GetSubscriber();
sub.Subscribe()
sub.Publish()
屬性:

// // 摘要: // Provides a way of overriding the default Task Factory. If not set, it will use // the default Task.Factory. Useful when top level code sets it's own factory which // may interfere with Redis queries. public static TaskFactory Factory { get; set; } // // 摘要: // Gets the client-name that will be used on all new connections public string ClientName { get; } // // 摘要: // Gets the configuration of the connection public string Configuration { get; } // // 摘要: // Should exceptions include identifiable details? (key names, additional .Data // annotations) public bool IncludeDetailInExceptions { get; set; } // // 摘要: // Should exceptions include performance counter details? (CPU usage, etc - note // that this can be problematic on some platforms) public bool IncludePerformanceCountersInExceptions { get; set; } // // 摘要: // Indicates whether any servers are connected public bool IsConnected { get; } // // 摘要: // The number of operations that have been performed on all connections public long OperationCount { get; } // // 摘要: // Gets or sets whether asynchronous operations should be invoked in a way that // guarantees their original delivery order public bool PreserveAsyncOrder { get; set; } // // 摘要: // Limit at which to start recording unusual busy patterns (only one log will be // retained at a time; set to a negative value to disable this feature) public int StormLogThreshold { get; set; } // // 摘要: // Gets the timeout associated with the connections public int TimeoutMilliseconds { get; }
ClientName
連接服務器的客戶端名字。
Configuration
連接配置字符串, 也就是ConnectionMultiplexer.Connect(config)這個字符串參數。
IncludeDetailInExceptions
異常是否應該包括可識別的細節?(關鍵的名字,額外的數據注釋)
IncludePerformanceCountersInExceptions
是否應該包括性能計數器細節?(CPU使用率,等等——注意這在某些平台上可能會有問題)
IsConnected
是否已經連接數據庫。
OperationCount
在所有連接上執行的操作數。
PreserveAsyncOrder
獲取或設置是否應該以保證其原始交付順序的方式調用異步操作。
TimeoutMilliseconds
連接超時時間。
事件:

// // 摘要: // Raised when configuration changes are detected public event EventHandler<EndPointEventArgs> ConfigurationChanged; // // 摘要: // Raised when nodes are explicitly requested to reconfigure via broadcast; this // usually means master/slave changes public event EventHandler<EndPointEventArgs> ConfigurationChangedBroadcast; // // 摘要: // Raised whenever a physical connection fails public event EventHandler<ConnectionFailedEventArgs> ConnectionFailed; // // 摘要: // Raised whenever a physical connection is established public event EventHandler<ConnectionFailedEventArgs> ConnectionRestored; // // 摘要: // A server replied with an error message; public event EventHandler<RedisErrorEventArgs> ErrorMessage; // // 摘要: // Raised when a hash-slot has been relocated public event EventHandler<HashSlotMovedEventArgs> HashSlotMoved; // // 摘要: // Raised whenever an internal error occurs (this is primarily for debugging) public event EventHandler<InternalErrorEventArgs> InternalError;
ConfigurationChanged
配置修改時執行。
ConfigurationChangedBroadcast
廣播,主從更改是執行。
ConnectionFailed
連接失敗是執行。
ConnectionRestored
連接建立時執行。
ErrorMessage
服務器發生錯誤是執行
HashSlotMoved
哈希槽重新分配是執行。 集群的時候
InternalError
出現內部錯誤時執行,主要用於調試。
http://www.cnblogs.com/liqingwen/p/6672452.html
ConfigurationOptions
配置選項。創建實例的時候配置參數。

ConfigurationOptions config = new ConfigurationOptions() { //是一個列表,一個復雜的的場景中可能包含有主從復制 , 對於這種情況,只需要指定所有地址在連接字符串中 //(它將會自動識別出主服務器)假設這里找到了兩台主服務器,將會對兩台服務進行裁決選出一台作為主服務器 //來解決這個問題 , 這種情況是非常罕見的 ,我們也應該避免這種情況的發生。 EndPoints = { { "127.0.0.1", 11111 }, { "127.0.0.1", 12111 } } }; //服務器秘密 config.Password = "123456"; //客戶端名字 config.ClientName = "127.0.0.1"; //服務器名字 config.ServiceName = "127.0.0.1"; //true表示管理員身份,可以用一些危險的指令。 config.AllowAdmin = true; //獲取或設置是否應該通過TimeoutException顯式通知連接 / 配置超時。 config.AbortOnConnectFail = true; //你可以禁用或者重命名一個命令。 配置文件里面也可以配置, 對於敏感的命令做處理(比如說清空整個庫 config這種命令)。 config.CommandMap = null; //每n秒檢查配置(默認情況下每分鍾) config.ConfigCheckSeconds = 60; //如果沒有服務器及時響應,重復初始連接周期的次數。 config.ConnectRetry = 1; //超時時間 指定應該允許連接的毫秒數(默認為5秒,除非SyncTimeout更高) config.ConnectTimeout = 5; //默認0到-1 指定要使用的默認數據庫當調用ConnectionMultiplexer.GetDatabase()沒有任何參數 //config.DefaultDatabase = 1; //版本號 config.DefaultVersion = new Version(2, 8, 8); //使用ThreadPriority。對於SocketManager閱讀器和寫入器線程(默認情況下是正確的)來說,這是正常的。如果錯誤,ThreadPriority。將使用正常。 //config.HighPrioritySocketThreads = true; //保存x秒的活動連接 config.KeepAlive = 180; //代理 枚舉類型 http://blog.csdn.net/u010601183/article/details/54426289 config.Proxy = Proxy.Twemproxy;
Connect方法有兩個重載。
ConnectionMultiplexer.Connect(config);
ConnectionMultiplexer.Connect(config.ToString());
tostring方法覆寫了。
https://www.cnblogs.com/soundcode/p/6214287.html
redis主從讀寫分離落地
搭建Redis主從哨兵
地址:http://www.cnblogs.com/wudequn/p/8109798.html 在網頁中搜索 redis哨兵配置下載 然后下載配置文件。
安裝說明配置好redis服務。
運行代碼測試

//准備過程 //1 http://www.cnblogs.com/wudequn/p/8109798.html 頁面中有下載主從哨兵配置文件(頁面搜索文字 redis哨兵配置下載 ) 並搭redis主從 哨兵。 //2 運行代碼測試 public static IConnectionMultiplexer RedisConnect; public static IDatabase DefaultDB; public static ISubscriber sentinelsub; private static ConnectionMultiplexer _sentinel; /// <summary> /// 創建redis連接 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button1_Click(object sender, EventArgs e) { ConfigurationOptions config = new ConfigurationOptions() { //是一個列表,一個復雜的的場景中可能包含有主從復制 , 對於這種情況,只需要指定所有地址在連接字符串中 //(它將會自動識別出主服務器 set值得時候用的主服務器)假設這里找到了兩台主服務器,將會對兩台服務進行裁決選出一台作為主服務器 //來解決這個問題 , 這種情況是非常罕見的 ,我們也應該避免這種情況的發生。 // EndPoints = { { "127.0.0.1", 11111 }, { "127.0.0.1", 12111 }, { "127.0.0.1", 13111 } } }; //服務器秘密 config.Password = "123456"; //客戶端名字 config.ClientName = "127.0.0.1"; //服務器名字 config.ServiceName = "127.0.0.1"; //true表示管理員身份,可以用一些危險的指令。 config.AllowAdmin = true; RedisConnect = ConnectionMultiplexer.Connect(config); DefaultDB = RedisConnect.GetDatabase(); Console.WriteLine("---------------------------Redis主從連接實例創建---------------------------"); Console.WriteLine(RedisConnect.GetStatus()); Console.WriteLine("---------------------------------------------------------------------------"); } /// <summary> /// 監控哨兵主從切換 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button2_Click(object sender, EventArgs e) { ConfigurationOptions sentineloption = new ConfigurationOptions(); sentineloption.TieBreaker = "";//sentinel模式一定要寫 //三個哨兵 sentineloption.EndPoints.Add("127.0.0.1", 11121); sentineloption.EndPoints.Add("127.0.0.1", 11131); sentineloption.EndPoints.Add("127.0.0.1", 11141); //哨兵連接模式 sentineloption.CommandMap = CommandMap.Sentinel; sentineloption.ServiceName = "mymaster"; //我們可以成功的連接一個sentinel服務器,對這個連接的實際意義在於:當一個主從進行切換后,如果它外層有Twemproxy代理,我們可以在這個時機(+switch-master事件)通 Twemproxy代理服務器,並更新它的配置文件里的master服務器的地址,然后從起你的Twemproxy服務,這樣你的主從切換才算真正完成。 //一般沒有代理服務器,直接更改從數據庫配置文件,將其升級為主數據庫。 _sentinel = ConnectionMultiplexer.Connect(sentineloption); sentinelsub = _sentinel.GetSubscriber(); sentinelsub.Subscribe("+switch-master", (ch, mg) => { Console.WriteLine((string)mg); }); } /// <summary> /// 讀寫測試 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button3_Click(object sender, EventArgs e) { //讀寫數據 string key = "WYX"; string value = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"); //默認寫入主庫。 DefaultDB.StringSet(key, value); Console.WriteLine($"寫入成功Key{key}:Value{value}"); Thread.Sleep(2000); //CommandFlags.PreferSlave參數表示讀取從庫數據 貌似是隨機你從不同的slave中讀取的。 //關注問題:https://github.com/StackExchange/StackExchange.Redis/issues/593 //關注問題:https://github.com/StackExchange/StackExchange.Redis/issues/547 var getvalue = DefaultDB.StringGet(key,CommandFlags.PreferSlave); Console.WriteLine($"寫入讀取Key{key}:Value{getvalue}"); } private void button4_Click(object sender, EventArgs e) { Console.WriteLine("這樣redis就落地了,讀寫分離。"); }
字典
一般為頁面下拉選項類型的,但是一般為一層的,但是也有樹狀多層的。
可以存儲在string類型中,json格式存入。
類、類列表
存在hash中。key就是主鍵。
頁面Module
代碼中建立一個頁面的額數據模型,把對應的頁面數據json存放在string類型中,key就是頁面的url表示。
緩存與數據庫交互模式
1、讀取數據
2、添加修改刪除數據
優點:這個流程的主要目的是把Redis當作數據庫使用,更新獲取數據比DB快。非常適合大數據量的頻繁變動(比如微博)。
缺點:對Redis的依賴很大,要做好宕機時的數據保存。(不過可以使用redis的快照AOF,快速恢復的話,應該不會有多大影響(即使是AOf也可能有1秒左右的數據缺失),因為就算Redis不工作了,也不會影響后續數據的處理。)
難點:在前期規划key的格式,存儲類型很重要,因為這會影響能否把數據同步到DB。