0. What is Redis
Redis is an open source API that is written in ANSI C, supports the network, can be persisted in memory, key-value databases, and provides multiple languages.
---wikipedia
1. Comparison with other user state save scenarios
General development of user status using session or cookie, two ways various pros and cons.
Session: Easy to lose in InProc mode and cause concurrency problems. If you use SQL Server or SQL Server mode and consume performance
Cookies are easy to expose some user information, and decryption also consumes performance.
Redis uses such a solution to solve a few problems,
1.Redis access speed is fast.
2. User data cannot be easily lost.
3. The user can easily support the cluster in many cases.
4. Ability to view online users.
5. Be able to realize the user log in one place. (through code implementation, follow-up introduction)
6. Support Persistence. (Of course it may be useless)
2. Realization of Ideas
1. We know that the session is actually stored in a cookie SessionID, the user each access will be sessionid to the server, the server through the ID of the user to find the corresponding state data.
My handling here is also to define a SessionID in the cookie, the program needs to get the user state when the SessionID as key to find in Redis.
2. At the same time the session allows users to not access the session during a certain period to recycle.
This feature is supported by the use of the keys in Redis to support expiration, but it is required to invoke this method on the program's own interception request in the renewal phase (Demo has an example)
The following starts the code description
3.Redis Calling Interface
The Servicestack related DLLs are referenced first.
In the Web. config add configuration, this configuration is used to set the Redis invocation address for each service separated by ",". Host written in first place
1 <appsettings>2 3 <!--per Redis, split. The first must be a host-->4 <add key= "Sessionredis" value= " 127.0.0.1:6384,127.0.0.1:6384 "/>5 6 </appSettings>
Initialize configuration
static Managers () {string sessionredis= configurationmanager.appsettings["Sessionredis"]; String timeOut = configurationmanager.appsettings["Sessionredistimeout"]; if (string. IsNullOrEmpty (Sessionredis)) {throw new Exception ("Web. config is missing a configuration Sessionredis, split between each redis." First Must be a host "); } if (string. IsNullOrEmpty (timeout) ==false) {timeout = Convert.ToInt32 (timeout); } var host = Sessionredis.split (char. Parse (",")); var writehost = new string[] {host[0]}; var readhosts = host. Skip (1). ToArray (); Clientmanagers = new Pooledredisclientmanager (Writehost, readhosts, new Redisclientmanagerconfig { Maxwritepoolsize = writereadcount,//"write" link pool link number maxreadpoolsize = writereadcount,//"read" Link Pool link number AutoStart = true}); }
To control the convenience of writing a delegate
<summary>/ /write to //</summary>//<typeparam name= "F" ></typeparam> // /<param name= "Dowrite" ></param>/// <returns></returns> public F tryrediswrite< F> (func<iredisclient, f> dowrite) { Pooledredisclientmanager prcm = new Managers (). Getclientmanagers (); Iredisclient client = null; Try { using (client = PRCM. Getclient ()) { return dowrite (client); } } catch (redisexception) { throw new Exception ("Redis write exception. Host:" + client.) Host + ", Port:" + client. Port); } Finally { if (client! = null) { client. Dispose ();}}}
A call to the example other specific look at the source code
<summary>//// store objects in key/value form to cache///</summary>// <typeparam name= "T" > Object categories </typeparam> //<param name= "Value" > collection to write </param> public void Kset (dictionary< String, t> value) { func<iredisclient, bool> fun = (iredisclient client) = = { client. Setall<t> (value); return true; }; Tryrediswrite (fun); }
4. Implement session
Write a SessionID to the cookie as stated above
<summary>/// User status Management/// </summary> public class Session {// <summary> ///Initialize//</summary>//<param name= "_context" ></param> public Session ( HttpContextBase _context) { var context = _context; var cookie = context. Request.Cookies.Get (sessionname); if (cookie = = NULL | | string. IsNullOrEmpty (cookies. Value) { SessionId = NewGuid (); Context. RESPONSE.COOKIES.ADD (New HttpCookie (SessionName, SessionId)); Context. REQUEST.COOKIES.ADD (New HttpCookie (SessionName, SessionId)); } else { SessionId = cookie. Value;}} }
Ways to access the user
<summary>/// Get current User information///</summary>// <typeparam name= "T" ></typeparam> / //<returns></returns> public Object get<t> () where t:class,new () { return new Redisclient<t> (). Kget (SessionId); } <summary>// whether the user is online//</summary>// <returns></returns> Public BOOL IsLogin () { return new redisclient<object> (). Kisexist (SessionId); } <summary>///Login/// </summary>/ <typeparam name= "T" ></typeparam> / //<param name= "obj" ></param> public void login<t> (T obj) where t:class,new () { C24/>new redisclient<t> (). Kset (SessionId, obj, new TimeSpan (0, managers.timeout, 0)); }
6. Renewal
The default user does not have access to log off users for more than 30 minutes, so the user's logoff time is delayed by 30 minutes per visit
This requires a call to the Redis renewal method
<summary>//extension/// </summary>/ <param name= "key" ></param>/// < param name= "expirestime" ></param> public void Ksetentryin (string key, TimeSpan expirestime) { Func<iredisclient, bool> fun = (iredisclient client) = = { client. Expireentryin (key, expirestime); return false; }; Tryrediswrite (fun); }
After encapsulation
Here I use the actionfilter in MVC3 to intercept all requests from the user.
namespace test{public class Sessionfilterattribute:actionfilterattribute { //<summary>// /renewal per request///</summary>// <param name= "Filtercontext" ></param> public override void OnActionExecuting (ActionExecutingContext filtercontext) { new Session (Filtercontext.httpcontext). Postpone ();}}}
To register in Global.asax
public static void Registerglobalfilters (Globalfiltercollection filters) { filters. ADD (New Sessionfilterattribute ()); } protected void Application_Start () { registerglobalfilters (globalfilters.filters); }
5. Invocation mode
To facilitate the invocation of new features in borrowing 4.0, add a controller to an extended property
public static class Extsessions{public static Session Sessionext (this controller controller) { return new Session (Controller. HttpContext);} }
Calling methods
public class Homecontroller:controller {publicly actionresult Index () {this . Sessionext (). IsLogin (); return View (); } }
6. Code download
Click to download
7. Follow-up
SessionManager includes getting the number of user lists, logging off a user, obtaining user information based on user ID, Online user object list, online user SessionID list, etc.
Follow-up will implement a user login function
Using Redis to implement session functions