C# 实现 key-value 结构自定义缓存 CustomCache
创始人
2024-06-01 11:12:28
0

功能需求

使用 C# 编写一个 key-value 结构进程内缓存,实现数据的缓存操作,此处所用到的知识点如下:

  • 线程安全的字典 ConcurrentDictionary
  • 设计模式之单例模式(Singleton);
  • 缓存数据【主动 & 被动】过期模式;

cache

key-value 缓存实现

说明:此处基于 .net 6 平台创建控制台项目。

  • 新建 ConsoleApp 项目,添加 CustomCacheHelper.cs 类;
  1. 导入命名空间(namespace
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
  1. CustomCacheHelper.cs 类中编写实现方法
/// 
/// 自定义内存缓存助手
/// 
public sealed class CustomCacheHelper
{#region 单例模式//创建私有化静态obj锁  private static readonly object _ObjLock = new();//创建私有静态字段,接收类的实例化对象  private static volatile CustomCacheHelper? _Instance = null;//构造函数私有化  private CustomCacheHelper() { }//创建单利对象资源并返回  public static CustomCacheHelper GetSingleObj(){if (_Instance == null){lock (_ObjLock){if (_Instance == null){_Instance = new CustomCacheHelper();}}}return _Instance;}#endregion/// /// 缓存字典 => 【key|value|time】/// private static volatile ConcurrentDictionary> _CacheDictionary = new();/// /// 1.主动过期/// static CustomCacheHelper(){Task.Run(() => {while (true){int millisecondsTimeout = 1000 * 60 * 10;Thread.Sleep(millisecondsTimeout); //10分钟检查一次if (_CacheDictionary != null && _CacheDictionary.Keys.Count > 0){ICollection listKey = _CacheDictionary.Keys;foreach (var key in listKey){var valueTime = _CacheDictionary[key];if (valueTime.Value < DateTime.Now){_CacheDictionary.TryRemove(key, out KeyValuePair value);}}}}});}/// /// 索引器/// /// /// public object this[string key]{get => _CacheDictionary[key];set => _CacheDictionary[key] = new KeyValuePair(value, null);}/// /// 设置相对过期缓存/// /// 键/// 数据包/// 相对过期时间public void Set(string key, object data, int seconds){var expirationTime = DateTime.Now.AddSeconds(seconds);_CacheDictionary[key] = new KeyValuePair(data, expirationTime);}/// /// 设置绝对过期缓存/// /// 键</// 数据包public void Set(string key, object data){this[key] = data; // 下面代码等效// _CacheDictionary[key] = new KeyValuePair(data, null);}/// /// 通过key获取缓存value/// 2.被动过期/// /// /// /// public T? Get(string key){if (Exist(key)){//var valueTime = _CacheDictionary[key];//return (T)valueTime.Key; //return (T)this[key];bool hasValue = _CacheDictionary.TryGetValue(key, out KeyValuePair value);if (hasValue){return (T)value.Key; //return (T)this[key];}}return default;}/// /// 获取所有的key/// /// public ICollection GetKeys() => _CacheDictionary.Keys;/// /// 获取缓存个数/// /// public int Count(){int count = 0;if (_CacheDictionary != null){count = _CacheDictionary.Count;}return count;}/// /// 删除指定key的value/// /// public void Remove(string key){if (Exist(key)){_CacheDictionary.TryRemove(key, out KeyValuePair value);}}/// /// 清空所有缓存/// public void Cleaner(){if (_CacheDictionary != null && _CacheDictionary.Count > 0){foreach (var key in _CacheDictionary.Keys){_CacheDictionary.TryRemove(key, out KeyValuePair value);}}}/// /// 2.被动过期,保证任何过期缓存都无法取值/// 检查key是否存在/// /// /// public bool Exist(string key){bool isExist = false;if (!string.IsNullOrWhiteSpace(key) && _CacheDictionary.ContainsKey(key)){var valTime = _CacheDictionary[key];if (valTime.Value != null && valTime.Value > DateTime.Now){isExist = true; //缓存没过期}else{if (valTime.Value == null){isExist = true; //永久缓存}else{_CacheDictionary.TryRemove(key, out KeyValuePair value); //缓存过期清理}}}return isExist;}
}

Main 方法使用缓存

由于该项目是采用控制台程序编写,我们可直接在 Main 方法中,添加如下代码:

var customCache = CustomCacheHelper.GetSingleObj();
customCache.Set("key1", "value1");
customCache.Set("key2", "value2", 3);
customCache.Set("key3", "value3", 6);
var keys = customCache.GetKeys();Console.WriteLine("首次打印:");
foreach (var key in keys)
{Console.WriteLine($"time:{DateTime.Now},key={key},value={customCache.Get(key)}");
}Console.WriteLine("睡眠5s后再次打印:");
Thread.Sleep(5000);
foreach (var key in keys)
{Console.WriteLine($"time:{DateTime.Now},key={key},value={customCache.Get(key)}");
}

此处代码中我们添加了三组 key-vaule 数据,其中一个是没有设置过期时间,另外两个设置过期时间,保存数据后,分别打印缓存中保存的数据,再第二次缓存打印前,先让线程睡眠等待 5 秒(5000毫秒),注意观察控制台输出的信息。

ConsoleApp 启动测试

从控制台输出的信息中,我们可以看到 key=key2value 值为空,说明我们内部调用 Exist 方法生效了,key2value 缓存有效时间是 3 秒,第二次打印输出信息时,此时已经睡眠 5 秒,相对于 key2 存储的内存数据已经超时,而 key3value 存储的有效时间是 6 秒,没有超时,所以能个获取到对应的内存数据。

启动测试

通过上面的 demo 演示,我们就实现了一个自定义的进程内缓存助手,在项目中可以很方便的导入使用。

相关内容

热门资讯

大行评级|大摩:维持汇丰控股“... 格隆汇7月3日|摩根士丹利发表报告,预期亚洲银行2025年第二季营运表现稳健,财富管理收入应可持续强...
景嘉微:业务开展与合作情况以指... 投资者提问:董秘好请问和成飞有业务来往吗董秘回答(景嘉微SZ300474):您好,有关公司业务开展与...
酷冷至尊全系一体式水冷享受保内...   炒股就看金麒麟分析师研报,权威,专业,及时,全面,助您挖掘潜力主题机会! IT之家 7 月 3...
全志科技:公司没有参加此次大会... 投资者提问:你好,7月的2025世界人工智能大会,公司有参加吗董秘回答(全志科技SZ300458):...
求一现言,女主车祸魂穿男主妻子... 求一现言,女主车祸魂穿男主妻子身上,女主家重男轻女,女主穿越后学化妆,男主好像是总裁。重生之乖乖妻错...
永泰能源:海则滩煤矿项目预计2... 永泰能源在互动平台表示,海则滩煤矿项目矿建工程于2024年6月进入二期工程施工。目前,四条井筒已全部...
投资者提问:请问公司的ai芯片... 投资者提问:请问公司的ai芯片景宏系列和JM11芯片公司是如何推广的?现在有哪些成效?它与市场上的主...
闷热感拉满!河南所遇皆是熟人 转自:大象文娱 【闷热感拉满!#河南所遇皆是熟人# 】据@中国天气,今天下午,河南、安徽、江苏...
抚松森林公安联合开展“送法进企... 近日,抚松森林公安分局泉水中心派出所联合抚松林区人民检察院第一检察部深入辖区民营企业开展“送法进企业...
美越贸易协议将影响一些中国商品... 7月3日,外交部发言人毛宁主持例行记者会。外交部:中方一贯主张有关谈判和协议不应针对或损害第三方的利...