推广 热搜: csgo  vue  angelababy  2023  gps  新车  htc  落地  app  p2p 

C# 实现 key-value 结构自定义缓存 CustomCache

   2023-08-29 网络整理佚名2280
核心提示:功能需求结构进程内缓存,实现数据缓存的基本操作,此处所用到的知识点如下:缓存实现平台创建控制台项目。导入命名空间()类中编写实现方法方法使用缓存方法中,添加如下代码:秒(5000毫秒),注意观察控制台输出的信息。启动测试秒,没有超时,所以能个获取到对应的内存数据。启动测试演示,我们就实现了一个自定义的进程内缓存助手,在项目中可以很方便的导入使用。

功能要求

使用C#编写一个键值结构进程内缓存,实现数据缓存的基本操作。 这里用到的知识点如下:

-值缓存实现

说明:这里创建一个基于.net 6平台的控制台项目。

导入命名空间()

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

在.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<string, KeyValuePair<object, DateTime?>> _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<string> listKey = _CacheDictionary.Keys;
                    foreach (var key in listKey)
                    {
                        var valueTime = _CacheDictionary[key];
                        if (valueTime.Value < DateTime.Now)
                        {
                            _CacheDictionary.TryRemove(key, out KeyValuePair<object, DateTime?> value);
                        }
                    }
                }
            }
        });
    }

    /// 
    /// 索引器
    /// 

    /// 
    /// 
    public object this[string key]
    {
        get => _CacheDictionary[key];
        set => _CacheDictionary[key] = new KeyValuePair<object, DateTime?>(valuenull);
    }

    /// 
    /// 设置相对过期缓存
    /// 

    /// 
    /// 数据包
    /// 相对过期时间
    public void Set(string key, object data, int seconds)
    {
        var expirationTime = DateTime.Now.AddSeconds(seconds);
        _CacheDictionary[key] = new KeyValuePair<object, DateTime?>(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<object, DateTime?> value);
            if (hasValue)
            {
                return (T)value.Key; //return (T)this[key];
            }
        }

        return default;
    }

    /// 
    /// 获取所有的key
    /// 

    /// 
    public ICollection<stringGetKeys() => _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<object, DateTime?> value);
        }
    }

    /// 
    /// 清空所有缓存
    /// 

    public void Cleaner()
    {
        if (_CacheDictionary != null && _CacheDictionary.Count > 0)
        {
            foreach (var key in _CacheDictionary.Keys)
            {
                _CacheDictionary.TryRemove(key, out KeyValuePair<object, DateTime?> 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<object, DateTime?> 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<string>(key)}");
}

Console.WriteLine("睡眠5s后再次打印:");
Thread.Sleep(5000);
foreach (var key in keys)
{
    Console.WriteLine($"time:{DateTime.Now},key={key},value={customCache.Get<string>(key)}");
}

这里的代码中,我们添加了三组键值数据,其中一组不设置过期时间,另外两组设置过期时间。 保存数据后,分别打印缓存中保存的数据,在第二次缓存打印之前,先让线程休眠等待5秒(5000毫秒),并注意控制台输出的信息。

开始测试

从控制台输出的信息可以看到key=key2的值为空,这说明我们内部调用Exist方法已经生效,key2的值缓存的有效时间为3秒。 当第二次打印出信息时,此时已经休眠了5秒,key2中存储的内存数据已经超时,而key3中存储的值有效期为6秒,没有超时,这样就可以一一获取对应的内存数据。

开始测试

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

portant;overflow-wrap: break-word !important;">
portant;overflow-wrap: break-word !important;">portant;overflow-wrap: break-word !important;">portant;overflow-wrap: break-word !important;">推荐阅读:
portant;overflow-wrap: break-word !important;">inktype="text" imgurl="" imgdata="null" data-itemshowtype="11" tab="innerlink" data-linktype="2">微软开源了一个 助力开发LLM 加持的应用的 工具包 semantic-kernel
portant;overflow-wrap: break-word !important;">inktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="outline: 0px;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">【译】使用 ChatGPT 和 Azure Cosmos DB 构建智能应用程序
portant;overflow-wrap: break-word !important;">inktype="text" imgurl="" imgdata="null" data-itemshowtype="11" tab="innerlink" data-linktype="2" hasload="1" style="outline: 0px;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">实际体验文心一言 VS ChatGPT
portant;overflow-wrap: break-word !important;">inktype="text" imgurl="" imgdata="null" data-itemshowtype="11" tab="innerlink" data-linktype="2" hasload="1" style="outline: 0px;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">选择 .NET 的 n 个理由
portant;overflow-wrap: break-word !important;">inktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="outline: 0px;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">一个.NET开发的开源神级录屏软件
portant;overflow-wrap: break-word !important;">inktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="outline: 0px;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">inktype="text" imgurl="" imgdata="null" data-itemshowtype="11" tab="innerlink" data-linktype="2" hasload="1" style="outline: 0px;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">跨平台`ChatGpt` 客户端

portant;overflow-wrap: break-word !important;">点击下方卡片关注DotNet NB

portant;overflow-wrap: break-word !important;">一起交流学习

portant;overflow-wrap: break-word !important;">

portant;overflow-wrap: break-word !important;">

portant;overflow-wrap: break-word !important;">▲ 点击上方卡片关注DotNet NB,一起交流学习

portant;overflow-wrap: break-word !important;">请在公众号后台

portant;overflow-wrap: break-word !important;">回复 【路线图】获取.NET 2021开发者路线图
portant;overflow-wrap: break-word !important;">回复 【原创内容】获取公众号原创内容
portant;overflow-wrap: break-word !important;">回复 【峰会视频】获取.NET Conf开发者大会视频
portant;overflow-wrap: break-word !important;">回复 【个人简介】获取作者个人简介
portant;overflow-wrap: break-word !important;">回复 【年终总结】获取作者年终总结
portant;overflow-wrap: break-word !important;">回复 加群加入DotNet NB 交流学习群
portant;overflow-wrap: break-word !important;">
portant;overflow-wrap: break-word !important;">长按识别下方二维码,或点击阅读原文。和我一起,交流学习,分享心得。
portant;overflow-wrap: break-word !important;">

portant;overflow-wrap: break-word !important;">

portant;overflow-wrap: break-word !important;">

portant;overflow-wrap: break-word !important;">

 
反对 0举报 0 收藏 0 打赏 0评论 0
 
更多>同类资讯
推荐图文
推荐资讯
点击排行
网站首页  |  关于我们  |  联系方式  |  使用协议  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报
Powered By DESTOON