使用MemCach加Cookie完美模拟Session

在官网上下载MemCach的dll根据文档配置MemCachHelper

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Memcached.ClientLibrary;

namespace Common
{
    public static class MemcachHelper
    {
        //缓存 全局共享的东东,所有安装了服务的主机就是数据源,他内部有个算法分配到什么数据都不用我们管了。
        private static MemcachedClient mc = null;
        static MemcachHelper()
        {

            string[] serverlist = { "127.0.0.1:11211"};//写到配置文件中。
            //初始化池
            SockIOPool pool = SockIOPool.GetInstance();
            pool.SetServers(serverlist);
            pool.InitConnections = 3;
            pool.MinConnections = 3;
            pool.MaxConnections = 5;

            pool.SocketConnectTimeout = 1000;
            pool.SocketTimeout = 3000;

            pool.MaintenanceSleep = 30;
            pool.Failover = true;

            pool.Nagle = false;
            pool.Initialize();

            // 获得客户端实例
            mc = new MemcachedClient();
            mc.EnableCompression = false;
        }
        /// <summary>
        /// 设置缓存的值
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void Set(string key, object value)
        {
            mc.Set(key, value);
        }

        /// <summary>
        /// 设置缓存的值和日期
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="datetime"></param>
        public static void Set(string key, object value, DateTime datetime)
        {
            mc.Set(key, value, datetime);
        }

        /// <summary>
        /// 获取缓存的值
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static object Get(string key)
        {
            return mc.Get(key);
        }

        /// <summary>
        /// 删除指定的键值对
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static bool Delete(string key)
        {
            //不存在删除失败
            if (!mc.KeyExists(key))
            {
                return false;
            }
            //存在删除
            return mc.Delete(key);
        }
    }
}

这里的数组填写的是子服务器的ip和端口 在缓存服务器上开启了服务,MemCach就会自动根据一个算法选择一个缓存服务器把数据存在其中

好了现在我们开始模拟Session 构造和Session类似的结构如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Memcached.ClientLibrary;
using System.Web;

namespace Common
{
    public class MemSession
    {
        private static MemSession MySession = new MemSession();
        public static MemSession GetSession()
        {
            return MySession;
        }

        public object this[string key]
        {
            set {
                HttpContext context = HttpContext.Current;
                 string id= null;
                 if (context.Request.Cookies["AspNet_SessionId"] != null)
                 {
                     id = context.Request.Cookies["AspNet_SessionId"].Value;
                 }
                 //第一次设置session id代表这次会话
                 else
                 {
                     context.Response.Clear();

                     HttpCookie cookie = new HttpCookie("AspNet_SessionId");
                     id = Guid.NewGuid().ToString().Substring(0, 12);
                     cookie.Value = id;
                     //设置不会出现异常大胆输出
                     context.Response.Cookies.Add(cookie);
                     //设置值,此时所有子服务器 都可以从这台缓存服务器中拿到值
                 }
                MemSessionDic.Set(id,key,value);
            }
            get {
                HttpContext context = HttpContext.Current;
                HttpCookie cookie = context.Request.Cookies["AspNet_SessionId"];
                string value = null;
                if (cookie != null)
                {
                    value = cookie.Value;
                }
                return MemSessionDic.Get(value, key);
            }

            
        }
    }
}

好了核心类出来了。注释已经写的很清楚了我就不多写了 这里要注意的是我使用了饿汉模式这是因为HttpContext.Current.Session 是唯一的 如果不是唯一的请求过来 是不知道找哪个键值对的 MemSessionDic的核心代码如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Common
{
    //在子服务器上处理设置session
    public class MemSessionDic
    {
        public static Dictionary<string, object> dic = new Dictionary<string, object>();
        public static void Set(string id, string key, object value)
        {
            //数据字典必须从缓存服务器中获取!存在缓存器中的字典被序列化了不会丢失,子服务器有sessionid完全可以从缓存服务器中拿到字典
            Dictionary<string,object> dic = MemcachHelper.Get(id) as Dictionary<string,object>;
            //如果是第一次设置
            if (dic == null)
            {
                dic = new Dictionary<string, object>();
                dic.Add(key, value);
            }
            //存在这个字典而且如果字典中存在这个key
            else if (dic.ContainsKey(key))
            {
                //覆盖
                dic[key] = value;
            }
            //存在这个字典而且如果是第一次设置这个key的值
            else
            {
                //添加进去
                dic.Add(key, value);
            }
            //从新存进去 设置过期时间为20分钟如果20分钟过了字典会被清空
            MemcachHelper.Set(id, dic, DateTime.Now.AddMinutes(20));
        
        }
        /// <summary>
        /// 获取session的值
        /// </summary>
        /// <param name="id">sessionid</param>
        /// <param name="key">session键的名称</param>
        /// <returns></returns>
        public static object Get(string id, string key)
        {
            //没有sessionid了等同与浏览器关掉了sessionid是cookie在内存中
            if (id == null)
            {
                return null;
            }
            //有id从缓存服务器中取出数据,或者数据是否过期,还怕有人伪造sessionid
            Dictionary<string, object> dic = MemcachHelper.Get(id) as Dictionary<string, object>;
            if (dic == null)
            {
                return null;
                //throw new Exception("sessionid不正确");
            }
            else
            {
                if (dic.ContainsKey(key))
                {
                    return dic[key];
                }
                 //缓存服务器里是否没有key的数据
                else
                {
                    return null;
                }
            }
        }
        
    }
}


 

如果有不懂的可以为我留言亲测有效。



 

使用MemCach加Cookie完美模拟Session

上一篇:达梦(6)联机备份恢复


下一篇:算法导论13-4:Treap