天天看點

Redis學習筆記~Redis主從伺服器,讀寫分離

回到目錄

Redis這個Nosql的存儲系統一般會被部署到linux系統中,我們可以把它當成是一個資料伺服器,對于并發理大時,我們會使用多台伺服器充當Redis伺服器,這時,各個Redis之間也是分布式的,而Redis與WWW之間也是一種分布式,對于各個redis之間的分布式不需要我們去幹預,它是由我們的redis用戶端去負責連結的,你當時鍊到哪台伺服器,完全由用戶端去控制,redis這種模式我們通常稱為“主從模式”,即一個主伺服器,主要負責寫入資料,多台從伺服器,負責資料的讀取,而它們之前的資料同步,也是redis自已為我們實作的,我們不需要去幹預它,這種模式通常會稱為“多級伺服器叢集架構”,它大大改善了程式的性能!

下面我們分别開啟主redis和從redis,如圖

對于配置從伺服器,我們主要設定port,bind和slaveof這三個參數就可以了,port是端口,bind是從伺服器的ip位址,slaveof是主伺服器的位址和端口,代碼如下

port 6380
bind 127.0.0.1
slaveof  127.0.0.1 6379       

執行個體:在主伺服器寫入一個字元串,在從伺服器讀取字元串

首先對redisConfig進行相關配置,我加了一些說明

/// <summary>
    /// redis主要資訊的配置參數
    /// </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連結位址,一般為一個伺服器,我們稱為主伺服器
        /// </summary>
        [ConfigurationProperty("WriteServerList", IsRequired = false)]
        public string WriteServerList
        {
            get
            {
                return (string)base["WriteServerList"]; 
            }
            set
            {
                base["WriteServerList"] = value;
            }
        }

        
        /// <summary>
        /// 負責讀的Redis連結位址,它一般由多個伺服器元件,一般稱為從伺服器(slave),各個伺服器之間用逗号分開
        /// </summary>
        [ConfigurationProperty("ReadServerList", IsRequired = false)]
        public string ReadServerList
        {
            get
            {
                return (string)base["ReadServerList"]; 
            }
            set
            {
                base["ReadServerList"] = value;
            }
        }

        
        /// <summary>
        /// 最大寫連結數
        /// </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>
        /// 最大讀連結數
        /// </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>
        /// 自動重新開機
        /// </summary>
        [ConfigurationProperty("AutoStart", IsRequired = false, DefaultValue = true)]
        public bool AutoStart
        {
            get
            {
                return (bool)base["AutoStart"];
            }
            set
            {
                base["AutoStart"] = value;
            }
        }


        
        /// <summary>
        /// 本地緩存到期時間(逾時時間),機關:秒
        /// </summary>
        [ConfigurationProperty("LocalCacheTime", IsRequired = false, DefaultValue = 36000)]
        public int LocalCacheTime
        {
            get
            {
                return (int)base["LocalCacheTime"];
            }
            set
            {
                base["LocalCacheTime"] = value;
            }
        }

       
        /// <summary>
        /// 是否記錄日志,該設定僅用于排查redis運作時出現的問題,如redis工作正常,請關閉該項
        /// </summary>
        [ConfigurationProperty("RecordeLog", IsRequired = false, DefaultValue = false)]
        public bool RecordeLog
        {
            get
            {
                return (bool)base["RecordeLog"];
            }
            set
            {
                base["RecordeLog"] = value;
            }
        }        

    }      

而配置檔案中,我們可以把redis讀伺服器和寫伺服器進行配置,多個伺服器使用逗号分開(redis本身就是支援讀寫分離的)

<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>      

下面我們向主伺服器加個對象

using (var test = redisClient.GetTypedClient<string>())
                        {
                            test.Lists["Test"].Add("資訊被添加");

                        }
                     

當沒有調用save方法時,對象隻存儲在記憶體中,資料不會被同步到從伺服器,而調用了save方法後,資料才會被同步到各個從伺服器中。

下面我們添加了這個save方法之後,在從伺服器上就會有資訊同步了

      using (var redisClient = RedisManager.GetClient())
            {
                using (var test = redisClient.GetTypedClient<string>())
                {

                    test.Lists["bobo"].Add("info");
                    test.Save();
                }
            }      

如圖所示

 

對于裝有防火牆的伺服器來說,當然要把對應的端口開放一下,否則用戶端也是不能連結上的,呵呵

設定好之事,我們可以在指令行上測試一下從伺服器的資料,如圖

在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>");
                    });

                }
            }      

分别進行重新整理之後的結果如圖

最後:一處寫入,多處讀取,它會從我們的所有伺服器上去讀取,這樣大大改善了程式的相應能力,分布式将在未來對于企業來說,将會是重中之重!

作者:倉儲大叔,張占嶺,

榮譽:微軟MVP

QQ:853066980

支付寶掃一掃,為大叔打賞!

Redis學習筆記~Redis主從伺服器,讀寫分離