Maison  >  Article  >  base de données  >  Redis remplace-t-il la session ?

Redis remplace-t-il la session ?

anonymity
anonymityoriginal
2019-06-05 13:40:433260parcourir

Qu'est-ce que Redis

Redis 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 API en plusieurs langues.

Redis remplace-t-il la session ?

1. Comparaison avec d'autres solutions de sauvegarde de l'état des utilisateurs

Généralement en développement, le statut de l'utilisateur utilise la session ou Cookies, les deux méthodes présentent divers avantages et inconvénients.

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.

6. Soutenez la persistance.

2. Idées d'implémentation

1 Nous savons que la session enregistre en fait un identifiant de session dans un cookie et que l'utilisateur envoie l'identifiant de session au serveur à chaque fois. Lorsqu'il visite, le serveur recherche les données d'état correspondant à l'utilisateur via l'ID.

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

L'emprunt de la fonctionnalité de délai d'expiration de Keys in Redis prend 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 un exemple)

Ci-dessous la description du code de démarrage

3. Interface d'appel Redis

Référencez d'abord la DLL lié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 d'initialisation

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

Écrit un délégué pour faciliter le 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();
                }
            }
        }

Un exemple d'appel d'autres Voir le code source pour plus de 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;
            }
        }
    }

Méthodes d'accès aux utilisateurs

        /// <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. Renouvellement

L'utilisateur par défaut n'a pas été déconnecté depuis plus de 30 minutes. Statut de connexion, l'utilisateur doit donc reporter le temps de déconnexion de l'utilisateur de 30 minutes à chaque visite

Cela nécessite d'appeler la 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 l'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 requêtes 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, empruntez. les nouvelles fonctionnalités de la fonctionnalité 4.0, ajoutez un attribut étendu

public static class ExtSessions
{public static Session SessionExt(this Controller controller)
    {
        return new Session(controller.HttpContext);
    }
}

au Controller pour appeler la méthode

    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            this.SessionExt().IsLogin();
            return View();
        }
    }

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn