ASP.NET caching pro více pokročilé: System.Web.Caching API

V předchozích dvou zápisech o cacheování jsem se věnoval ukládání hotových výstupů, ať už celých stránek nebo jenom jejich částí (user controls). To ovšem není jediná forma cachingu, jakou ASP.NET podporují. Prostřednictvím caching API (namespace System.Web.Caching.Cache) můžete ukládat v podstatě libovolné objekty. Patřičné rozhraní je jednoduché, ale velmi užitečné.

Základní informace o tomto tématu sepsala má milovaná před nějakým časem ve článku System.Web.Caching – cachování objektů v ASP.NET, na který vás tímto odkazuji. Budu se věnovat několika záludnostem.

Bezpečné načítání položek z cache

To že jste si něco uložili do cache ještě neznamená, že to tam najdete. Systém položky z cache odstraňuje nejen dle vámi explicitně určených pravidel (závislostí), ale též dle vlastního uvážení, příkladně pocítí-li nedostatek paměti. Obecně tedy možné na existenci cacheovaných dat spoléhat a pokud s nimi chcete pracovat, měli byste tak činit prostřednictvím nějakého wrapperu, který je buď načte z cache a nebo, neexistují-li, je vygeneruje a do cache uloží. Osobně používám přibližně následující kód:

Public Function GetCategories(Optional ByVal UseCache As Boolean = True) As DataTable
    ' Pokus se načíst hodnotu z cache
    Dim Cats As DataTable = DirectCast(Cache("Categories"), DataTable)

    If Cats Is Nothing Or Not UseCache Then
        ' Pokud nebyl objekt v cache nalezen, nebo bylo použití cache 
        ' explicitně zakázáno, načti data z databáze
        Dim DA As New System.Data.SqlClient.SqlDataAdapter( _
            "SELECT CategoryID, Name, Description FROM Categories ORDER BY Name", _
            "SERVER=(local);UID=uzivatel;PWD=heslo")
        DA.Fill(Cats)
        DA.Dispose()

        ' ...a ulož je do cache
        Cache.Insert("Categories", Cats, Nothing, DateTime.Now.AddMinutes(15), TimeSpan.Zero)
    End If

    ' Vrať obstaranou hodnotu
    Return Cats
End Function

Pomocí nepovinného parametru UseCache jest možno v odůvodněných případech vynutit obnovení cache (např. vím-li že se daná hodnota změnila).

Záludnost jménem CacheItemRemovedCallback

ASP.NET teoreticky obsahují výtečnou funkci, která by shora uvedený problém mohla vyřešit. Tou je delegát CacheItemRemovedCallback, který může ukazovat na funkci, která se vykoná v okamžiku, kdy je objekt z cache odstraněn. V praxi je její použitelnost dosti omezená, protože volání probíhá tak, že se objekt nejprve odstraní z cache a až potom se zavolá callback, který by cache mohl eventuelně znovu naplnit. Což je úkon, který může jistou dobu trvat. Po tuto dobu objekt v cache nebude přítomen, což nás oklikou vrací zpět na začátek a na objekty uložené v cache není možno se spolehnout.

V praxi jsem zatím našel pro tuto funkci jediné využití, a to zaznamenávat případy odstranění objektu z důvodu nedostatku paměti. Pokud se to stává příliš často, měli byste uvažovat o tom, že svému serveru dopřejete víc RAMky.

Sladká budoucnost

Cacheování získává nový rozměr v okamžiku, kdy lze specifikovat závislost uloženého objektu na něčem jiném. Současná verze ASP.NET 1.1 umí nastavovat závislost uložených objektů toliko na souborech nebo jiných cacheovaných objektech (prostřednictvím System.Web.Caching.CacheDependency). V případě, že je údaj závislý na něčem jiném, příkladně na obsahu databáze, máte smůlu - musíte se smířit s tím, že může nastat situace kdy bude objekt neaktuální a nastavit čas expirace tak, aby ta doba byla přijatelná pro vaše záměry.

ASP.NET 2.0 (Whidbey) ovšem slibují třídu System.Web.Caching.SqlCacheDependency, umožňující stanovit závislost cacheovaného prvku na SQL databázi. O důvod víc, proč se na Whidbey těšit.

Titulek:
Text komentáře:
Vaše jméno:
Váš e-mail: (nebude zveřejněn)

WWW stránka:
Opište text z obrázku:
odpovědětodpovědět Gravatar

CacheItemRemovedCallback - upresneni

Objekt v cache je sice z cache uvolnen, ale delegatu je jeho obsah predan v parametru Value. A s tim se da pracovat.

Puvodni obsah se necha ihned ulozit do cache, a mezitim ziskavat novou verzi obsahu (at ve stejnem, ci jinem threadu).

Ja naopak CacheItemRemovedCallback pouzivam k tzn. "Bezpecne cache". Nekdy se stane, ze obsah cache taham z externim ci neprilis spolehlivych zdroju. Pak mam logiku, ze pokud se mi nepodari ziskat novou verzi obsahu, ponechavam starou. A k tomu pouzivam (mimojine) CacheItemRemovedCallback.

Na SqlCacheDependency bych uplne nesazel - je to osidna vec, ktera pri nechodnem pouziti zpusobi pretizeni SQL serveru (hlavne SQL 7 a 2000). A implementovat ji uz dnes do .NET 1.1 je pomerne snadne......

viz posledni odstavec v http://blog.vyvojar.cz/radim/archive/2004/05/27/1173.aspx

odpovědětodpovědět Gravatar

RE: SqlCacheDependency - jak napsat

ukazku vlatni SqlCacheDependency v .NET 1.1 (v tomto pripade pro SQLite, ale to neni podstatne) najdete treba na http://www.eggheadcafe.com/articles/20040916.asp

odpovědětodpovědět Gravatar

RE: SqlCacheDependency

Z Vaseho pridpevku mi vyplyva, ze SqlCacheDependency(.net 2) bude pracovat s akoukolvek databazou. Preto som z toho trochu zmateny, lebo ked som sa v oktobri na Invexe pytal cloveka z Microsoftu ako bude implementovana SqlCacheDependency, povedal ze bude vyuzivat Notification Service v Yukone, z coho mi vyplynulo, ze bude fungovat iba s Yukonom. Tak teraz neviem ci sa nieco zmenilo, alebo mam sklerozu, alebo...:-) Budem rad ak mi to objasnite. Vdaka

odpovědětodpovědět Gravatar

RE: SqlCacheDependency

SqlCacheDependency (alepson podle mne znamych 3 mesice starych informaci) bude podporovat SQL 7/2000 (pomoci triggeru a pomocnych tabulek, ktere periodicky nacita a kontroluje zmeny (timestamp), takze "pull" ), v Yukonu pomoci Notification Service (coz zjednodusene znamena, ze .NET SqlCacheDependency si prihlasi odber zprav z Yukonu a pokud se v tabulce neco zmeni, dostane od Yukonu zpravu ( "push" )

co se podpory "libovolne" db tyka, tak bych to nenazval. Standartne v .NETu bude podpora pro vyse zminene db, ale protoze v .NETu je maloco uzavrene, je mozne dopsat podporu SqlCacheDependency i pro jine databaze.

odpovědětodpovědět Gravatar

Session vs. Cache

Jak je to z hlediska výkonu serveru, když si třeba dataset uložím do session? Je nějaký rozdíl, pokud jej uložím do cache nebo session - mimo to, že session vyprchá?

Hlavní rozdíl mezi session a cache spočívá v tom, že cache je společná pro všechny uživatele (požadavky). S ukládáním většího objemu dat do session je tradičně potřeba být velice opatrný. Nejste-li, pak stačí jeden indexovací robot bez cookies (nebo úmyslný útok) a vyswapuje vám server.

odpovědětodpovědět Gravatar

RE: Session vs. Cache

Souhlasím, že se mají sessions používat opatrně. Nicméně, je to z hlediska výkonu obdobné, když počítám tedy ne sessions, ale applications? Je mi jasné, že cache je hodně vylepšený nástroj na ukládání dat, pro applications si to člověk musel udělat sám.

  • Altairis
  • Nemesis
  • Microsoft MVP
  • IIS
  • ASP.NET