接一的考虑,那么就做Redis的SessionProvider就非常简单了,只考虑整个Session的缓存,主要实现以下两个函数就可以了
1 public override SessionStateStoreData GetItem(System.Web.HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) 2 { 3 OpenRedis(); 4 var response = _connection.Strings.Get(_dbNumber, id); 5 var value = _connection.Wait(response); 6 var sessionItems = value.FromBinary<SerializableSessionStateItemCollection>(); 7 8 locked = false; 9 lockAge = new TimeSpan(0); 10 lockId = null; 11 actions = SessionStateActions.None; 12 13 SessionStateStoreData storeData = null; 14 if (sessionItems != null) 15 { 16 storeData = new SessionStateStoreData(sessionItems, SessionStateUtility.GetSessionStaticObjects(context), _timeout); 17 } 18 else 19 { 20 storeData = new SessionStateStoreData(new SerializableSessionStateItemCollection(), SessionStateUtility.GetSessionStaticObjects(context), _timeout); 21 } 22 return storeData; 23 } 24 25 public override SessionStateStoreData GetItemExclusive(System.Web.HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions) 26 { 27 return GetItem(context, id, out locked, out lockAge, out lockId, out actions); 28 }
1 public override void SetAndReleaseItemExclusive(System.Web.HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem) 2 { 3 OpenRedis(); 4 var items = item.Items as SerializableSessionStateItemCollection; 5 if (items != null) 6 { 7 var response = _connection.Strings.Set(_dbNumber, id, item.Items.ToBinary(), _timeout*60); 8 _connection.Wait(response); 9 } 10 }
配置Web.Config
<sessionState mode="Custom" customProvider="redis" timeout="20"> <providers> <add name="redis" type=".Web.Session.RedisSessionProvider,Common.Web" server="localhost" port ="6379" dbNumber="2"/> </providers> </sessionState>
调试通过,包括设置和获取Session,Session超时,Session Aband,基本达到要求,美中不足的是,存入Session的对象必须标记可序列化的。
经测试发现,每次Request,都会调用上面的2个函数,用户量大的时候,redis会有点压力