自己封装的内存缓存类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 }

 

posted @ 2013-04-19 21:39  支点  阅读(2213)  评论(5编辑  收藏  举报