C# 缓存

介绍
缓存,在一定程度上,是可以提高程序性能的一个解决方案,比如,我们从数据库读数据,如果每次都从数据库读取的话,每次都需要进行 网络IO操作,需要等待网络数据返回,如果在60s内,有成千上百个访问进行同样的数据进行查询,将会更加耗时耗力……如果,我们将第一个访问者查询的数据,先保存起来,然后60s内,其他访问者均读取保存起来的数据,这样不需要再去重新查询数据库,减少一定的网络操作,所以说,缓存,一定程度上可以提高程序性能!
这里将介绍如何使用C# 中的MemoryCache 来实现内存缓存!

建立项目
用vs 新建 命令行程序,然后,引入 system.running.cache类库

Cache 实现
定义一个ICache 接口

public interface ICache
{
    /// <summary>
    ///     获取缓存项,当没有缓存时,使用factory提供的值
    /// </summary>
    /// <param name="key"></param>
    /// <param name="factory"></param>
    /// <returns></returns>
    object Get(string key, Func<string, object> factory);


    /// <summary>
    ///     获取缓存项,没有缓存时返回默认数据
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    object GetOrDefault(string key);

    /// <summary>
    ///     设置缓存项并设置过期时间
    /// </summary>
    /// <param name="key">key</param>
    /// <param name="value">值</param>
    /// <param name="slidingExpireTime">多久未访问则失效</param>
    /// <param name="absoluteExpireTime">超时失效</param>
    void Set(string key, object value, TimeSpan? slidingExpireTime = null,TimeSpan?absoluteExpireTime=null);

    /// <summary>
    ///     移除缓存项
    /// </summary>
    /// <param name="key"></param>
    void Remove(string key);

    /// <summary>
    ///     清空缓存
    /// </summary>
    void Clear();

}

该接口提供了获取缓存、设置缓存、移除缓存和清空缓存操作,且 get 方法,如果缓存中没有项,则可以通过 factory返回数据并保存到缓存!
缓存基类:CacheBase

public abstract class CacheBase : ICache
{

    protected readonly object SyncObj = new object();

    protected CacheBase()
    {
    }

    public virtual object Get(string key, Func<string, object> factory)
    {
        var cacheKey = key;
        var item = this.GetOrDefault(key);
        if (item == null)
        {
            lock (this.SyncObj)// TODO: 为何要锁定
            {
                item = this.GetOrDefault(key);
                if (item != null)
                {
                    return item;
                }

                item = factory(key);
                if (item == null)
                {
                    return null;
                }

                this.Set(cacheKey, item);
            }
        }

        return item;
    }
    
    public abstract object GetOrDefault(string key);
    
    public abstract void Set(string key, object value, TimeSpan? slidingExpireTime = null, TimeSpan? absoluteExpireTime = null);
    
    public abstract void Remove(string key);
    
    public abstract void Clear();
    
    public virtual void Dispose()
    {

    }
}

缓存基类为虚类,只实现了 Get(string key, Func<string, object> factory) 方法, 这里进行了锁定,主要是为了多线程操作,在设置缓存的时候,只会有一个访问者在设置缓存项,其他方法均为虚方法,等待具体实现类实现

缓存具体实现类:DemoCache

public class DemoCache : CacheBase
{
    private MemoryCache _memoryCache;

    public DemoCache()
        : base()
    {
        this._memoryCache = new MemoryCache("DemoCache");
    }
    
    public override object GetOrDefault(string key)
    {
        return this._memoryCache.Get(key);

    }

    public override void Set(string key, object value, TimeSpan? slidingExpireTime = null, TimeSpan? absoluteExpireTime = null)
    {
        if (value == null)
        {
            throw new Exception("Can not insert null values to the cache!");
        }


        var cachePolicy = new CacheItemPolicy();

        if (absoluteExpireTime != null)
        {
            cachePolicy.AbsoluteExpiration = DateTimeOffset.Now.Add(absoluteExpireTime.Value);

        }
        else if (slidingExpireTime != null)
        {
            cachePolicy.SlidingExpiration = slidingExpireTime.Value;
        }
        else
        {
            cachePolicy.AbsoluteExpiration = DateTimeOffset.Now.Add(TimeSpan.FromSeconds(60));
            

        }

        this._memoryCache.Set(key, value, cachePolicy);

    }

    public override void Remove(string key)
    {
        this._memoryCache.Remove(key);

    }

    public override void Clear()
    {
        // 将原来的释放,并新建一个cache
        this._memoryCache.Dispose();
        this._memoryCache = new MemoryCache("DemoCache");

    }
    
    public override void Dispose()
    {
        this._memoryCache.Dispose();
        base.Dispose();
    }
}

在具体实现类内,维护一个 MemoryCache, 其他方法,均操作MemoryCache 进行缓存操作!
在具体的设置缓存项中,设置了,如果过期时间为空的话,则设置多久为访问超时,如果两则都为空的话,则设置 定时超时,这里默认为 60 秒。
清空缓存的时候,则释放 memorycache,并新建具体cache实例来实现

使用缓存
定义一个方法,用来取数据

private static int GetCacheRandom(ICache cache)
{
var cacheItem = cache.Get(“random”,
(key) =>
{
Random random = new Random();
return random.Next(1, 1000);
});
return int.Parse(cacheItem.ToString());
}

这个方法,提供了取1到1000的随机值,并保存到缓存中。
定义一个现实函数,用来现实 何时取到的数字

    private static void ShowCacheItem(int value)
    {
        Console.WriteLine("{0}  取数:{1}",DateTime.Now.ToString("HH:mm:ss"), value);
    }

具体使用

    static void Main(string[] args)
    {
        ICache cache = new DemoCache();

        var cacheItem = GetCacheRandom(cache);
        Console.Write("第一次取值    ");
        ShowCacheItem(cacheItem);

        Stopwatch watch=new Stopwatch();
        watch.Start();

        while (true)
        {
            if (watch.ElapsedMilliseconds < 10000)
            {
                continue;
            }

            cacheItem = GetCacheRandom(cache);
            Console.Write("10s后取值    ");
            ShowCacheItem(cacheItem);
            break;
        }

        while (true)
        {
            if (watch.ElapsedMilliseconds < 40000)
            {
                continue;
            }
            cacheItem = GetCacheRandom(cache);
            Console.Write("40s后取值    ");
            ShowCacheItem(cacheItem);
            break;
        }

        while (true)
        {
            if (watch.ElapsedMilliseconds < 70000)
            {
                continue;
            }
            cacheItem = GetCacheRandom(cache);
            Console.Write("70s后取值,此时应该是新值    ");
            ShowCacheItem(cacheItem);
            break;
        }
        
        watch.Stop();

        Console.WriteLine("输入任意键退出!");
        Console.ReadKey();

    }

首先建立 DemoCache的实例,然后获取一次数值,然后10s取一次数据,40s取一次数据,70s取一次数据,如果缓存生效,则前三次,即第一次,10s取得一次,40s取得数字,应该是一样的,70s取得数据应该和前三次不一样。
运行结果如下:

图片.png

通过结果我们可以发现,前三次的取值是一样的,也就是说,缓存是生效的

总结
主要是通过memoryCache来实现缓存,以及简单的缓存用法!

作者:诸葛_小亮
链接:https://www.jianshu.com/p/03e6741deb3c

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值