您当前的位置:首页 > 电脑百科 > 数据库 > Redis

不想引入Redis,你可以试试MemoryCache实现内存缓存

时间:2023-05-14 13:31:31  来源:今日头条  作者:小乖兽技术

System.Runtime.Caching库是.NET 4.0引入的缓存库,用于提高应用程序性能。它提供了一组API,用于在内存中存储、检索和管理缓存对象,并包括一些高级功能,如回调和过期策略等。在.NET 7.0中,System.Runtime.Caching库进行了进一步改进和优化,可用于实现不同级别的缓存管理。下面我们对其进行详细介绍和分类。

以下是System.Runtime.Caching库按照不同的功能和用途进行分类,并附有源代码剖析:

System.Runtime.Caching库的适用场景

System.Runtime.Caching库适用于需要在应用程序中实现内存缓存的场景。以下是一些常见的使用场景:

  1. 数据库查询结果的缓存:在数据库查询时,如果查询结果重复使用的概率较高,可以使用MemoryCache类将结果缓存到内存中,减少对数据库的访问次数,提高性能。
  2. 频繁读取的配置信息:在应用程序中,一些配置信息需要频繁读取,这些配置信息可以通过MemoryCache类缓存起来,提高应用程序的响应速度。
  3. 网络请求响应的缓存:在网络请求中,如果某个请求的响应结果较为稳定,可以使用MemoryCache类将响应结果缓存到内存中,提高响应速度和吞吐量。
  4. 预先加载静态资源:在Web应用程序中,某些静态资源(如css、JS等)需要在应用程序启动时预先加载,这些资源可以使用MemoryCache类进行缓存,提高页面渲染速度。
  5. 业务逻辑计算结果的缓存:在某些业务逻辑中,需要频繁进行计算,如果计算结果稳定,可以使用MemoryCache类缓存计算结果,提高计算速度。

System.Runtime.Caching库的优缺点

System.Runtime.Caching是Microsoft提供的内存缓存方案,封装了一组用于管理缓存的API。它使用MemoryCache类来实现内存缓存,可以用于单个应用程序域或分布式系统中。以下是System.Runtime.Caching的优缺点:

优点:

  1. 高性能:System.Runtime.Caching使用内存缓存,相比于其他持久化缓存方案,具有更高的读写速度和更低的响应延迟。
  2. 简单易用:System.Runtime.Caching提供了易于使用的API,可以方便地创建、访问和管理内存缓存,适用于各种.NET应用程序。
  3. 可扩展性:System.Runtime.Caching支持多种缓存项过期策略、缓存项优先级和回收策略,可以根据特定需求进行自定义。
  4. 高可靠性:System.Runtime.Caching支持缓存项压缩、内存监视和回收机制等功能,可以有效提高缓存的可靠性和稳定性。

缺点:

  1. 有容量上限:System.Runtime.Caching使用内存缓存,所以缓存的容量受到硬件资源的限制。对于大型的数据集合,需要考虑使用其他缓存方式或增加硬件资源。
  2. 无法持久化:System.Runtime.Caching只是一个内存缓存方案,不支持将缓存项持久化到磁盘或其他介质中。如果需要实现持久化缓存,需要使用其他缓存方案。
  3. 可能存在并发访问问题:System.Runtime.Caching默认情况下是线程安全的,但是在高并发环境下,仍然可能存在竞争条件和死锁等问题。需要注意并发访问限制和异常处理。

System.Runtime.Caching库API介绍

 

System.Runtime.Caching提供了一组用于管理缓存的API,主要包括以下类型:

  1. MemoryCache类:实现了一个内存缓存,可以用于单个应用程序域或分布式系统中。MemoryCache支持多种缓存项过期策略、缓存项优先级和回收策略,可以根据具体需求进行自定义。常用方法包括Add、Get、Set和Remove等。
  2. CacheItem类:表示缓存中的一个项。CacheItem包含缓存键、缓存值和缓存过期策略等属性,可以通过构造函数创建缓存项,也可以通过MemoryCache类的方法管理缓存项。
  3. CacheItemPolicy类:表示一个缓存项的过期策略。CacheItemPolicy包含过期时间、优先级、回收处理和缓存移除回调等属性,可以通过构造函数创建缓存项策略,并设置给MemoryCache或CacheItem对象。
  4. CacheEntryRemovedArguments类:表示缓存项移除时的参数。CacheEntryRemovedArguments包含了缓存项的键、值、移除原因和移除通知等属性,可以在缓存项移除时进行处理。
  5. CacheEntryUpdateArguments类:表示缓存项更新时的参数。CacheEntryUpdateArguments包含了旧的缓存项的键、值和更新通知等属性,可以在缓存项更新时进行处理。
  6. CacheEntryChangeMonitor类:表示一个监视缓存项变化的对象。CacheEntryChangeMonitor支持多种变化监视器,例如文件监视器、键依赖监视器和SqlDependency监视器等。

MemoryCache类

MemoryCache类是System.Runtime.Caching库中的核心类,它表示一个内存中的缓存集合。MemoryCache类是一个线程安全的、可扩展的、基于键值对的缓存系统。MemoryCache类提供了以下一些方法:

  • Add(string key, object value, CacheItemPolicy policy):向缓存中添加一个具有指定键和值的缓存项,并使用指定的策略对象指定该缓存项的过期和依赖项信息。
  • ContAIns(string key):返回一个值,指示指定键是否存在于缓存中。
  • Get(string key):获取指定键的缓存项。
  • Remove(string key):从缓存中移除指定键的缓存项。
  • GetCount():获取当前缓存中的项数。
  • Dispose():释放MemoryCache对象占用的资源。

源代码剖析:

   [DefaultMember("Item")]
    public class MemoryCache : ObjectCache, IEnumerable, IDisposable
    {
        public MemoryCache(string name, NameValueCollection config = null);
        public MemoryCache(string name, NameValueCollection config, bool ignoreConfigSection);

        public override object this[string key] { get; set; }

        public static MemoryCache Default { get; }
        public long PhysicalMemoryLimit { get; }
        public override string Name { get; }
        public long CacheMemoryLimit { get; }
        public TimeSpan PollingInterval { get; }
        public override DefaultCacheCapabilities DefaultCacheCapabilities { get; }
			  // 添加缓存项
        public override bool Add(CacheItem item, CacheItemPolicy policy);
        public override object AddOrGetExisting(string key, object value, DateTimeOffset absoluteExpiration, string regionName = null);
        public override CacheItem AddOrGetExisting(CacheItem item, CacheItemPolicy policy);
        public override object AddOrGetExisting(string key, object value, CacheItemPolicy policy, string regionName = null);
        public override bool Contains(string key, string regionName = null);
        public override CacheEntryChangeMonitor CreateCacheEntryChangeMonitor(IEnumerable<string> keys, string regionName = null);
        public void Dispose();
      
       // 获取缓存项
        public override object Get(string key, string regionName = null);
        public override CacheItem GetCacheItem(string key, string regionName = null);
        public override long GetCount(string regionName = null);
        public long GetLastSize(string regionName = null);
        public override IDictionary<string, object> GetValues(IEnumerable<string> keys, string regionName = null);
        public override object Remove(string key, string regionName = null);
      
       // 移除缓存项  
       public object Remove(string key, CacheEntryRemovedReason reason, string regionName = null);
        public override void Set(string key, object value, CacheItemPolicy policy, string regionName = null);
        public override void Set(CacheItem item, CacheItemPolicy policy);
        public override void Set(string key, object value, DateTimeOffset absoluteExpiration, string regionName = null);
        public long Trim(int percent);
      
        // 遍历缓存
        protected override IEnumerator<KeyValuePair<string, object>> GetEnumerator();
    }

CacheItem和CacheItemPolicy类

CacheItem表示一个缓存项,包括键、值、过期时间等属性。CacheItemPolicy则表示一个策略对象,用于指定缓存项的一些属性,如过期时间、回收策略、依赖项等。

源代码剖析:

public class CacheItem
{
  public CacheItem(string key);
  public CacheItem(string key, object value);
  public CacheItem(string key, object value, string regionName);

  public string Key { get; set; }
	public object Value { get; set; }
	public string RegionName { get; set; }
}

public class CacheItemPolicy
{
        public CacheItemPolicy();
  
        public DateTimeOffset AbsoluteExpiration { get; set; }
        public Collection<ChangeMonitor> ChangeMonitors { get; }
        public CacheItemPriority Priority { get; set; }
        public CacheEntryRemovedCallback RemovedCallback { get; set; }
        public TimeSpan SlidingExpiration { get; set; }
        public CacheEntryUpdateCallback UpdateCallback { get; set; }
  }

CacheEntryChangeMonitor类

CacheEntryChangeMonitor类提供了监视缓存项更改的功能,以便在发生更改时执行回调函数或其他操作。

源代码剖析:

public abstract class CacheEntryChangeMonitor : ChangeMonitor
    {
        protected CacheEntryChangeMonitor();

        public abstract ReadOnlyCollection<string> CacheKeys { get; }
        public abstract DateTimeOffset LastModified { get; }
        public abstract string RegionName { get; }
    }

缓存对象的管理方式

过期策略

过期策略用于确定何时从缓存中删除对象,以防止缓存过多的对象导致内存泄漏或性能降低。System.Runtime.Caching库中提供了三种基本的过期策略:绝对时间、相对时间和空闲时间。可以通过CacheItemPolicy类中的AbsoluteExpiration、SlidingExpiration属性指定缓存项的过期策略。

源代码剖析:

public class CacheItemPolicy
{
    // 设置过期时间(绝对时间)
    public DateTimeOffset? AbsoluteExpiration { get; set; }

    // 设置过期时间(相对时间)
    public TimeSpan? SlidingExpiration { get; set; }
}

依赖关系

依赖关系用于使缓存项具有基于文件、目录、键或其他对象的依赖关系。当这些依赖项更改时,缓存中的项将自动无效。在System.Runtime.Caching库中,可以通过以下类实现依赖关系的管理:

  • CacheDependency类:表示一个基于文件或目录的依赖项。
  • ChangeMonitor类:表示一个监视缓存项的变化的类,包括CacheDependency、FileChangeMonitor、SqlChangeMonitor等。

源代码剖析:

public class CacheDependency : IDisposable
{
    public CacheDependency(string filename);
    public CacheDependency(string[] filenames);
    public virtual string GetUniqueID();
    public virtual void NotifyDependencyChanged(object sender, EventArgs e);
}

public abstract class ChangeMonitor : IDisposable
{
    // 标识缓存项是否已过期
    public virtual bool HasChanged { get; }
}

回调函数

回调函数用于在缓存项过期或被删除时执行指定的回调函数。在System.Runtime.Caching库中,可以通过CacheItemPolicy类中的RemovedCallback属性指定当缓存项过期或被删除时要执行的回调函数。

源代码剖析:

public class CacheItemPolicy
{
    // 设置缓存项被删除时的回调函数
    public int RemovedCallback { get; set; }
}

高级功能

缓存统计信息

缓存统计信息提供了缓存对象的统计数据,如当前缓存项数目、命中率等。在System.Runtime.Caching库中,可以通过MemoryCacheStatistics类获取缓存统计信息。

源代码剖析:

public sealed class MemoryCacheStatistics
{
    public int Count { get; }
    public long Hits { get; }
    public double HitRatio { get; }
    public long Misses { get; }
    public double MissRatio { get; }
}

高级回收策略

高级回收策略提供了自定义的回收策略,以更精细地控制缓存对象的生命周期。在System.Runtime.Caching库中,可以通过以下类实现高级回收策略的管理:

  • ICachePolicyManager接口:表示一个可自定义的缓存策略管理器。
  • CacheMemoryPressureMonitor类:表示一个监视系统内存压力的对象。
  • BackgroundMemoryMonitor类:表示一个后台线程,用于检测系统内存压力并根据指定的缓存策略来删除缓存项。

源代码剖析:

public interface ICachePolicyManager
{
    CacheItemPolicy GetItemPolicy(string key, object value);
}

public sealed class CacheMemoryPressureMonitor : IDisposable
{
    // 监视系统内存压力,并设置相应的缓存策略
}

public sealed class BackgroundMemoryMonitor : IDisposable
{
    public BackgroundMemoryMonitor(ICachePolicyManager policyManager);
    // 监视系统内存压力,并根据缓存策略来删除缓存项
}

缓存区域

缓存区域允许将缓存项分配到不同的区域,以便更好地管理和组织缓存项。在System.Runtime.Caching库中,可以通过CacheArea类实现缓存区域的管理。

源代码剖析:

public class CacheArea : IDisposable
{
    public CacheArea(string name);
    public string Name { get; }
    public void Dispose();
    public object Get(string key);
    public bool Contains(string key);
    public void Add(string key, object value, CacheItemPolicy policy);
    public void Remove(string key);
}

完整的示例代码

以下是一个使用System.Runtime.Caching命名空间的示例代码,展示了如何使用MemoryCache类来创建缓存并添加、获取和删除缓存项:

using System;
using System.Runtime.Caching;

namespace MemoryCacheDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            // 创建一个内存缓存对象
            MemoryCache cache = MemoryCache.Default;

            // 添加一个缓存项
            cache.Add("key1", "value1", DateTimeOffset.UtcNow.AddMinutes(30));

            // 获取缓存项的值
            Object value = cache.Get("key1");
            if (value != null)
            {
                Console.WriteLine("获取缓存项:{0}", value);
            }

            // 删除缓存项
            cache.Remove("key1");

            // 再次尝试获取已被删除的缓存项
            value = cache.Get("key1");
            if (value == null)
            {
                Console.WriteLine("获取失败,缓存项已被删除");
            }

            // 设置缓存项的属性
            CacheItemPolicy policy = new CacheItemPolicy();
            policy.AbsoluteExpiration = DateTimeOffset.UtcNow.AddMinutes(30);
            cache.Set("key2", "value2", policy);

            Console.ReadKey();
        }
    }
}

在这个例子中,我们首先使用MemoryCache.Default静态属性来获取默认的内存缓存对象。然后,我们使用Add方法向缓存中添加一个项,Get方法从缓存中获取一个项,Remove方法从缓存中删除一个项,以及Set方法设置缓存项的属性。注意,我们使用CacheItemPolicy类来指定缓存项的过期时间和其他选项。

以上是System.Runtime.Caching库按照不同的功能和用途进行分类,并提供相应的源代码剖析。根据实际需求,可以选择适当的API和功能进行组合使用,以达到最佳的性能和效果。



Tags:Redis   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
Redis 不再 “开源”,未来采用 SSPLv1 和 RSALv2 许可证
Redis 官方于21日宣布修改开源协议 &mdash;&mdash; 未来所有版本都将使用 “源代码可用” 的许可证 (source-available licenses)。具体来说,Redis 将不再遵循 BSD 3-Clause...【详细内容】
2024-03-27  Search: Redis  点击:(11)  评论:(0)  加入收藏
Redis“叛逃”开源,得罪了几乎所有人
内存数据库供应商Redis近日在开源界砸下了一块“巨石”。Redis即将转向双许可模式,并实施更为严格的许可条款。官方对此次变更的公告直截了当:从Redis 7.4版本开始,Redis将在Re...【详细内容】
2024-03-25  Search: Redis  点击:(9)  评论:(0)  加入收藏
如何使用 Redis 实现消息队列
Redis不仅是一个强大的内存数据存储系统,它还可以用作一个高效的消息队列。消息队列是应用程序间或应用程序内部进行异步通信的一种方式,它允许数据生产者将消息放入队列中,然...【详细内容】
2024-03-22  Search: Redis  点击:(17)  评论:(0)  加入收藏
Redis不再 “开源”
Redis 官方今日宣布修改开源协议 &mdash;&mdash; 未来所有版本都将使用 “源代码可用” 的许可证 (source-available licenses)。具体来说,Redis 将不再遵循 BSD 3-Clause 开...【详细内容】
2024-03-21  Search: Redis  点击:(8)  评论:(0)  加入收藏
在Redis中如何实现分布式锁的防死锁机制?
在Redis中实现分布式锁是一个常见的需求,可以通过使用Redlock算法来防止死锁。Redlock算法是一种基于多个独立Redis实例的分布式锁实现方案,它通过协调多个Redis实例之间的锁...【详细内容】
2024-02-20  Search: Redis  点击:(47)  评论:(0)  加入收藏
手动撸一个 Redis 分布式锁
大家好呀,我是楼仔。今天第一天开工,收拾心情,又要开始好好学习,好好工作了。对于使用 Java 的小伙伴,其实我们完全不用手动撸一个分布式锁,直接使用 Redisson 就行。但是因为这些...【详细内容】
2024-02-19  Search: Redis  点击:(39)  评论:(0)  加入收藏
工作中Redis有哪些好用的运维工具
工作中使用 Redis 时,如果大家公司没有专业运维,可能开发人员就会面临这些运维的工作,包括 Redis 的运行状态监控,数据迁移,主从集群、切片集群的部署和运维等等。本文我就从这三...【详细内容】
2024-02-06  Search: Redis  点击:(55)  评论:(0)  加入收藏
深入Go底层原理,重写Redis中间件实战
Go语言以其简洁、高效和并发性能而闻名,深入了解其底层原理可以帮助我们更好地利用其优势。在本文中,我们将探讨如何深入Go底层原理,以及如何利用这些知识重新实现一个简单的Re...【详细内容】
2024-01-25  Search: Redis  点击:(66)  评论:(0)  加入收藏
批量执行Redis命令的四种方式!
前言在我们的印象中Redis命令好像都是一个个单条进行执行的,如果有人问你如何批量执行Redis命令,你能回答的上吗,或者说能答出几种方式呢?最容易想到的是Redis的一些批量命令,例...【详细内容】
2024-01-17  Search: Redis  点击:(58)  评论:(0)  加入收藏
Redis 实现多规则限流的思考与实践
市面上很多介绍redis如何实现限流的,但是大部分都有一个缺点,就是只能实现单一的限流,比如1分钟访问1次或者60分钟访问10次这种,但是如果想一个接口两种规则都需要满足呢,我们的...【详细内容】
2024-01-03  Search: Redis  点击:(109)  评论:(0)  加入收藏
▌简易百科推荐
Redis 不再 “开源”,未来采用 SSPLv1 和 RSALv2 许可证
Redis 官方于21日宣布修改开源协议 &mdash;&mdash; 未来所有版本都将使用 “源代码可用” 的许可证 (source-available licenses)。具体来说,Redis 将不再遵循 BSD 3-Clause...【详细内容】
2024-03-27  dbaplus社群    Tags:Redis   点击:(11)  评论:(0)  加入收藏
Redis“叛逃”开源,得罪了几乎所有人
内存数据库供应商Redis近日在开源界砸下了一块“巨石”。Redis即将转向双许可模式,并实施更为严格的许可条款。官方对此次变更的公告直截了当:从Redis 7.4版本开始,Redis将在Re...【详细内容】
2024-03-25    51CTO  Tags:Redis   点击:(9)  评论:(0)  加入收藏
如何使用 Redis 实现消息队列
Redis不仅是一个强大的内存数据存储系统,它还可以用作一个高效的消息队列。消息队列是应用程序间或应用程序内部进行异步通信的一种方式,它允许数据生产者将消息放入队列中,然...【详细内容】
2024-03-22  后端Q  微信公众号  Tags:Redis   点击:(17)  评论:(0)  加入收藏
Redis不再 “开源”
Redis 官方今日宣布修改开源协议 &mdash;&mdash; 未来所有版本都将使用 “源代码可用” 的许可证 (source-available licenses)。具体来说,Redis 将不再遵循 BSD 3-Clause 开...【详细内容】
2024-03-21  OSC开源社区    Tags:Redis   点击:(8)  评论:(0)  加入收藏
在Redis中如何实现分布式锁的防死锁机制?
在Redis中实现分布式锁是一个常见的需求,可以通过使用Redlock算法来防止死锁。Redlock算法是一种基于多个独立Redis实例的分布式锁实现方案,它通过协调多个Redis实例之间的锁...【详细内容】
2024-02-20  编程技术汇    Tags:Redis   点击:(47)  评论:(0)  加入收藏
手动撸一个 Redis 分布式锁
大家好呀,我是楼仔。今天第一天开工,收拾心情,又要开始好好学习,好好工作了。对于使用 Java 的小伙伴,其实我们完全不用手动撸一个分布式锁,直接使用 Redisson 就行。但是因为这些...【详细内容】
2024-02-19  楼仔  微信公众号  Tags:Redis   点击:(39)  评论:(0)  加入收藏
工作中Redis有哪些好用的运维工具
工作中使用 Redis 时,如果大家公司没有专业运维,可能开发人员就会面临这些运维的工作,包括 Redis 的运行状态监控,数据迁移,主从集群、切片集群的部署和运维等等。本文我就从这三...【详细内容】
2024-02-06  waynaqua    Tags:Redis   点击:(55)  评论:(0)  加入收藏
批量执行Redis命令的四种方式!
前言在我们的印象中Redis命令好像都是一个个单条进行执行的,如果有人问你如何批量执行Redis命令,你能回答的上吗,或者说能答出几种方式呢?最容易想到的是Redis的一些批量命令,例...【详细内容】
2024-01-17  小许code  微信公众号  Tags:Redis命令   点击:(58)  评论:(0)  加入收藏
Redis 实现多规则限流的思考与实践
市面上很多介绍redis如何实现限流的,但是大部分都有一个缺点,就是只能实现单一的限流,比如1分钟访问1次或者60分钟访问10次这种,但是如果想一个接口两种规则都需要满足呢,我们的...【详细内容】
2024-01-03  架构精进之路  微信公众号  Tags:Redis   点击:(109)  评论:(0)  加入收藏
一站式Redis解决方案
Redis是一个高效的内存数据库,它支持包括String、List、Set、SortedSet和Hash等数据类型的存储,在Redis中通常根据数据的key查询其value值,Redis没有模糊条件查询,在面对一些需...【详细内容】
2024-01-01  大雷家吃饭    Tags:Redis   点击:(66)  评论:(0)  加入收藏
站内最新
站内热门
站内头条