Redis學習筆記(ji)~Redis主從服務(wu)器(qi),讀寫分離(li)
Redis這個Nosql的(de)(de)存儲系統一般會被部(bu)署(shu)到(dao)linux系統中,我(wo)們(men)(men)(men)(men)可以把它(ta)(ta)當成是(shi)一個數據(ju)服(fu)(fu)務(wu)器(qi)(qi)(qi),對(dui)于并發理大(da)(da)時(shi),我(wo)們(men)(men)(men)(men)會使用(yong)多臺服(fu)(fu)務(wu)器(qi)(qi)(qi)充當Redis服(fu)(fu)務(wu)器(qi)(qi)(qi),這時(shi),各個Redis之間(jian)也(ye)是(shi)分布式(shi)(shi)的(de)(de),而(er)Redis與WWW之間(jian)也(ye)是(shi)一種(zhong)分布式(shi)(shi),對(dui)于各個redis之間(jian)的(de)(de)分布式(shi)(shi)不(bu)需(xu)(xu)要(yao)我(wo)們(men)(men)(men)(men)去(qu)干預,它(ta)(ta)是(shi)由(you)我(wo)們(men)(men)(men)(men)的(de)(de)redis客戶(hu)端去(qu)負責鏈接的(de)(de),你當時(shi)鏈到(dao)哪臺服(fu)(fu)務(wu)器(qi)(qi)(qi),完全由(you)客戶(hu)端去(qu)控制,redis這種(zhong)模(mo)式(shi)(shi)我(wo)們(men)(men)(men)(men)通常(chang)稱(cheng)為(wei)“主從模(mo)式(shi)(shi)”,即一個主服(fu)(fu)務(wu)器(qi)(qi)(qi),主要(yao)負責寫入(ru)數據(ju),多臺從服(fu)(fu)務(wu)器(qi)(qi)(qi),負責數據(ju)的(de)(de)讀(du)取,而(er)它(ta)(ta)們(men)(men)(men)(men)之前的(de)(de)數據(ju)同步(bu),也(ye)是(shi)redis自已為(wei)我(wo)們(men)(men)(men)(men)實現的(de)(de),我(wo)們(men)(men)(men)(men)不(bu)需(xu)(xu)要(yao)去(qu)干預它(ta)(ta),這種(zhong)模(mo)式(shi)(shi)通常(chang)會稱(cheng)為(wei)“多級服(fu)(fu)務(wu)器(qi)(qi)(qi)集(ji)群架構”,它(ta)(ta)大(da)(da)大(da)(da)改(gai)善了程序的(de)(de)性能(neng)!
下面(mian)我們分別開(kai)啟主redis和從redis,如圖(tu)
對于(yu)配置(zhi)從(cong)服務(wu)器(qi)(qi),我們主要設(she)置(zhi)port,bind和slaveof這(zhe)三個參數就可以(yi)了,port是(shi)端口,bind是(shi)從(cong)服務(wu)器(qi)(qi)的(de)ip地(di)址,slaveof是(shi)主服務(wu)器(qi)(qi)的(de)地(di)址和端口,代碼如下(xia)
port 6380 bind 127.0.0.1 slaveof 127.0.0.1 6379
實例:在主服務(wu)器寫入一(yi)個(ge)字(zi)符串,在從服務(wu)器讀取字(zi)符串
首(shou)先對redisConfig進行相關(guan)配置,我加了一(yi)些說明(ming)
/// <summary> /// redis主(zhu)要信息的配置參數 /// </summary> public sealed class RedisConfigInfo : ConfigurationSection { public static RedisConfigInfo GetConfig() { RedisConfigInfo section = (RedisConfigInfo)ConfigurationManager.GetSection("RedisConfig"); return section; } public static RedisConfigInfo GetConfig(string sectionName) { RedisConfigInfo section = (RedisConfigInfo)ConfigurationManager.GetSection("RedisConfig"); if (section == null) throw new ConfigurationErrorsException("Section " + sectionName + " is not found."); return section; } /// <summary> /// 負責寫入的Redis鏈接地址,一般(ban)為一個服務器,我們稱為主服務器 /// </summary> [ConfigurationProperty("WriteServerList", IsRequired = false)] public string WriteServerList { get { return (string)base["WriteServerList"]; } set { base["WriteServerList"] = value; } } /// <summary> /// 負(fu)責讀的Redis鏈接地址,它一般由多個服務器(qi)組件,一般稱為(wei)從服務器(qi)(slave),各個服務器(qi)之間用逗(dou)號分開 /// </summary> [ConfigurationProperty("ReadServerList", IsRequired = false)] public string ReadServerList { get { return (string)base["ReadServerList"]; } set { base["ReadServerList"] = value; } } /// <summary> /// 最大寫鏈(lian)接數 /// </summary> [ConfigurationProperty("MaxWritePoolSize", IsRequired = false, DefaultValue = 5)] public int MaxWritePoolSize { get { int _maxWritePoolSize = (int)base["MaxWritePoolSize"]; return _maxWritePoolSize > 0 ? _maxWritePoolSize : 5; } set { base["MaxWritePoolSize"] = value; } } /// <summary> /// 最大(da)讀鏈接數 /// </summary> [ConfigurationProperty("MaxReadPoolSize", IsRequired = false, DefaultValue = 5)] public int MaxReadPoolSize { get { int _maxReadPoolSize = (int)base["MaxReadPoolSize"]; return _maxReadPoolSize > 0 ? _maxReadPoolSize : 5; } set { base["MaxReadPoolSize"] = value; } } /// <summary> /// 自動重啟(qi) /// </summary> [ConfigurationProperty("AutoStart", IsRequired = false, DefaultValue = true)] public bool AutoStart { get { return (bool)base["AutoStart"]; } set { base["AutoStart"] = value; } } /// <summary> /// 本地緩存(cun)到期時(shi)(shi)間(超(chao)時(shi)(shi)時(shi)(shi)間),單位(wei):秒 /// </summary> [ConfigurationProperty("LocalCacheTime", IsRequired = false, DefaultValue = 36000)] public int LocalCacheTime { get { return (int)base["LocalCacheTime"]; } set { base["LocalCacheTime"] = value; } } /// <summary> /// 是否記錄(lu)日志,該設(she)置僅(jin)用于排查redis運行時出現的問題,如redis工作正常,請(qing)關閉該項 /// </summary> [ConfigurationProperty("RecordeLog", IsRequired = false, DefaultValue = false)] public bool RecordeLog { get { return (bool)base["RecordeLog"]; } set { base["RecordeLog"] = value; } } }
而配(pei)置文件中,我們可以把redis讀(du)服(fu)(fu)務器和寫服(fu)(fu)務器進行配(pei)置,多個服(fu)(fu)務器使用逗號分(fen)開(kai)(redis本(ben)身就是(shi)支持讀(du)寫分(fen)離的)
<RedisConfig WriteServerList="192.168.2.71:6379" ReadServerList="192.168.2.71:6379,192.168.2.71:6380" MaxWritePoolSize="60" MaxReadPoolSize="60" AutoStart="true" LocalCacheTime="180" RecordeLog="false"> </RedisConfig>
下面(mian)我(wo)們向主服務器(qi)加(jia)個對象
using (var test = redisClient.GetTypedClient<string>()) { test.Lists["Test"].Add("信(xin)息(xi)被(bei)添加(jia)"); }
當沒有調用save方法時,對象只存儲在內存中,數據不會被同步到從服務器,而調用了save方法后,數據才會被同步到各個從服務器中。
下面我們添加了這(zhe)個save方法之(zhi)后,在從服務(wu)器上(shang)就會(hui)有(you)信息同(tong)步了
using (var redisClient = RedisManager.GetClient()) { using (var test = redisClient.GetTypedClient<string>()) { test.Lists["bobo"].Add("info"); test.Save(); } }
如圖所示
對于(yu)裝有防火墻(qiang)的服務器來說,當然要把對應的端口開放一下,否(fou)則客戶(hu)端也是不能(neng)鏈接上(shang)的,呵呵
設置(zhi)好(hao)之(zhi)事,我們可以在命令行上測試一下從服(fu)務器(qi)的(de)數據,如圖(tu)
在WEB端進行測試
using (var redisClient = RedisManager.GetClient()) { using (var test = redisClient.GetTypedClient<string>()) { test.Lists["bobo"].ToList().ForEach(i => { Response.Write(redisClient.Port + " " + i); Response.Write("<br>"); }); } }
分別(bie)進行刷(shua)新之后的結果如圖
最后:一處寫入,多處讀取,它會(hui)從我(wo)們的所(suo)有(you)服務(wu)器上去(qu)讀取,這(zhe)樣大大改善了程序的相應能(neng)力,分(fen)布(bu)式將在(zai)未(wei)來(lai)對于企業來(lai)說,將會(hui)是(shi)重中之重!