服務(wù)熱線
153 8323 9821
隨著網(wǎng)站訪問量的增加,在線用戶實體信息的存儲方式變得重要起來。存儲在線用戶的信息一般有這三種方案:
1、用戶的實體信息保存在Session里,簡單方便,隨著Session的過期用戶信息自動過期。
2、用戶信息保存在數(shù)據(jù)庫中,用一個表存儲在線的用戶信息。
3、用戶信息保存在內(nèi)存。
當前項目用的是第一種方法,把用戶的實體信息保存在Session中,雖然使用方便,但總感覺很別扭。Discuz!NT使用的是第二種方法,把在線用戶標識保存在一個表中,從cookie跟讀取用戶的ID,并從用戶信息表查詢該用戶的信息,組裝到實體中。如果有大量的用戶在線同時操作時,這也不是一個很好的解決辦法。
這里選擇第三種解決方案,把用戶信息保存到內(nèi)存。
我們使用Dictionary來存儲用戶信息,由于Dictionary不是線程安全的,因此需要注意只能單線程更新字典。
先定義一個保存用戶信息的實體:
internal class UserEntity<T> { /// <summary> /// 用戶信息 /// </summary> internal T UserInfo { get; set; } /// <summary> /// 添加到列表的時間戳 /// </summary> internal DateTime Timestamp { get; set; } }
使用泛型包裝用戶實體,并增加一個時間戳,表示該用戶信息添加到內(nèi)存的時間,過期是根據(jù)這個時間來判斷的。
再增加一個在線用戶信息管理類:
/// <summary> /// 在線用戶緩存管理 /// </summary> /// <typeparam name="T"></typeparam> public class UserCacheManager<T> { #region 靜態(tài)屬性 /// <summary> /// 靜態(tài)用戶緩存表 /// </summary> private static Dictionary<long, UserEntity<T>> _UserList = new Dictionary<long, UserEntity<T>>(); /// <summary> /// 過期時間 /// </summary> private static int _ExpiredMinutes = 30; /// <summary> /// 定時器 /// </summary> private static Timer _Timer = null; #endregion #region 靜態(tài)構(gòu)造函數(shù) /// <summary> /// 靜態(tài)構(gòu)造函數(shù) /// 初始化計時器 /// </summary> static UserCacheManager() { _Timer = new Timer(new TimerCallback(TimerClear), null, 60000, _ExpiredMinutes × 60000); } #endregion #region 私有方法 /// <summary> /// 清除在線用戶 /// </summary> /// <param name="sender"></param> private static void TimerClear(object sender) { ThreadPool.QueueUserWorkItem(new WaitCallback(AsyncClear)); } /// <summary> /// 異步清除過期的在線用戶 /// </summary> /// <param name="sender"></param> private static void AsyncClear(object sender) { //當前時間 DateTime timestamp = DateTime.Now.AddMinutes(0 - _ExpiredMinutes); //過期的用戶列表 var expiredUserList = (from userEntity in _UserList where userEntity.Value.Timestamp <= timestamp Select userEntity); if (expiredUserList != null && expiredUserList.Count() > 0) { List<long> expiredUserIdentities = expiredUserList.Select(o => o.Key).ToList(); lock (_UserList) { foreach (long userId in expiredUserIdentities) _UserList.Remove(userId); } } } #endregion #region 公共方法 /// <summary> /// 增加在線用戶 /// </summary> /// <param name="userIdentity">用戶身份標識</param> /// <param name="userInfo">用戶實體</param> public static void Add(long userIdentity, T userInfo) { lock (_UserList) { #region 創(chuàng)建用戶實體 UserEntity<T> userEntity = new UserEntity<T> { Timestamp = DateTime.Now, UserInfo = userInfo }; #endregion if (_UserList.Keys.Contains(userIdentity)) { _UserList[userIdentity] = userEntity; } else { _UserList.Add(userIdentity, userEntity); } } } /// <summary> ///