成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

分布式中使用Redis實(shí)現(xiàn)Session共享

數(shù)據(jù)庫(kù) 其他數(shù)據(jù)庫(kù) 分布式 Redis
session和cookie是我們做web開(kāi)發(fā)中常用到的兩個(gè)對(duì)象,它們之間會(huì)不會(huì)有聯(lián)系呢?

  Session實(shí)現(xiàn)原理

  session和cookie是我們做web開(kāi)發(fā)中常用到的兩個(gè)對(duì)象,它們之間會(huì)不會(huì)有聯(lián)系呢?

  Cookie是什么? Cookie 是一小段文本信息,伴隨著用戶(hù)請(qǐng)求和頁(yè)面在 Web 服務(wù)器和瀏覽器之間傳遞。Cookie 包含每次用戶(hù)訪問(wèn)站點(diǎn)時(shí) Web 應(yīng)用程序都可以讀取的信息。(Cookie 會(huì)隨每次HTTP請(qǐng)求一起被傳遞服務(wù)器端,排除js,css,image等靜態(tài)文件,這個(gè)過(guò)程可以從fiddler或者ie自帶的網(wǎng)絡(luò)監(jiān)控里面分析到,考慮性能的化可以從盡量減少cookie著手)

  Cookie寫(xiě)入瀏覽器的過(guò)程:我們可以使用如下代碼在Asp.net項(xiàng)目中寫(xiě)一個(gè)Cookie 并發(fā)送到客戶(hù)端的瀏覽器(為了簡(jiǎn)單我沒(méi)有設(shè)置其它屬性)。

  1. HttpCookie cookie = new HttpCookie("RedisSessionId", "string value");Response.Cookies.Add(cookie); 

  

 

  我們可以看到在服務(wù)器寫(xiě)的cookie,會(huì)通過(guò)響應(yīng)頭Set-Cookie的方式寫(xiě)入到瀏覽器。

  Session是什么? Session我們可以使用它來(lái)方便地在服務(wù)端保存一些與會(huì)話相關(guān)的信息。比如常見(jiàn)的登錄信息。

  Session實(shí)現(xiàn)原理? HTTP協(xié)議是無(wú)狀態(tài)的,對(duì)于一個(gè)瀏覽器發(fā)出的多次請(qǐng)求,WEB服務(wù)器無(wú)法區(qū)分 是不是來(lái)源于同一個(gè)瀏覽器。所以服務(wù)器為了區(qū)分這個(gè)過(guò)程會(huì)通過(guò)一個(gè)sessionid來(lái)區(qū)分請(qǐng)求,而這個(gè)sessionid是怎么發(fā)送給服務(wù)端的呢?前面說(shuō)了cookie會(huì)隨每次請(qǐng)求發(fā)送到服務(wù)端,并且cookie相對(duì)用戶(hù)是不可見(jiàn)的,用來(lái)保存這個(gè)sessionid是最好不過(guò)了,我們通過(guò)下面過(guò)程來(lái)驗(yàn)證一下。

  1. Session["UserId"] = 123; 

 

  通過(guò)上圖再次驗(yàn)證了session和cookie的關(guān)系,服務(wù)器產(chǎn)生了一次設(shè)置cookie的操作,這里的sessionid就是用來(lái)區(qū)分瀏覽器的。為了實(shí)驗(yàn)是區(qū)分瀏覽器的,可以實(shí)驗(yàn)在IE下進(jìn)行登錄,然后在用chrome打開(kāi)相同頁(yè)面,你會(huì)發(fā)現(xiàn)在chrome還是需要你登錄的,原因是chrome這時(shí)沒(méi)有sessionid。httpOnly是表示這個(gè)cookie是不會(huì)在瀏覽器端通過(guò)js進(jìn)行操作的,防止人為串改sessionid。

  asp.net默認(rèn)的sessionid的鍵值是ASP.NET_SessionId,可以在web.config里面修改這個(gè)默認(rèn)配置

  

  1. <sessionState mode="InProc" cookieName="MySessionId"></sessionState> 

  服務(wù)器端Session讀取? 服務(wù)器端是怎么讀取session的值呢 ,Session["鍵值"]。那么問(wèn)題來(lái)了,為什么在Defaule.aspx.cs文件里可以獲取到這個(gè)Session對(duì)象,這個(gè)Session對(duì)象又是什么時(shí)候被初始化的呢。

  為了弄清楚這個(gè)問(wèn)題,我們可以通過(guò)轉(zhuǎn)到定義的方式來(lái)查看。

  System.Web.UI.Page ->HttpSessionState(Session)

  1. protected internal override HttpContext Context { 
  2. [System.Runtime.TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] 
  3.   get { 
  4.        if (_context == null) { 
  5.            _context = HttpContext.Current; 
  6.        } 
  7.        return _context; 
  8.     } 
  9.  } 
  10.  public virtual HttpSessionState Session { 
  11.         get { 
  12.             if (!_sessionRetrieved) { 
  13.                 /* try just once to retrieve it */ 
  14.                 _sessionRetrieved = true; 
  15.  
  16.                 try { 
  17.                     _session = Context.Session; 
  18.                 } 
  19.                 catch { 
  20.                     //  Just ignore exceptions, return null. 
  21.                 } 
  22.             } 
  23.  
  24.             if (_session == null) { 
  25.                 throw new HttpException(SR.GetString(SR.Session_not_enabled)); 
  26.             } 
  27.  
  28.             return _session; 
  29.         } 
  30.     } 

上面這一段是Page對(duì)象初始化Session對(duì)象的,可以看到Session的值來(lái)源于HttpContext.Current,而HttpContext.Current又是什么時(shí)候被初始化的呢,我們接著往下看。

  1. public sealed class HttpContext : IServiceProvider, IPrincipalContainer 
  2.     { 
  3.  
  4.         internal static readonly Assembly SystemWebAssembly = typeof(HttpContext).Assembly; 
  5.         private static volatile bool s_eurlSet; 
  6.         private static string s_eurl; 
  7.  
  8.         private IHttpAsyncHandler  _asyncAppHandler;   // application as handler (not always HttpApplication) 
  9.         private AsyncPreloadModeFlags _asyncPreloadModeFlags; 
  10.         private bool               _asyncPreloadModeFlagsSet; 
  11.         private HttpApplication    _appInstance; 
  12.         private IHttpHandler       _handler; 
  13.         [DoNotReset] 
  14.         private HttpRequest        _request; 
  15.         private HttpResponse       _response; 
  16.         private HttpServerUtility  _server; 
  17.         private Stack              _traceContextStack; 
  18.         private TraceContext       _topTraceContext; 
  19.         [DoNotReset] 
  20.         private Hashtable          _items; 
  21.         private ArrayList          _errors; 
  22.         private Exception          _tempError; 
  23.         private bool               _errorCleared; 
  24.         [DoNotReset] 
  25.         private IPrincipalContainer _principalContainer; 
  26.         [DoNotReset] 
  27.         internal ProfileBase       _Profile; 
  28.         [DoNotReset] 
  29.         private DateTime           _utcTimestamp; 
  30.         [DoNotReset] 
  31.         private HttpWorkerRequest  _wr; 
  32.         private VirtualPath        _configurationPath; 
  33.         internal bool              _skipAuthorization; 
  34.         [DoNotReset] 
  35.         private CultureInfo        _dynamicCulture; 
  36.         [DoNotReset] 
  37.         private CultureInfo        _dynamicUICulture; 
  38.         private int                _serverExecuteDepth; 
  39.         private Stack              _handlerStack; 
  40.         private bool               _preventPostback; 
  41.         private bool               _runtimeErrorReported; 
  42.         private PageInstrumentationService _pageInstrumentationService = null; 
  43.         private ReadOnlyCollection<string> _webSocketRequestedProtocols; 
  44. } 

  我這里只貼出了一部分源碼,HttpContext包含了我們常用的Request,Response等對(duì)象。HttpContext得從ASP.NET管道說(shuō)起,以IIS 6.0為例,在工作進(jìn)程w3wp.exe中,利用Aspnet_ispai.dll加載.NET運(yùn)行時(shí)(如果.NET運(yùn)行時(shí)尚未加載)。IIS 6.0引入了應(yīng)用程序池的概念,一個(gè)工作進(jìn)程對(duì)應(yīng)著一個(gè)應(yīng)用程序池。一個(gè)應(yīng)用程序池可以承載一個(gè)或多個(gè)Web應(yīng)用,每個(gè)Web應(yīng)用映射到一個(gè)IIS虛擬目錄。與IIS 5.x一樣,每一個(gè)Web應(yīng)用運(yùn)行在各自的應(yīng)用程序域中。如果HTTP.SYS接收到的HTTP請(qǐng)求是對(duì)該Web應(yīng)用的第一次訪問(wèn),在成功加載了運(yùn)行時(shí)后,會(huì)通過(guò)AppDomainFactory為該Web應(yīng)用創(chuàng)建一個(gè)應(yīng)用程序域(AppDomain)。隨后,一個(gè)特殊的運(yùn)行時(shí)IsapiRuntime被加載。IsapiRuntime定義在程序集System.Web中,對(duì)應(yīng)的命名空間為System.Web.Hosting。IsapiRuntime會(huì)接管該HTTP請(qǐng)求。IsapiRuntime會(huì)首先創(chuàng)建一個(gè)IsapiWorkerRequest對(duì)象,用于封裝當(dāng)前的HTTP請(qǐng)求,并將該IsapiWorkerRequest對(duì)象傳遞給ASP.NET運(yùn)行時(shí):HttpRuntime,從此時(shí)起,HTTP請(qǐng)求正式進(jìn)入了ASP.NET管道。根據(jù)IsapiWorkerRequest對(duì)象,HttpRuntime會(huì)創(chuàng)建用于表示當(dāng)前HTTP請(qǐng)求的上下文(Context)對(duì)象:HttpContext。
     至此相信大家對(duì)Session初始化過(guò)程,session和cookie的關(guān)系已經(jīng)很了解了吧,下面開(kāi)始進(jìn)行Session共享實(shí)現(xiàn)方案。 

  Session共享實(shí)現(xiàn)方案

  一.StateServer方式

 

  這種是asp.net提供的一種方式,還有一種是SQLServer方式(不一定程序使用的是SQLServer數(shù)據(jù)庫(kù),所以通用性不高,這里就不介紹了)。也就是將會(huì)話數(shù)據(jù)存儲(chǔ)到單獨(dú)的內(nèi)存緩沖區(qū)中,再由單獨(dú)一臺(tái)機(jī)器上運(yùn)行的Windows服務(wù)來(lái)控制這個(gè)緩沖區(qū)。狀態(tài)服務(wù)全稱(chēng)是“ASP.NET State Service ”(aspnet_state.exe)。它由Web.config文件中的stateConnectionString屬性來(lái)配置。該屬性指定了服務(wù)所在的服務(wù)器,以及要監(jiān)視的端口。

  1. <sessionState mode="StateServer"      stateConnectionString="tcpip=127.0.0.1:42424"     cookieless="false" timeout="20" /> 

  在這個(gè)例子中,狀態(tài)服務(wù)在當(dāng)前機(jī)器的42424端口(默認(rèn)端口)運(yùn)行。要在服務(wù)器上改變端口和開(kāi)啟遠(yuǎn)程服務(wù)器的該功能,可編輯HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\aspnet_state\Parameters注冊(cè)表項(xiàng)中的Port值和AllowRemoteConnection修改成1。 顯然,使用狀態(tài)服務(wù)的優(yōu)點(diǎn)在于進(jìn)程隔離,并可在多站點(diǎn)中共享。 使用這種模式,會(huì)話狀態(tài)的存儲(chǔ)將不依賴(lài)于iis進(jìn)程的失敗或者重啟,然而,一旦狀態(tài)服務(wù)中止,所有會(huì)話數(shù)據(jù)都會(huì)丟失(這個(gè)問(wèn)題redis不會(huì)存在,重新了數(shù)據(jù)不會(huì)丟失)。

  這里提供一段bat文件幫助修改注冊(cè)表,可以復(fù)制保存為.bat文件執(zhí)行

  1. reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\aspnet_state\Parameters" /v "AllowRemoteConnection" /t REG_DWORD  /d 1 /f 
  2.  
  3. reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\aspnet_state\Parameters" /v "Port" /t REG_DWORD  /d 42424 /f 
  4.  
  5. net stop aspnet_state 
  6. net start aspnet_state 
  7.  
  8. pause 

二.redis實(shí)現(xiàn)session共享

   下面我們將使用redis來(lái)實(shí)現(xiàn)共享,首先要弄清楚session的幾個(gè)關(guān)鍵點(diǎn),過(guò)期時(shí)間,SessionId,一個(gè)SessionId里面會(huì)存在多組key/value數(shù)據(jù)。基于這個(gè)特性我將采用Hash結(jié)構(gòu)來(lái)存儲(chǔ),看看代碼實(shí)現(xiàn)。用到了上一篇提供的RedisBase幫助類(lèi)。

  1. using System; 
  2. using System.Collections.Generic; 
  3. using System.Linq; 
  4. using System.Web; 
  5. using System.Web.SessionState; 
  6. using ServiceStack.Redis; 
  7. using Com.Redis; 
  8.  
  9. namespace ResidSessionDemo.RedisDemo 
  10.     public class RedisSession 
  11.     { 
  12.         private HttpContext context; 
  13.  
  14.         public RedisSession(HttpContext context, bool IsReadOnly, int Timeout) 
  15.         { 
  16.             this.context = context; 
  17.             this.IsReadOnly = IsReadOnly; 
  18.             this.Timeout = Timeout; 
  19.             //更新緩存過(guò)期時(shí)間 
  20.             RedisBase.Hash_SetExpire(SessionID, DateTime.Now.AddMinutes(Timeout)); 
  21.         } 
  22.  
  23.         /// <summary> 
  24.         /// SessionId標(biāo)識(shí)符 
  25.         /// </summary> 
  26.         public static string SessionName = "Redis_SessionId"; 
  27.  
  28.         // 
  29.         // 摘要: 
  30.         //     獲取會(huì)話狀態(tài)集合中的項(xiàng)數(shù)。 
  31.         // 
  32.         // 返回結(jié)果: 
  33.         //     集合中的項(xiàng)數(shù)。 
  34.         public int Count 
  35.         { 
  36.             get 
  37.             { 
  38.                 return RedisBase.Hash_GetCount(SessionID); 
  39.             } 
  40.         } 
  41.  
  42.         // 
  43.         // 摘要: 
  44.         //     獲取一個(gè)值,該值指示會(huì)話是否為只讀。 
  45.         // 
  46.         // 返回結(jié)果: 
  47.         //     如果會(huì)話為只讀,則為 true;否則為 false。 
  48.         public bool IsReadOnly { get; set; } 
  49.  
  50.         // 
  51.         // 摘要: 
  52.         //     獲取會(huì)話的唯一標(biāo)識(shí)符。 
  53.         // 
  54.         // 返回結(jié)果: 
  55.         //     唯一會(huì)話標(biāo)識(shí)符。 
  56.         public string SessionID 
  57.         { 
  58.             get 
  59.             { 
  60.                 return GetSessionID(); 
  61.             } 
  62.         } 
  63.  
  64.         // 
  65.         // 摘要: 
  66.         //     獲取并設(shè)置在會(huì)話狀態(tài)提供程序終止會(huì)話之前各請(qǐng)求之間所允許的時(shí)間(以分鐘為單位)。 
  67.         // 
  68.         // 返回結(jié)果: 
  69.         //     超時(shí)期限(以分鐘為單位)。 
  70.         public int Timeout { get; set; } 
  71.  
  72.         /// <summary> 
  73.         /// 獲取SessionID 
  74.         /// </summary> 
  75.         /// <param name="key">SessionId標(biāo)識(shí)符</param> 
  76.         /// <returns>HttpCookie值</returns> 
  77.         private string GetSessionID() 
  78.         { 
  79.             HttpCookie cookie = context.Request.Cookies.Get(SessionName); 
  80.             if (cookie == null || string.IsNullOrEmpty(cookie.Value)) 
  81.             { 
  82.                 string newSessionID = Guid.NewGuid().ToString(); 
  83.                 HttpCookie newCookie = new HttpCookie(SessionName, newSessionID); 
  84.                 newCookie.HttpOnly = IsReadOnly; 
  85.                 newCookie.Expires = DateTime.Now.AddMinutes(Timeout); 
  86.                 context.Response.Cookies.Add(newCookie); 
  87.                 return "Session_"+newSessionID; 
  88.             } 
  89.             else 
  90.             { 
  91.                 return "Session_"+cookie.Value; 
  92.             } 
  93.         } 
  94.  
  95.         // 
  96.         // 摘要: 
  97.         //     按名稱(chēng)獲取或設(shè)置會(huì)話值。 
  98.         // 
  99.         // 參數(shù): 
  100.         //   name: 
  101.         //     會(huì)話值的鍵名。 
  102.         // 
  103.         // 返回結(jié)果: 
  104.         //     具有指定名稱(chēng)的會(huì)話狀態(tài)值;如果該項(xiàng)不存在,則為 null。 
  105.         public object this[string name] 
  106.         { 
  107.             get 
  108.             { 
  109.                 return RedisBase.Hash_Get<object>(SessionID, name); 
  110.             } 
  111.             set 
  112.             { 
  113.                 RedisBase.Hash_Set<object>(SessionID, name, value); 
  114.             } 
  115.         } 
  116.  
  117.         // 摘要: 
  118.         //     判斷會(huì)話中是否存在指定key 
  119.         // 
  120.         // 參數(shù): 
  121.         //   name: 
  122.         //     鍵值 
  123.         // 
  124.         public bool IsExistKey(string name) 
  125.         { 
  126.             return RedisBase.Hash_Exist<object>(SessionID, name); 
  127.         } 
  128.  
  129.         // 
  130.         // 摘要: 
  131.         //     向會(huì)話狀態(tài)集合添加一個(gè)新項(xiàng)。 
  132.         // 
  133.         // 參數(shù): 
  134.         //   name: 
  135.         //     要添加到會(huì)話狀態(tài)集合的項(xiàng)的名稱(chēng)。 
  136.         // 
  137.         //   value: 
  138.         //     要添加到會(huì)話狀態(tài)集合的項(xiàng)的值。 
  139.         public void Add(string name, object value) 
  140.         { 
  141.             RedisBase.Hash_Set<object>(SessionID, name, value); 
  142.         } 
  143.         // 
  144.         // 摘要: 
  145.         //     從會(huì)話狀態(tài)集合中移除所有的鍵和值。 
  146.         public void Clear() 
  147.         { 
  148.             RedisBase.Hash_Remove(SessionID); 
  149.         } 
  150.  
  151.         // 
  152.         // 摘要: 
  153.         //     刪除會(huì)話狀態(tài)集合中的項(xiàng)。 
  154.         // 
  155.         // 參數(shù): 
  156.         //   name: 
  157.         //     要從會(huì)話狀態(tài)集合中刪除的項(xiàng)的名稱(chēng)。 
  158.         public void Remove(string name) 
  159.         { 
  160.             RedisBase.Hash_Remove(SessionID,name); 
  161.         } 
  162.         // 
  163.         // 摘要: 
  164.         //     從會(huì)話狀態(tài)集合中移除所有的鍵和值。 
  165.         public void RemoveAll() 
  166.         { 
  167.             Clear(); 
  168.         } 
  169.     } 

下面是實(shí)現(xiàn)類(lèi)似在cs文件中能直接使用Session["UserId"]的方式,我的MyPage類(lèi)繼承Page實(shí)現(xiàn)了自己的邏輯主要做了兩件事  1:初始化RedisSession  2:實(shí)現(xiàn)統(tǒng)一登錄認(rèn)證,OnPreInit方法里面判斷用戶(hù)是否登錄,如果沒(méi)有登錄了則跳轉(zhuǎn)到登陸界面

  1. using System; 
  2. using System.Collections.Generic; 
  3. using System.Linq; 
  4. using System.Web; 
  5. using System.Web.UI; 
  6.  
  7. namespace ResidSessionDemo.RedisDemo 
  8.     /// <summary> 
  9.     /// 自定義Page 實(shí)現(xiàn)以下功能 
  10.     /// 1.初始化RedisSession 
  11.     /// 2.實(shí)現(xiàn)頁(yè)面登錄驗(yàn)證,繼承此類(lèi),則可以實(shí)現(xiàn)所有頁(yè)面的登錄驗(yàn)證 
  12.     /// </summary> 
  13.     public class MyPage:Page 
  14.     { 
  15.         private RedisSession redisSession; 
  16.  
  17.         /// <summary> 
  18.         /// RedisSession 
  19.         /// </summary> 
  20.         public RedisSession RedisSession 
  21.         { 
  22.             get 
  23.             { 
  24.                 if (redisSession == null) 
  25.                 { 
  26.                     redisSession = new RedisSession(Context, true, 20); 
  27.                 } 
  28.                 return redisSession; 
  29.             } 
  30.         } 
  31.  
  32.         protected override void OnPreInit(EventArgs e) 
  33.         { 
  34.             base.OnPreInit(e); 
  35.             //判斷用戶(hù)是否已經(jīng)登錄,如果未登錄,則跳轉(zhuǎn)到登錄界面 
  36.             if (!RedisSession.IsExistKey("UserCode")) 
  37.             { 
  38.                 Response.Redirect("Login.aspx"); 
  39.             } 
  40.         } 
  41.     } 

 我們來(lái)看看Default.aspx.cs是如何使用RedisSession的,至此我們實(shí)現(xiàn)了和Asp.netSession一模一樣的功能和使用方式。

  1. RedisSession.Remove("UserCode"); 

  相比StateServer,RedisSession具有以下優(yōu)點(diǎn)

  1.redis服務(wù)器重啟不會(huì)丟失數(shù)據(jù) 2.可以使用redis的讀寫(xiě)分離個(gè)集群功能更加高效讀寫(xiě)數(shù)據(jù)

  測(cè)試效果,使用nginx和iis部署兩個(gè)站點(diǎn)做負(fù)載均衡,iis1地址127.0.0.1:8002 iis2地址127.0.0.1:9000 nginx代理服務(wù)地址127.0.0.1:8003,不懂如何配置的可以去閱讀我的nginx+iis實(shí)現(xiàn)負(fù)載均衡這篇文章。我們來(lái)看一下測(cè)試結(jié)果。

  訪問(wèn)127.0.0.1:8003 需要進(jìn)行登錄 用戶(hù)名為admin 密碼為123

  

 

  登錄成功以后,重點(diǎn)關(guān)注端口號(hào)信息

  

 

  刷新頁(yè)面,重點(diǎn)關(guān)注端口號(hào)信息

  

 

  可以嘗試直接訪問(wèn)iis1地址127.0.0.1:8002 iis2地址127.0.0.1:9000 這兩個(gè)站點(diǎn),你會(huì)發(fā)現(xiàn)都不需要登錄了。至此我們的redis實(shí)現(xiàn)session功能算是大功告成了。

  回到頂部

  問(wèn)題拓展

  使用redis實(shí)現(xiàn)session告一段落,下面留個(gè)問(wèn)題討論一下方案。微信開(kāi)發(fā)提供了很多接口,參考下面截圖,可以看到獲取access_token接口每日最多調(diào)用2000次,現(xiàn)在大公司提供的很多接口針對(duì)不對(duì)級(jí)別的用戶(hù)接口訪問(wèn)次數(shù)限制都是不一樣的,至于做這個(gè)限制的原因應(yīng)該是防止惡意攻擊和流量限制之類(lèi)的。那么我的問(wèn)題是怎么實(shí)現(xiàn)這個(gè)接口調(diào)用次數(shù)限制功能。大家可以發(fā)揮想象力參與討論哦,或許你也會(huì)碰到這個(gè)問(wèn)題。

  

 

  先說(shuō)下我知道的兩種方案:

  1.使用流量整形中的令牌桶算法,大小固定的令牌桶可自行以恒定的速率源源不斷地產(chǎn)生令牌。如果令牌不被消耗,或者被消耗的速度小于產(chǎn)生的速度,令牌就會(huì)不斷地增多,直到把桶填滿(mǎn)。后面再產(chǎn)生的令牌就會(huì)從桶中溢出。最后桶中可以保存的最大令牌數(shù)永遠(yuǎn)不會(huì)超過(guò)桶的大小。

  說(shuō)淺顯點(diǎn):比如上面的獲取access_token接口,一天2000次的頻率,即1次/分鐘。我們令牌桶容量為2000,可以使用redis 最簡(jiǎn)單的key/value來(lái)存儲(chǔ) ,key為用戶(hù)id,value為整形存儲(chǔ)還可使用次數(shù),然后使用一個(gè)定時(shí)器1分鐘調(diào)用client.Incr(key) 實(shí)現(xiàn)次數(shù)自增;用戶(hù)每訪問(wèn)一次該接口,相應(yīng)的client.Decr(key)來(lái)減少使用次數(shù)。

  但是這里存在一個(gè)性能問(wèn)題,這僅僅是針對(duì)一個(gè)用戶(hù)來(lái)說(shuō),假設(shè)有10萬(wàn)個(gè)用戶(hù),怎么使用定時(shí)器來(lái)實(shí)現(xiàn)這個(gè)自增操作呢,難道是循環(huán)10萬(wàn)次分別調(diào)用client.Incr(key)嗎?這一點(diǎn)沒(méi)有考慮清楚。

  2.直接用戶(hù)訪問(wèn)一次 先進(jìn)行總次數(shù)判斷,符合條件再就進(jìn)行一次自增

  

      兩種方案優(yōu)缺點(diǎn)比較
  優(yōu)點(diǎn) 缺點(diǎn)
令牌桶算法 流量控制精確  實(shí)現(xiàn)復(fù)雜,并且由于控制精確反而在實(shí)際應(yīng)用中有麻煩,很可能用戶(hù)在晚上到凌晨期間訪問(wèn)接口次數(shù)不多,白天訪問(wèn)次數(shù)多些。
簡(jiǎn)單算法 實(shí)現(xiàn)簡(jiǎn)單可行,效率高  流量控制不精確
 

  總結(jié)

  本篇從實(shí)際應(yīng)用講解了redis,后面應(yīng)該還會(huì)有幾篇繼續(xù)介紹redis實(shí)際應(yīng)用,敬請(qǐng)期待!

  本篇文章用到的資源打包下載地址:redis_demo

 

  svn下載地址:http://code.taobao.org/svn/ResidSessionDemo/

責(zé)任編輯:honglu 來(lái)源: 博客園
相關(guān)推薦

2020-03-20 14:48:46

SpringBootJava分布式

2014-05-08 14:38:26

tornadoredissession

2024-10-07 10:07:31

2024-04-01 05:10:00

Redis數(shù)據(jù)庫(kù)分布式鎖

2023-12-29 08:18:31

Session分布式系統(tǒng)微服務(wù)

2022-01-06 10:58:07

Redis數(shù)據(jù)分布式鎖

2023-08-21 19:10:34

Redis分布式

2019-06-19 15:40:06

分布式鎖RedisJava

2019-07-31 08:44:27

Session共享Memcache

2015-06-17 14:10:34

Redis分布式系統(tǒng)協(xié)調(diào)

2019-02-26 09:51:52

分布式鎖RedisZookeeper

2023-01-13 07:39:07

2021-03-08 09:56:24

存儲(chǔ)分布式Session

2024-06-13 09:34:35

JWTTokenSpring

2020-07-30 09:35:09

Redis分布式鎖數(shù)據(jù)庫(kù)

2020-07-15 16:50:57

Spring BootRedisJava

2022-06-28 08:37:07

分布式服務(wù)器WebSocket

2024-01-02 13:15:00

分布式鎖RedissonRedis

2023-03-01 08:07:51

2018-11-28 16:00:41

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: av在线播放网址 | 欧美成人一区二区三区 | 国产1页 | 精品一二区 | 五月天综合影院 | 最新av在线播放 | 99热在线观看精品 | 色毛片| 一区二区三区久久久 | 在线免费观看亚洲 | 久久精品亚洲精品 | 日本精品一区二区三区视频 | 中文字幕成人av | 天堂中文字幕av | 久草热线 | 日韩有码一区 | 黄视频网址 | 国产精品成人久久久久 | 91看片在线观看 | 91精品在线播放 | av网站免费观看 | 精品综合久久久 | 狠狠躁躁夜夜躁波多野结依 | 国产精品一二区 | 国产国拍亚洲精品av | 欧美亚洲激情 | 日韩免费 | 日韩欧美国产电影 | 久久精品小视频 | 黑人巨大精品欧美一区二区免费 | 国产黄色在线观看 | 久草精品在线 | 中文字幕加勒比 | 国产激情视频在线 | 国产精品成人一区二区三区夜夜夜 | 日本在线综合 | 亚洲欧美日韩精品久久亚洲区 | 在线观看中文视频 | 欧美日韩中文字幕 | av黄色国产 | 一区二区三区免费 |