2012-03-09 5 views
1

거의 업데이트되지 않는 일부 목록 데이터를 저장하기 위해 ASP.NET MVC 웹 응용 프로그램에서 캐시를 사용하려고합니다. 나는이 같은 UpdateCache() 방법으로 캐시에 데이터를 삽입합니다 ASP.NET에서 캐시 사용

HttpContext.Current.Cache.Insert("MyApp-Products", products, null, DateTime.Now.AddYears(99), Cache.NoSlidingExpiration); 

그런 다음 내 모델에서 내가 검색 : 예상대로

public static List<string> GetProducts() 
{ 
    var cachedProducts = HttpContext.Current.Cache["MyApp-Products"]; 
    if (cachedProducts == null) 
    { 
     UpdateCache(); 
     cachedProducts = HttpContext.Current.Cache["MyApp-Products"]; 
    } 
    return ((List<string>)cachedProducts); 
} 

내가 페이지를 처음 방문이 UpdateCache()가 호출됩니다. 새로 고침하면 데이터가 캐시에서 가져오고 UpdateCache() 번으로 전화 할 필요가 없습니다. 그러나 15 분이 지나면 앱으로 돌아가 캐시 된 값이 사라집니다. 나의 이해는이 캐시가 세션이 아닌 응용 프로그램마다 있었기 때문에 나 자신이나 다른 사용자를 위해 여전히 거기에있을 것으로 기대했을 것입니다.

캐시를 저장하는 방식에 문제가 있습니까? 또는 ASP.NET의 Cache이 웹 앱에서 어떻게 작동하는지 이해하지 못하고 있습니까?

+2

IIS에서 유휴 시간 제한이란 무엇입니까? 응용 프로그램이 종료되는 것입니까? 기본값은 20 분입니다. –

+0

저는 IIS에 익숙하지 않습니다. IIS 관리자에서이 설정을 찾을 수 있습니까? – Paul

+0

찾았습니다. 그리고 그것이 문제라고 생각합니다. 감사! – Paul

답변

2

이것은 전체 IIS에서 발생하며 매 15 분마다 발생합니다. 유휴 시간 초과 값을 확인하십시오.

즉,이 목록이 "절대로"변경되지 않으면 정적 배열에 저장하지 않는 것이 좋습니다.

+0

거의 변경되지 않지만 절대로 변경되지는 않습니다. 백그라운드에서'UpdateCache()'를 주기적으로 호출하는 예약 된 작업을 실행할 계획이었습니다. – Paul

+0

어디에서 IIS의 시간 제한 값을 확인할 수 있습니까? – Pankaj

+0

ApplicationPool의 고급 속성 아래에 있습니다. – Paul

5

나의 이해는이 캐시는 응용 프로그램 당 세션 아니라는 것을, 그래서 나는 여전히 자신 또는 다른 사용자가있을 것으로 예상했을 것이다.

캐시는 응용 프로그램마다 있지만 ASP.NET은 캐시에 항목을 저장하면 다시 찾을 수 있음을 보증하지 않습니다. 예를 들어 서버의 메모리가 부족한 상태 등으로 인해 캐시가 제거 될 수 있습니다. 이벤트에 가입하고 항목이 캐시에서 제거 될 때 알림을받을 수 있습니다. 항목을 캐싱 할 때 우선 순위를 정의 할 수도 있습니다. 우선 순위가 높을수록이 항목이 제거 될 확률이 낮아집니다.

또한 캐시가 웹 서버의 메모리에 저장되므로 (기본적으로) 응용 프로그램 도메인을 IIS가 언제든지 재활용 할 수 있다는 사실을 잊어서는 안됩니다. 예를 들어 일정량의 비활성 후 또는 메모리가 부족한 상태로 시작하거나 특정 CPU 임계 값 사용량에 도달 했더라도 캐시를 포함하여 메모리에 저장된 모든 내용이 무효로 사라지고 다음 요청이 사라집니다 응용 프로그램의 새 AppDomain이 시작됩니다.

그러나 어떤 경우에도 항목을 사용하기 전에 캐시에 항목이 있는지 확인하십시오. 당신이 무언가를 그것 안에 저장했다면, 그것을 발견 할 것이라는 사실에 결코 의지하지 마십시오.

이 모든 blabla는 코드에서 매우 걱정스러운 부분입니다. List<string> 인스턴스를 캐시에 저장하는 것 같습니다. 그러나 캐시가 응용 프로그램 당 하나이므로이 단일 인스턴스 List<string>은 응용 프로그램의 여러 사용자가 공유 할 수 있으며 물론 동시에 발생할 수 있습니다. 그리고 알고 있듯이 List<T>은 스레드 안전 구조가 아닙니다. 따라서이 코드를 사용하면 기껏해야 예외가 발생하고 최악의 경우 데이터가 손상됩니다. 따라서 캐싱 할 내용과 스레드가 안전한 클래스를 캐싱하는 경우 특히 구조에 대한 액세스를 동기화하는 방법에 대해 매우 신중해야합니다.

+0

값을 변경하려고하는 것처럼 들리지 않아 문제가되지 않을 수도 있습니다. IEnumerable 을 사용하면 더 명확하게 알 수 있습니다. – Timbo

+0

읽기 전용 데이터입니다. IEnumerable 을 사용하는 것이 여전히 좋을까요, 아니면 수정되지 않는 것이 중요할까요? – Paul

+1

@Paul, 이는 데이터로 무엇을하고 있는지에 달려 있습니다. 예를 들어, 읽기 용 색인을 사용하여 목록의 개별 요소에 액세스하는 것은 스레드로부터 안전합니다. 그것은 구현 세부 비록. 반면 목록에서 열거하는 것은 스레드로부터 안전하지 않습니다. 따라서이 목록에 foreach 루프를 작성하고 동일한 인스턴스에서이 루프를 실행하는 2 명의 동시 사용자가있는 경우 문제가 발생할 수 있습니다. –

0

데이터베이스에서 데이터를 일반적으로 저장하는 것이 정적 개체보다 더 나은지 확인할 수 있습니다. 데이터가 변경되는 경우 응용 프로그램보다 DB를 업데이트하는 것이 더 쉽습니다.

는 개체를 캐시 할 때 명시 적으로 절대 만료를 설정하십시오 :

HttpRuntime.Cache.Insert("MyApp-Products", cachedProducts, null, DateTime.Now.AddDays(20), TimeSpan.Zero); 

httpRuntime을이 차이가 작은 경우에도 성능 향상을 위해 대신 HttpContext를 사용됩니다.