Redis 分布式session
这里有三种和方式实现:
1.Harbour.RedisSessionStateStore , ServiceStack.Redis
配置web.config
<sessionState mode="Custom" customProvider="RedisSessionStateProvider"> <providers> <clear /> <add name="RedisSessionStateProvider" type="Harbour.RedisSessionStateStore.RedisSessionStateStoreProvider" host="localhost:6379" clientType="pooled" /> </providers> </sessionState>
2.StackExchange.Redis RedisSessionStateProvider
配置文件web.config
<sessionState mode="Custom" customProvider="MySessionStateStore"> <providers> <add name="MySessionStateStore" type="Microsoft.Web.Redis.RedisSessionStateProvider" host="127.0.0.1" port="6379" accessKey="" ssl="true" /> </providers> </sessionState>
3.自定义SessionStateStateProvider
借鉴网上的例子,需要做修改:
public class RedisSessionStateStore : SessionStateStoreProviderBase { /// <summary> /// 创建新的Session执行 /// </summary> public override SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout) { return CreateLegitStoreData(context, null, null, timeout); } internal static SessionStateStoreData CreateLegitStoreData(HttpContext context, ISessionStateItemCollection sessionItems, HttpStaticObjectsCollection staticObjects, int timeout) { if (sessionItems == null) sessionItems = new SessionStateItemCollection(); if (staticObjects == null && context != null) staticObjects = SessionStateUtility.GetSessionStaticObjects(context); return new SessionStateStoreData(sessionItems, staticObjects, timeout); } public override void CreateUninitializedItem(HttpContext context, string id, int timeout) { RedisSessionState state = new RedisSessionState(null, null, timeout); RedisBase.Item_Set<string>(id, state.ToJson(), timeout); } private SessionStateStoreData DoGet(HttpContext context, string id, bool exclusive, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags) { locked = false; lockId = null; lockAge = TimeSpan.Zero; actionFlags = SessionStateActions.None; RedisSessionState state = RedisSessionState.FromJson(RedisBase.Item_Get<string>(id)); if (state == null) { return null; } RedisBase.Item_SetExpire(id, state._timeout); return CreateLegitStoreData(context, state._sessionItems, state._staticObjects, state._timeout); } /// <summary> /// 取值的时候执行 /// </summary> public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags) { return this.DoGet(context, id, false, out locked, out lockAge, out lockId, out actionFlags); } public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags) { return this.DoGet(context, id, true, out locked, out lockAge, out lockId, out actionFlags); } /// <summary> /// 新增 修改 移除键值时执行 /// </summary> /// <param name="item">item.Items为当前所有的键值对</param> public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem) { ISessionStateItemCollection sessionItems = null; HttpStaticObjectsCollection staticObjects = null; if (item.Items.Count > 0) sessionItems = item.Items; if (!item.StaticObjects.NeverAccessed) staticObjects = item.StaticObjects; RedisSessionState state2 = new RedisSessionState(sessionItems, staticObjects, item.Timeout); RedisBase.Item_Set<string>(id, state2.ToJson(), item.Timeout); } #region "未实现方法" public override void Dispose() { } public override void EndRequest(HttpContext context) { } public override void InitializeRequest(HttpContext context) { } public override void ReleaseItemExclusive(HttpContext context, string id, object lockId) { } public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item) { RedisBase.Item_Remove(id); } public override void ResetItemTimeout(HttpContext context, string id) { } public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback) { return true; } #endregion } internal sealed class SessionStateItem { public Dictionary<string, object> Dict; public int Timeout; } internal sealed class RedisSessionState { internal ISessionStateItemCollection _sessionItems; internal HttpStaticObjectsCollection _staticObjects; internal int _timeout; internal RedisSessionState(ISessionStateItemCollection sessionItems, HttpStaticObjectsCollection staticObjects, int timeout) { this.Copy(sessionItems, staticObjects, timeout); } internal void Copy(ISessionStateItemCollection sessionItems, HttpStaticObjectsCollection staticObjects, int timeout) { this._sessionItems = sessionItems; this._staticObjects = staticObjects; this._timeout = timeout; } public string ToJson() { // 这里忽略_staticObjects这个成员。 if (_sessionItems == null || _sessionItems.Count == 0) { return null; } Dictionary<string, object> dict = new Dictionary<string, object>(_sessionItems.Count); string key; NameObjectCollectionBase.KeysCollection keys = _sessionItems.Keys; for (int i = 0; i < keys.Count; i++) { key = keys[i]; dict.Add(key, _sessionItems[key]); } SessionStateItem item = new SessionStateItem { Dict = dict, Timeout = this._timeout }; return JsonConvert.SerializeObject(item); } public static RedisSessionState FromJson(string json) { if (string.IsNullOrEmpty(json)) { return null; } try { SessionStateItem item = JsonConvert.DeserializeObject<SessionStateItem>(json); SessionStateItemCollection collections = new SessionStateItemCollection(); foreach (KeyValuePair<string, object> kvp in item.Dict) { collections[kvp.Key] = kvp.Value; } return new RedisSessionState(collections, null, item.Timeout); } catch { return null; } } }
<sessionState mode="Custom" customProvider="RedisSessionStateProvider"> <providers> <clear /> <add name="RedisSessionStateProvider" type="Harbour.RedisSessionStateStore.RedisSessionStateStoreProvider" host="localhost:6379" clientType="pooled" /> </providers> </sessionState>
之前建了一个mvc的项目测试,但是创建了Action 没有创建对应的视图,一直不能再redis中增加值,以为自己配置错了,但是还是我想的太简单了,当返回一个view才完成一次请求,这样才能知道session的改变,才能做出相应的改变。注意下。