• 自己封装的内存缓存类DotNet.Caches.Bytecached


    Bytecached类是DSS.NET(Distributed State Service分布式状态服务)、DFS.NET(Distributed File System分布式文件系统)中的一个核心内存缓存类。

    在DSS.NET中用于保存和管理网站用户的Session数据。

    在DFS.NET中用于缓存使用频率较高的文件数据。

    特性:

    1、使用读写锁实现多线程并发控制

    2、多种过期数据清理方式

    3、精准的容量控制

    4、以最小的系统开销进行数据清理

    在一个对性能要求比较高的系统中,都需要用缓存来保存一临时数据。也许你正在寻找。。。

    View Code
      1 using System;
      2 using System.Collections.Generic;
      3 using System.Collections.ObjectModel;
      4 using System.ComponentModel;
      5 using System.Diagnostics;
      6 using System.Linq;
      7 using System.Threading;
      8 using DotNet.Utilities;
      9 
     10 namespace DotNet.Caches
     11 {
     12     public class Bytecached : IDisposable
     13     {
     14         private readonly IDictionary<string, byte[]> _caches;
     15         private readonly IDictionary<string, DateTime> _times;
     16         private long _size;
     17         private readonly ReaderWriterLock _readerWriterLock;
     18         private readonly BackgroundWorker _checkWorker;
     19 
     20         /// <summary>
     21         /// 最大容量/B
     22         /// </summary>
     23         public long MaxSize { get; set; }
     24 
     25         /// <summary>
     26         /// 是否启用缓存
     27         /// </summary>
     28         public bool Enabled { get; set; }
     29 
     30         /// <summary>
     31         /// 超时时间
     32         /// </summary>
     33         public TimeSpan Timeout { get; set; }
     34 
     35         /// <summary>
     36         /// 一次清理数量
     37         /// </summary>
     38         public int ClearCount { get; set; }
     39 
     40         /// <summary>
     41         /// 是否正在检查并清理超时缓存
     42         /// </summary>
     43         public bool Checking { get; private set; }
     44 
     45         /// <summary>
     46         /// 构造
     47         /// </summary>
     48         /// <param name="timingcheck">定时检查时间</param>
     49         public Bytecached(TimeSpan timingcheck = default(TimeSpan))
     50         {
     51             _caches = new Dictionary<string, byte[]>();
     52             _times = new Dictionary<string, DateTime>();
     53             _readerWriterLock = new ReaderWriterLock();
     54             MaxSize = 64*1024*1024;
     55             Enabled = true;
     56             ClearCount = 1;
     57 
     58             #region 检查并清理缓存
     59 
     60             if (timingcheck == default(TimeSpan))
     61             {
     62                 _checkWorker = new BackgroundWorker();
     63                 _checkWorker.DoWork += CheckWorker_DoWork;
     64             }
     65             else
     66             {
     67                 new Thread(obj =>
     68                 {
     69                     while (true)
     70                     {
     71                         var swt = new Stopwatch();
     72                         swt.Start();
     73                         CheckWorker_DoWork(null, null);
     74                         swt.Stop();
     75                         Thread.Sleep(timingcheck);
     76                     }
     77                 }) { IsBackground = true }.Start();
     78             }
     79 
     80             #endregion
     81         }
     82 
     83         public bool Set(string key, byte[] value)
     84         {
     85             return Set(key, value, DateTime.Now.Add(Timeout));
     86         }
     87 
     88         public bool Set(string key, byte[] value, DateTime effectiveDate)
     89         {
     90             if (!Enabled)
     91                 return false;
     92 
     93             _readerWriterLock.AcquireWriterLock(-1);
     94             try
     95             {
     96                 if (_caches.ContainsKey(key))
     97                 {
     98                     _size -= _caches[key].Length;
     99                     _caches[key] = value;
    100                     _times[key] = effectiveDate;
    101                 }
    102                 else
    103                 {
    104                     _caches.Add(key, value);
    105                     _times.Add(key, effectiveDate);
    106                 }
    107                 _size += value.Length;
    108             }
    109             catch(Exception er)
    110             {
    111                 LogUtil.WriteLog("Bytecached.Set", er);
    112                 return false;
    113             }
    114             finally
    115             {
    116                 _readerWriterLock.ReleaseWriterLock();
    117             }
    118 
    119             #region 检查并清理缓存
    120 
    121             try
    122             {
    123                 if (_checkWorker != null && !_checkWorker.IsBusy)
    124                 {
    125                     _checkWorker.RunWorkerAsync();
    126                 }
    127             }
    128             catch (Exception er)
    129             {
    130                 LogUtil.WriteLog("检查并清理缓存", er);
    131             }
    132 
    133             #endregion
    134 
    135             return true;
    136         }
    137 
    138         public byte[] Get(string key)
    139         {
    140             var expiry = Timeout == TimeSpan.Zero ? default(DateTime) : DateTime.Now.Add(Timeout);
    141             return Get(key, expiry);
    142         }
    143 
    144         public byte[] Get(string key, DateTime effectiveDate)
    145         {
    146             if (!Enabled)
    147                 return null;
    148 
    149             _readerWriterLock.AcquireReaderLock(-1);
    150             var exist = false;
    151             try
    152             {
    153                 byte[] v;
    154                 exist = _caches.TryGetValue(key, out v);
    155                 return v;
    156             }
    157             catch(Exception er)
    158             {
    159                 LogUtil.WriteLog("Bytecached.Get", er);
    160                 return null;
    161             }
    162             finally
    163             {
    164                 _readerWriterLock.ReleaseReaderLock();
    165                 if (exist && effectiveDate != default(DateTime))
    166                 {
    167                     #region 刷新缓存
    168 
    169                     new Thread(obj =>
    170                     {
    171                         var k = (string)((object[])obj)[0];
    172                         var edate = (DateTime)((object[])obj)[1];
    173                         while (!Refresh(k, edate))
    174                         {
    175                             Thread.Sleep(100);
    176                         }
    177                     }) { IsBackground = true }.Start(new object[]{key, effectiveDate});
    178 
    179                     #endregion
    180                 }
    181             }
    182         }
    183 
    184         public bool ContainsKey(string key)
    185         {
    186             if (!Enabled)
    187                 return false;
    188 
    189             _readerWriterLock.AcquireReaderLock(-1);
    190             try
    191             {
    192                 return _caches.ContainsKey(key);
    193             }
    194             catch(Exception er)
    195             {
    196                 LogUtil.WriteLog("Bytecached.ContainsKey", er);
    197                 return false;
    198             }
    199             finally
    200             {
    201                 _readerWriterLock.ReleaseReaderLock();
    202             }
    203         }
    204 
    205         public bool Refresh(string key)
    206         {
    207             return Timeout != TimeSpan.Zero && Refresh(key, DateTime.Now.Add(Timeout));
    208         }
    209 
    210         public bool Refresh(string key, DateTime effectiveDate)
    211         {
    212             _readerWriterLock.AcquireWriterLock(-1);
    213             try
    214             {
    215                 if (_caches.ContainsKey(key))
    216                 {
    217                     _times[key] = effectiveDate;
    218                 }
    219             }
    220             catch(Exception er)
    221             {
    222                 LogUtil.WriteLog("Bytecached.Refresh", er);
    223                 return false;
    224             }
    225             finally
    226             {
    227                 _readerWriterLock.ReleaseWriterLock();
    228             }
    229             return true;
    230         }
    231 
    232         public IList<string> Keys
    233         {
    234             get
    235             {
    236                 _readerWriterLock.AcquireReaderLock(-1);
    237                 try
    238                 {
    239                     return _caches.Keys.ToList();
    240                 }
    241                 catch (Exception er)
    242                 {
    243                     LogUtil.WriteLog("Bytecached.Keys", er);
    244                     return new List<string>();
    245                 }
    246                 finally
    247                 {
    248                     _readerWriterLock.ReleaseReaderLock();
    249                 }
    250             }
    251         }
    252 
    253         public ICollection<byte[]> Values
    254         {
    255             get
    256             {
    257                 _readerWriterLock.AcquireReaderLock(-1);
    258                 try
    259                 {
    260                     return _caches.Values;
    261                 }
    262                 catch (Exception er)
    263                 {
    264                     LogUtil.WriteLog("Bytecached.Keys", er);
    265                     return new List<byte[]>();
    266                 }
    267                 finally
    268                 {
    269                     _readerWriterLock.ReleaseReaderLock();
    270                 }
    271             }
    272         }
    273 
    274         public ICollection<DateTime> Times
    275         {
    276             get
    277             {
    278                 _readerWriterLock.AcquireReaderLock(-1);
    279                 try
    280                 {
    281                     return _times.Values;
    282                 }
    283                 catch (Exception er)
    284                 {
    285                     LogUtil.WriteLog("Bytecached.Times", er);
    286                     return new Collection<DateTime>();
    287                 }
    288                 finally
    289                 {
    290                     _readerWriterLock.ReleaseReaderLock();
    291                 }
    292             }
    293         }
    294 
    295         /// <summary>
    296         /// 移除指定数据
    297         /// </summary>
    298         /// <param name="key"></param>
    299         /// <returns></returns>
    300         public bool Remove(string key)
    301         {
    302             _readerWriterLock.AcquireWriterLock(-1);
    303             try
    304             {
    305                 if (_caches.ContainsKey(key))
    306                 {
    307                     _size -= _caches[key].Length;
    308                     _caches.Remove(key);
    309                     _times.Remove(key);
    310                 }
    311             }
    312             catch(Exception er)
    313             {
    314                 LogUtil.WriteLog("Bytecached.Remove_key", er);
    315                 return false;
    316             }
    317             finally
    318             {
    319                 _readerWriterLock.ReleaseWriterLock();
    320             }
    321             return true;
    322         }
    323 
    324         public void Clear()
    325         {
    326             _readerWriterLock.AcquireWriterLock(-1);
    327             try
    328             {
    329                 _size = 0;
    330                 _caches.Clear();
    331                 _times.Clear();
    332             }
    333             catch(Exception er)
    334             {
    335                 LogUtil.WriteLog("Bytecached.Clear", er);
    336             }
    337             finally
    338             {
    339                 _readerWriterLock.ReleaseWriterLock();
    340             }
    341         }
    342 
    343         private void CheckWorker_DoWork(object sender, DoWorkEventArgs e)
    344         {
    345             Checking = true;
    346             try
    347             {
    348                 bool clearSize;
    349                 bool collect;
    350                 IEnumerable<string> clearKeys;
    351                 var count = 0;
    352                 var swt = new Stopwatch();
    353                 var t = new Stopwatch();
    354 
    355                 #region 清理超时记录
    356 
    357                 _readerWriterLock.AcquireReaderLock(-1);
    358                 swt.Start();
    359                 try
    360                 {
    361                     clearKeys = from time in _times where time.Value <= DateTime.Now orderby time.Value select time.Key;
    362                 }
    363                 finally
    364                 {
    365                     _readerWriterLock.ReleaseReaderLock();
    366                     swt.Stop();
    367                 }
    368                 Thread.Sleep(10);
    369                 _readerWriterLock.AcquireWriterLock(-1);
    370                 t.Start();
    371                 swt.Reset();
    372                 swt.Start();
    373                 try
    374                 {
    375                     foreach (var clearKey in clearKeys)
    376                     {
    377                         if (t.ElapsedMilliseconds > 20)
    378                         {
    379                             _readerWriterLock.ReleaseWriterLock();
    380                             Thread.Sleep(10);
    381                             _readerWriterLock.AcquireWriterLock(-1);
    382                             t.Reset();
    383                         }
    384                         if (_caches.ContainsKey(clearKey))
    385                         {
    386                             _size -= _caches[clearKey].Length;
    387                             _caches.Remove(clearKey);
    388                             _times.Remove(clearKey);
    389                         }
    390                         count++;
    391                     }
    392                 }
    393                 finally
    394                 {
    395                     clearSize = _size >= MaxSize;
    396                     collect = count > 0 || clearSize;
    397                     _readerWriterLock.ReleaseWriterLock();
    398                     t.Stop();
    399                     swt.Stop();
    400                 }
    401 
    402                 #endregion
    403 
    404                 if (clearSize)
    405                 {
    406                     #region 清理超量记录
    407 
    408                     Thread.Sleep(10);
    409                     _readerWriterLock.AcquireReaderLock(-1);
    410                     swt.Reset();
    411                     swt.Start();
    412                     try
    413                     {
    414                         clearKeys = from time in _times orderby time.Value select time.Key;
    415                     }
    416                     finally
    417                     {
    418                         _readerWriterLock.ReleaseReaderLock();
    419                         swt.Stop();
    420                     }
    421                     Thread.Sleep(10);
    422                     _readerWriterLock.AcquireWriterLock(-1);
    423                     t.Reset();
    424                     t.Start();
    425                     swt.Reset();
    426                     swt.Start();
    427                     count = 0;
    428                     try
    429                     {
    430                         var i = 0;
    431                         foreach (var clearKey in clearKeys)
    432                         {
    433                             if (i == ClearCount - 1)
    434                                 i = 0;
    435                             if (i == 0 && _size < MaxSize)
    436                                 break;
    437                             if (t.ElapsedMilliseconds > 20)
    438                             {
    439                                 _readerWriterLock.ReleaseWriterLock();
    440                                 Thread.Sleep(10);
    441                                 _readerWriterLock.AcquireWriterLock(-1);
    442                                 t.Reset();
    443                             }
    444                             if (_caches.ContainsKey(clearKey))
    445                             {
    446                                 _size -= _caches[clearKey].Length;
    447                                 _caches.Remove(clearKey);
    448                                 _times.Remove(clearKey);
    449                             }
    450                             i++;
    451                             count++;
    452                         }
    453                     }
    454                     finally
    455                     {
    456                         _readerWriterLock.ReleaseWriterLock();
    457                         t.Stop();
    458                         swt.Stop();
    459                     }
    460 
    461                     #endregion
    462                 }
    463 
    464                 if (collect)
    465                 {
    466                     ThreadPool.QueueUserWorkItem(obj => GC.Collect());
    467                 }
    468             }
    469             finally
    470             {
    471                 Checking = false;
    472             }
    473         }
    474 
    475         public int Count
    476         {
    477             get
    478             {
    479                 _readerWriterLock.AcquireReaderLock(-1);
    480                 try
    481                 {
    482                     return _caches.Count;
    483                 }
    484                 catch(Exception er)
    485                 {
    486                     LogUtil.WriteLog("Bytecached.Count", er);
    487                     return 0;
    488                 }
    489                 finally
    490                 {
    491                     _readerWriterLock.ReleaseReaderLock();
    492                 }
    493             }
    494         }
    495 
    496         public long Size
    497         {
    498             get
    499             {
    500                 _readerWriterLock.AcquireReaderLock(-1);
    501                 try
    502                 {
    503                     return _size;
    504                 }
    505                 catch (Exception er)
    506                 {
    507                     LogUtil.WriteLog("Bytecached.Size", er);
    508                     return 0;
    509                 }
    510                 finally
    511                 {
    512                     _readerWriterLock.ReleaseReaderLock();
    513                 }
    514             }
    515         }
    516 
    517         public object[][] List
    518         {
    519             get
    520             {
    521                 _readerWriterLock.AcquireReaderLock(-1);
    522                 try
    523                 {
    524                     return _caches.Select(obj => new object[] { obj.Key, obj.Value.Length, _times[obj.Key] }).ToArray();
    525                 }
    526                 catch (Exception er)
    527                 {
    528                     LogUtil.WriteLog("Bytecached.List", er);
    529                     return new object[3][];
    530                 }
    531                 finally
    532                 {
    533                     _readerWriterLock.ReleaseReaderLock();
    534                 }
    535             }
    536         }
    537 
    538         public void Dispose()
    539         {
    540             Clear();
    541         }
    542     }
    543 }
  • 相关阅读:
    JVM内存模型
    生产者与消费者的Java实现
    kafka常用命令
    java中join用法
    elasticsearch关于索引切分的实现
    三十六进制加法
    leetCode之Median of Two Sorted Arrays
    腾讯云“动态加速”与“CDN”的区别——浅谈对“动态加速”的理解(可能有误)
    洗澡或游泳等导致的耳朵进水的解决方案
    windows服务器间文件同步搭建步骤搜集
  • 原文地址:https://www.cnblogs.com/zhidian/p/3031441.html
Copyright © 2020-2023  润新知