[c#] System.Runtime.Caching.MemoryCache 대 HttpRuntime.Cache-차이점이 있습니까?

MemoryCache와 사이에 차이점이 있는지 궁금합니다. 어떤 HttpRuntime.Cache것이 ASP.NET MVC 프로젝트에서 선호됩니까?

내가 이해하는 한, 둘 다 스레드로부터 안전하고 API는 첫눈에 어느 정도 동일하므로 사용할 때 차이가 있습니까?



답변

HttpRuntime.CacheCache현재 애플리케이션에 대한를 가져옵니다 .

MemoryCache클래스는 ASP.NET Cache클래스 와 유사합니다 .

MemoryCache클래스에는 ASP.NET Cache클래스를 사용한 경우 익숙한 캐시 액세스를위한 많은 속성과 메서드가 있습니다 .

주요 차이점 HttpRuntime.CacheMemoryCache후자는 ASP.NET 응용 프로그램에없는 .NET Framework 응용 프로그램이 사용할 수 있도록 변경되었습니다 점이다.

추가 정보 :

업데이트 :

유저들의 피드백에 따르면 가끔 Jon Davis 블로그가 작동하지 않는 경우가 있으므로 전체 글을 이미지로 담았습니다.

참고 : 명확하지 않은 경우 이미지를 클릭하면 브라우저에서 열리고 다시 클릭하면 확대됩니다.

여기에 이미지 설명 입력


답변

여기에 Jon Davis의 기사가 있습니다. 가독성을 유지하기 위해 지금은 사용되지 않는 EntLib 섹션, 소개 및 결론을 잘라내겠습니다.


ASP.NET 캐시

ASP.NET 또는 System.Web.dll 어셈블리에는 캐싱 메커니즘이 있습니다. 웹 컨텍스트 외부에서 사용할 수는 없지만 웹 외부에서 사용할 수 있으며 해시 테이블에서 위의 모든 만료 동작을 수행합니다.

Google을 살펴본 후 .NET의 기본 제공 캐싱 기능에 대해 논의한 많은 사람들이 웹이 아닌 프로젝트에서 ASP.NET 캐시를 사용하는 것으로 보입니다. 이것은 더 이상 .NET에서 가장 많이 사용 가능하고 가장 많이 지원되는 내장 캐싱 시스템이 아닙니다. .NET 4에는 나중에 살펴볼 ObjectCache가 있습니다. Microsoft는 ASP.NET 캐시가 웹 외부에서 사용하기위한 것이 아니라는 점을 항상 단호했습니다. 그러나 많은 사람들이 여전히 .NET 2.0 및 .NET 3.5에 갇혀 있고 작업 할 무언가가 필요합니다. MSDN이 다음과 같이 분명히 말 했음에도 불구하고 이는 많은 사람들에게 작동합니다.

참고 : Cache 클래스는 ASP.NET 응용 프로그램 외부에서 사용하기위한 것이 아닙니다. 웹 응용 프로그램에 대한 캐싱을 제공하기 위해 ASP.NET에서 사용하도록 설계 및 테스트되었습니다. 콘솔 응용 프로그램이나 Windows Forms 응용 프로그램과 같은 다른 유형의 응용 프로그램에서는 ASP.NET 캐싱이 제대로 작동하지 않을 수 있습니다.

ASP.NET 캐시의 클래스는 System.Web.dll의 System.Web.Caching.Cache입니다. 그러나 단순히 Cache 개체를 새로 만들 수는 없습니다. System.Web.HttpRuntime.Cache에서 가져와야합니다.

Cache cache = System.Web.HttpRuntime.Cache;

ASP.NET 캐시 작업은 여기 MSDN에 문서화되어 있습니다 .

장점 :

  1. 그것은있어 내장 .
  2. .NET 1.0 구문에도 불구하고 사용 이 매우 간단 합니다.
  3. 웹 컨텍스트에서 사용하면 잘 테스트되었습니다 . 웹 컨텍스트 외부에서 Google 검색에 따르면 .NET 2.0 이상을 사용하는 한 Microsoft가 권장하지 않지만 일반적으로 문제를 일으키는 것으로 알려져 있지 않습니다.
  4. 항목이 제거되면 대리인을 통해 알림 을 받을 수 있습니다 . 항목을 유지해야하고 항목의 우선 순위를 미리 설정할 수없는 경우 필요합니다.
  5. 개별 항목은 이 문서 상단의 제거 방법 목록에있는 (a), (b) 또는 (c) 만료 및 제거 방법 중 하나를 유연하게 사용할 수 있습니다. 만료 동작을 실제 파일의 존재와 연관시킬 수도 있습니다.

단점 :

  1. 정적 일뿐만 아니라 . Cache의 자체 정적 인스턴스를 사용하여 고유 한 유형을 만들 수 없습니다. 전체 앱 기간에 대해 하나의 버킷 만 가질 수 있습니다. 키에 접두사 사전 주입과 같은 작업을 수행하는 자체 래퍼로 버킷을 래핑하고 키 / 값 쌍을 다시 가져올 때 이러한 접두사를 제거 할 수 있습니다. 그러나 여전히 버킷은 하나뿐입니다. 모든 것이 하나로 묶여 있습니다. 예를 들어 서너 가지 종류의 데이터를 개별적으로 캐시해야하는 서비스가있는 경우 이는 실제 성가신 일이 될 수 있습니다. 이것은 비참하게 단순한 프로젝트의 경우 큰 문제가되지 않아야합니다. 그러나 프로젝트의 요구 사항으로 인해 상당한 복잡성이있는 경우 일반적으로 ASP.NET 캐시로는 충분하지 않습니다.
  2. 항목이 사라질 수 있습니다.. 이 캐시 구현에 대한 지식을 새로 고칠 때까지 많은 사람들이이를 인식하지 못했습니다. 기본적으로 ASP.NET 캐시는 항목이 “느껴질 때”항목을 파괴하도록 설계되었습니다. 더 구체적으로,이 기사의 맨 위에있는 캐시 테이블 정의에서 (c)를 참조하십시오. 동일한 프로세스의 다른 스레드가 완전히 다른 작업을 수행하고 우선 순위가 높은 항목을 캐시에 덤프하는 경우 .NET이 약간의 메모리가 필요하다고 결정하자마자 캐시의 일부 항목을 삭제하기 시작합니다. 우선 순위를 낮추고 우선 순위를 낮 춥니 다. 캐시 항목을 추가하기 위해 여기에 설명 된 모든 예제는 NotRemovable 우선 순위 값이 아닌 기본 우선 순위를 사용합니다.이 값은 메모리 지우기 목적으로 제거되지 않도록하지만 만료 정책에 따라 제거됩니다.
  3. 키는 문자열이어야합니다. 예를 들어, 레코드가 long 또는 정수에 키가 지정된 데이터 레코드를 캐싱하는 경우 먼저 키를 문자열로 변환해야합니다.
  4. 구문이 오래되었습니다 . .NET 1.0 구문이며 ArrayList 또는 Hashtable보다 더 추합니다. 여기에는 제네릭, IDictionary <> 인터페이스가 없습니다. Contains () 메서드, Keys 컬렉션, 표준 이벤트가 없습니다. Get () 메서드와 Get ()과 동일한 작업을 수행하는 인덱서 만 있으며 일치하는 항목이 없으면 null을 반환하고 Add (), Insert () (중복?), Remove () 및 GetEnumerator () .
  5. 기본 만료 / 제거 동작을 설정 하는 DRY 원칙무시 하므로 잊어 버릴 수 있습니다. 항목을 추가 할 때마다 추가하는 항목이 만료되거나 제거되는 방법을 캐시에 명시 적으로 지정해야합니다.
  6. 추가 된 타임 스탬프와 같은 캐시 된 항목 의 캐싱 세부 정보액세스 할 수있는 방법이 없습니다 . 캡슐화는 여기에서 약간 넘어져서 캐시 된 항목이 다른 캐싱 메커니즘 (예 : 세션 컬렉션)에 대해 무효화되어야하는지 여부를 결정하려고 할 때 캐시를 사용하기가 어려웠습니다.
  7. 제거 이벤트이벤트 로 노출되지 않으며 추가시 추적해야합니다.
  8. 그리고 내가 충분히 말하지 않았다면, 마이크로 소프트 는 웹 외부 에서 그것에 대해 명시 적으로 권장 합니다. 그리고 .NET 1.1로 저주를 받았다 면 웹 외부 에서 안정성에 대한 확신을 가지고 사용 해서는 안되므로 신경 쓰지 마십시오.

.NET 4.0의 ObjectCache / MemoryCache

Microsoft는 마지막으로 최신 버전의 .NET Framework에서 추상 ObjectCache 클래스를 구현했으며 웹이 아닌 설정에서 메모리 내 목적으로 ObjectCache를 상속하고 구현하는 MemoryCache 구현을 구현했습니다.

System.Runtime.Caching.ObjectCache는 System.Runtime.Caching.dll 어셈블리에 있습니다. 기본적으로 ASP.NET 캐시에있는 것과 동일한 .NET 1.0 스타일 인터페이스를 선언하는 추상 클래스입니다. System.Runtime.Caching.MemoryCacheObjectCache의 메모리 내 구현이며 몇 가지 변경 사항 만 제외하면 ASP.NET 캐시와 매우 유사합니다.

슬라이딩 만료가있는 항목을 추가하려면 코드는 다음과 같습니다.

var config = new NameValueCollection();
var cache = new MemoryCache("myMemCache", config);
cache.Add(new CacheItem("a", "b"),
    new CacheItemPolicy
    {
        Priority = CacheItemPriority.NotRemovable,
        SlidingExpiration=TimeSpan.FromMinutes(30)
    });

장점 :

  1. 기본 제공되며 이제 웹 외부에서 Microsoft에서 지원하고 권장합니다.
  2. ASP.NET 캐시와 달리 MemoryCache 개체 인스턴스를 인스턴스화 할 수 있습니다.

    참고 : 정적 일 필요는 없지만 Microsoft의 권장 사항입니다 (노란색주의 참조) .

  3. ASP.NET 캐시의 인터페이스에 비해 항목이 추가되고 중복 된 Insert ()가 제거되고 CacheItem을 사용하여 항목을 추가 할 수있는 항목이 없어도 제거 이벤트를 구독하는 기능과 같은 약간의 개선이 이루어졌습니다. 캐싱 전략을 정의하는 이니셜 라이저가있는 개체 및 Contains ()가 추가되었습니다.

단점 :

  1. 여전히 DRY를 완전히 강화하지 않습니다. 내 경험이 적어도 슬라이딩 만료 TimeSpan을 한 번 설정하고 잊어 버릴 수는 없습니다. 그리고 솔직히 위의 항목 추가 샘플의 정책이 더 읽기 쉽지만 끔찍한 장황함이 필요합니다.
  2. 여전히 일반적으로 키가 지정되어 있지 않습니다. 키로 문자열이 필요합니다. 따라서 문자열로 변환하지 않는 한 데이터 레코드를 캐싱하는 경우 long 또는 int를 저장할 수 없습니다.

DIY : 스스로 만들기

명시 적 또는 슬라이딩 만료를 수행하는 캐싱 사전을 만드는 것은 실제로 매우 간단합니다. (메모리 정리를 위해 항목을 자동 제거하려는 경우 훨씬 더 어려워집니다.) 다음은 수행 할 모든 작업입니다.

  1. T 유형의 값을 포함하는 Expiring 또는 Expirable과 같은 값 컨테이너 클래스, 값이 캐시에 추가 된시기를 저장할 DateTime 유형의 TimeStamp 속성 및 해당 타임 스탬프에서 얼마나 멀리 떨어져 있는지 나타내는 TimeSpan을 만듭니다. 항목이 만료되어야합니다. 명시 적 만료를 위해 타임 스탬프에서 날짜를 뺀 시간을 설정하는 속성 설정자를 노출 할 수 있습니다.
  2. IDictionary를 구현하는 클래스를 만들고 ExpirableItemsDictionary라고합시다. 소비자가 정의한 일반 클래스로 만드는 것을 선호합니다.
  3. # 2에서 만든 클래스에서 Dictionary>를 속성으로 추가하고 InnerDictionary라고합니다.
  4. # 2에서 생성 된 클래스의 IDictionary 구현은 InnerDictionary를 사용하여 캐시 된 항목을 저장해야합니다. 캡슐화는 위의 # 1에서 생성 된 유형의 인스턴스를 통해 캐싱 메서드 세부 정보를 숨 깁니다.
  5. 인덱서 (this []), ContainsKey () 등이 값을 반환하기 전에 만료 된 항목을 지우고 만료 된 항목을 제거하도록주의해야합니다. 항목이 제거 된 경우 getter에서 null을 반환합니다.
  6. 모든 getter, setter, ContainsKey (), 특히 만료 된 항목을 지울 때 스레드 잠금을 사용하십시오.
  7. 만료로 인해 항목이 제거 될 때마다 이벤트를 발생시킵니다.
  8. System.Threading.Timer 인스턴스를 추가하고 초기화 중에 리깅하여 만료 된 항목을 15 초마다 자동 제거합니다. 이것은 ASP.NET 캐시와 동일한 동작입니다.
  9. 항목의 컨테이너 (Expiring 인스턴스)가 이미있는 경우 타임 스탬프를 교체하여 슬라이딩 만료를 푸시하는 AddOrUpdate () 루틴을 추가 할 수 있습니다.

마이크로 소프트는 사용자 기반이 그들에 대한 의존성을 구축했기 때문에 원래 디자인을 지원해야하지만 그것이 좋은 디자인이라는 의미는 아닙니다.

장점 :

  1. 구현 을 완전히 제어 할 수 있습니다 .
  2. DRY을 강화 기본 캐싱 동작을 설정 한 후 바로 캐싱을 선언하지 않고에 키 / 값 쌍을 놓아하면 항목을 추가 할 때마다 자세히 설명합니다.
  3. 즉, 현대적인 인터페이스를 구현할 수 IDictionary<K,T>있습니다. 이렇게하면 인터페이스가 사전 인터페이스로 더 예측 가능하므로 훨씬 쉽게 사용할 수 있으며 IDictionary <>와 함께 작동하는 도우미 및 확장 메서드에 더 쉽게 액세스 할 수 있습니다.
  4. 공용 읽기 전용 속성을 통해 InnerDictionary를 노출하는 것과 같이 캐싱 세부 정보를 캡슐화하지 않을 수 있으므로 캐싱 전략에 대해 명시적인 단위 테스트를 작성하고이를 기반으로하는 추가 캐싱 전략으로 기본 캐싱 구현을 확장 할 수 있습니다.
  5. ASP.NET 캐시 또는 캐싱 응용 프로그램 블록의 .NET 1.0 스타일 구문에 익숙해 진 사용자에게 반드시 익숙한 인터페이스는 아니지만 원하는 모양으로 인터페이스정의수 있습니다 .
  6. 모든 유형의 키를 사용할 수 있습니다. 이것이 제네릭이 만들어진 이유 중 하나입니다. 모든 것이 문자열로 입력되어야하는 것은 아닙니다.

단점 :

  1. Microsoft가 발명하거나 보증 하지 않으므로 동일한 품질 보증을받지 못할 것입니다.
  2. 위에서 설명한 지침 만 구현되었다고 가정 할 때 우선 순위에 따라 메모리를 지우는 항목을 “무언가”지우지 않습니다 (어쨌든 캐시의 코너 케이스 유틸리티 기능입니다. .. 캐시를 사용할 곳에서 RAM을 구입하십시오. , RAM은 저렴합니다).

이 네 가지 옵션 중에서 이것이 제가 선호하는 옵션입니다. 이 기본 캐싱 솔루션을 구현했습니다. 지금까지 완벽하게 작동하는 것 같습니다. 알려진 버그는 없습니다 (아래 의견을 보내 주시거나 jon-at-jondavis에 연락해주세요 !!). 필요한 모든 소규모 프로젝트에서 사용할 예정입니다 기본 캐싱. 여기있어:

Github 링크 : https://github.com/kroimon/ExpirableItemDictionary

이전 링크 : ExpirableItemDictionary.zip

언급할만한 가치 : AppFabric, NoSQL, Et Al

이 블로그 기사의 제목은 “Heavy-Duty Caching”이 아니라 “Simple Caching”을 나타냅니다. 무거운 작업을 수행하려면 전용 스케일 아웃 솔루션을 찾아야합니다.


답변

MemoryCache는 메모리에 저장된 캐시입니다.

HttpRuntime.Cache ( http://msdn.microsoft.com/en-us/library/system.web.httpruntime.cache (v = vs.100) .aspxhttp://msdn.microsoft.com/en- 참조) us / library / system.web.caching.cache.aspx )는 애플리케이션에서 구성한 모든 항목에 유지됩니다.

예를 들어 “ASP.NET 4.0 : 사용자 지정 출력 캐시 공급자 작성”
http://weblogs.asp.net/gunnarpeipman/archive/2009/11/19/asp-net-4-0-writing-custom-output-cache를 참조하십시오. -providers.aspx


답변

Core에 “System.Web.Caching”및 “HttpRuntime”이 없으므로 MemoryCache.Default는 클래식 ASP.NET MVC 앱을 ASP.NET Core로 마이그레이션하는 경우 “브리지”역할도 할 수 있습니다.

나는 또한 bool항목을 20000 번 저장하기위한 작은 벤치 마크를 작성했고 (그리고 그것을 검색하기위한 또 다른 벤치 마크) MemoryCache는 두 배 느린 것처럼 보이지만 (27ms 대 13ms-이는 모든 2 만 회 반복에 대한 합계입니다) 초고속이며 무시할 수 있습니다.


답변