Maison >base de données >Redis >Comment utiliser Redis pour implémenter la fonction de session
Présentons brièvement redis.
Redis (Remote Dictionary Server), le service de dictionnaire distant, est une base de données de valeurs-clés de type journal open source écrite en langage ANSI C, prend en charge le réseau, peut être basée sur la mémoire et persistante, et fournit plusieurs API de langage. Depuis le 15 mars 2010, le développement de Redis est hébergé par VMware. Depuis mai 2013, le développement de Redis est sponsorisé par Pivotal.
1. Comparaison avec d'autres solutions de sauvegarde de l'état utilisateur
Généralement en développement, l'état utilisateur utilise une session ou un cookie, les deux méthodes ont des avantages et des inconvénients différents.
Session : Il est facile de perdre en mode InProc et de provoquer des problèmes de concurrence. Si vous utilisez SQLServer ou le mode SQLServer et consommez des performances
Les cookies peuvent facilement exposer certaines informations utilisateur, et le cryptage et le déchiffrement consomment également des performances.
Redis utilise cette solution pour résoudre plusieurs problèmes,
1 Redis a une vitesse d'accès rapide.
2. Les données utilisateur ne sont pas facilement perdues.
3. Il est facile de prendre en charge des clusters lorsqu'il y a de nombreux utilisateurs.
4. Capable de visualiser les utilisateurs en ligne.
5. Capable de permettre aux utilisateurs de se connecter à un seul endroit. (Réalisé grâce au code, introduit plus tard)
6. Prise en charge de la persistance. (Bien sûr, cela peut être inutile)
2. Idées d'implémentation
1. Nous savons que la session enregistre en fait un identifiant de session dans un cookie. L'utilisateur envoie l'identifiant de session au serveur à chaque fois qu'il visite. , et le serveur transmet l'ID recherche les données d'état correspondant à l'utilisateur.
Mon approche ici consiste à définir un identifiant de session dans le cookie Lorsque le programme a besoin d'obtenir le statut d'utilisateur, l'identifiant de session sera utilisé comme clé de recherche dans Redis.
2. En même temps, la session aide les utilisateurs à recycler la session s'ils n'y accèdent pas pendant un certain temps.
Emprunter la fonctionnalité de Keys in Redis qui prend en charge le délai d'expiration pour prendre en charge cette fonction, mais en termes de renouvellement, le programme doit intercepter la demande et appeler cette méthode par lui-même (la démo a des exemples)
Démarrez la description du code ci-dessous
3.Interface d'appel de Redis
Référencez d'abord la DLL associée à ServiceStack.
Ajouter une configuration dans web.config Cette configuration est utilisée pour définir l'adresse d'appel Redis pour chaque service séparée par [,]. L'hôte est écrit en premier
<appSettings> <!--每台Redis之间用,分割.第一个必须为主机--> <add key="SessionRedis" value="127.0.0.1:6384,127.0.0.1:6384"/> </appSettings>
Configuration initiale
static Managers() { string sessionRedis= ConfigurationManager.AppSettings["SessionRedis"]; string timeOut = ConfigurationManager.AppSettings["SessionRedisTimeOut"]; if (string.IsNullOrEmpty(sessionRedis)) { throw new Exception("web.config 缺少配置SessionRedis,每台Redis之间用,分割.第一个必须为主机"); } 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,//“写”链接池链接数 MaxReadPoolSize = writeReadCount,//“读”链接池链接数 AutoStart = true }); }
Un délégué est écrit à des fins de contrôle
/// <summary> /// 写入 /// </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写入异常.Host:" + client.Host + ",Port:" + client.Port); } finally { if (client != null) { client.Dispose(); } } }
Pour un exemple d'appel, veuillez consulter le code source de autres détails
/// <summary> /// 以Key/Value的形式存储对象到缓存中 /// </summary> /// <typeparam name="T">对象类别</typeparam> /// <param name="value">要写入的集合</param> public void KSet(Dictionary<string, T> value) { Func<IRedisClient, bool> fun = (IRedisClient client) => { client.SetAll<T>(value); return true; }; TryRedisWrite(fun); }
4. Implémenter la session
Écrivez un identifiant de session dans le cookie comme mentionné ci-dessus
/// <summary> /// 用户状态管理 /// </summary> public class Session { /// <summary> /// 初始化 /// </summary> /// <param name="_context"></param> public Session(HttpContextBase _context) { var context = _context; var cookie = context.Request.Cookies.Get(SessionName); if (cookie == null || string.IsNullOrEmpty(cookie.Value)) { SessionId = NewGuid(); context.Response.Cookies.Add(new HttpCookie(SessionName, SessionId)); context.Request.Cookies.Add(new HttpCookie(SessionName, SessionId)); } else { SessionId = cookie.Value; } } }
Comment accéder à l'utilisateur
/// <summary> /// 获取当前用户信息 /// </summary> /// <typeparam name="T"></typeparam> /// <returns></returns> public object Get<T>() where T:class,new() { return new RedisClient<T>().KGet(SessionId); } /// <summary> /// 用户是否在线 /// </summary> /// <returns></returns> public bool IsLogin() { return new RedisClient<object>().KIsExist(SessionId); } /// <summary> /// 登录 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="obj"></param> public void Login<T>(T obj) where T : class,new() { new RedisClient<T>().KSet(SessionId, obj, new TimeSpan(0, Managers.TimeOut, 0)); }
6.
Par défaut, l'utilisateur est déconnecté après une absence de visite pendant plus de 30 minutes, donc à chaque visite de l'utilisateur, le temps de déconnexion de l'utilisateur doit être reporté de 30 minutes
Cela nécessite d'appeler le Méthode de renouvellement Redis
/// <summary> /// 延期 /// </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); }
Après encapsulation
/// <summary> /// 续期 /// </summary> public void Postpone() { new RedisClient<object>().KSetEntryIn(SessionId, new TimeSpan(0, Managers.TimeOut, 0)); }
Ici, j'ai utilisé l'ActionFilter dans MVC3 pour intercepter toutes les demandes des utilisateurs
namespace Test { public class SessionFilterAttribute : ActionFilterAttribute { /// <summary> /// 每次请求都续期 /// </summary> /// <param name="filterContext"></param> public override void OnActionExecuting(ActionExecutingContext filterContext) { new Session(filterContext.HttpContext).Postpone(); } } }
Enregistrez-le dans Global.asax
public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new SessionFilterAttribute()); } protected void Application_Start() { RegisterGlobalFilters(GlobalFilters.Filters); }
5. Méthode d'appel
Afin de faciliter l'appel et l'emprunt des nouvelles fonctionnalités de la version 4.0, ajoutez un attribut étendu à la méthode d'appel du contrôleur
public static class ExtSessions {public static Session SessionExt(this Controller controller) { return new Session(controller.HttpContext); } }
:
public class HomeController : Controller { public ActionResult Index() { this.SessionExt().IsLogin(); return View(); } }
6. Téléchargement du code
7. Suivi
SessionManager comprend l'obtention du nombre de listes d'utilisateurs, se déconnecter d'un utilisateur et obtenir des informations utilisateur basées sur l'ID utilisateur, la liste d'objets utilisateur en ligne, la liste SessionId de l'utilisateur en ligne et d'autres méthodes
La fonction de connexion utilisateur sera implémentée en un seul endroit à l'avenir
Recommandations associées : Tutoriel sur la base de données Redis
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!