共計 4965 個字符,預計需要花費 13 分鐘才能閱讀完成。
自動寫代碼機器人,免費開通
這篇文章主要介紹怎么使用 redis 實現 session 功能,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!
我們來簡單介紹下 redis。
Redis(Remote Dictionary Server ),即遠程字典服務,是一個開源的使用 ANSI C 語言編寫、支持網絡、可基于內存亦可持久化的日志型、Key-Value 數據庫,并提供多種語言的 API。從 2010 年 3 月 15 日起,Redis 的開發工作由 VMware 主持。從 2013 年 5 月開始,Redis 的開發由 Pivotal 贊助。
1. 與其他用戶狀態保存方案比較
一般開發中用戶狀態使用 session 或者 cookie,兩種方式各種利弊。
Session: 在 InProc 模式下容易丟失,并且引起并發問題。如果使用 SQLServer 或者 SQLServer 模式又消耗了性能
Cookie 則容易將一些用戶信息暴露,加解密同樣也消耗了性能。
Redis 采用這樣的方案解決了幾個問題,
1.Redis 存取速度快。
2. 用戶數據不容易丟失。
3. 用戶多的情況下容易支持集群。
4. 能夠查看在線用戶。
5. 能夠實現用戶一處登錄。(通過代碼實現,后續介紹)
6. 支持持久化。(當然可能沒什么用)
2. 實現思路
1. 我們知道 session 其實是在 cookie 中保存了一個 sessionid,用戶每次訪問都將 sessionid 發給服務器,服務器通過 ID 查找用戶對應的狀態數據。
在這里我的處理方式也是在 cookie 中定義一個 sessionid,程序需要取得用戶狀態時將 sessionid 做為 key 在 Redis 中查找。
2. 同時 session 支持用戶在一定時間不訪問將 session 回收。
借用 Redis 中 Keys 支持過期時間的特性支持這個功能,但是在續期方面需要程序自行攔截請求調用這個方法(demo 有例子)
下面開始代碼說明
3.Redis 調用接口
首先引用 ServiceStack 相關 DLL。
在 web.config 添加配置,這個配置用來設置 Redis 調用地址每臺服務用【,】隔開。主機寫在第一位
appSettings
!-- 每臺 Redis 之間用, 分割. 第一個必須為主機 --
add key= SessionRedis value= 127.0.0.1:6384,127.0.0.1:6384 /
/appSettings
初始化配置
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
});
}
為了控制方面寫了一個委托
/// 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();
}
}
}
一個調用的例子其他的具體看源碼
/// 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. 實現 Session
按上面說的給 cookie 寫一個 sessionid
/// 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;
}
}
}
去存取用戶的方法
/// 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. 續期
默認用戶沒訪問超過 30 分鐘注銷用戶的登錄狀態,所以用戶每次訪問都要將用戶的注銷時間推遲 30 分鐘
這需要調用 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);
}
封裝以后
/// summary
/// 續期
/// /summary
public void Postpone()
new RedisClient object ().KSetEntryIn(SessionId, new TimeSpan(0, Managers.TimeOut, 0));
}
這里我利用了 MVC3 中的 ActionFilter,攔截用戶的所有請求
namespace Test
public class SessionFilterAttribute : ActionFilterAttribute
{
/// summary
/// 每次請求都續期
/// /summary
/// param name= filterContext /param
public override void OnActionExecuting(ActionExecutingContext filterContext)
{ new Session(filterContext.HttpContext).Postpone();
}
}
}
在 Global.asax 中要注冊一下
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{ filters.Add(new SessionFilterAttribute());
}
protected void Application_Start()
{ RegisterGlobalFilters(GlobalFilters.Filters);
}
5. 調用方式
為了方便調用借用 4.0 中的新特性,把 Controller 添加一個擴展屬性
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();
}
}
以上是“怎么使用 redis 實現 session 功能”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注丸趣 TV 行業資訊頻道!
向 AI 問一下細節