System.Runtime.Caching.MemoryCache กับ HttpRuntime.Cache - มีความแตกต่างหรือไม่?


85

ฉันสงสัยว่ามีความแตกต่างระหว่างMemoryCacheและHttpRuntime.Cacheข้อใดเป็นที่ต้องการในโครงการ ASP.NET MVC

เท่าที่ฉันเข้าใจทั้งสองอย่างปลอดภัยเธรด API ตั้งแต่แรกเห็นเหมือนกันมากหรือน้อยกว่ากันดังนั้นเวลาที่จะใช้มีความแตกต่างกันอย่างไร

คำตอบ:


82

HttpRuntime.CacheรับCacheแอปพลิเคชันปัจจุบัน

MemoryCacheชั้นคล้ายกับ ASP.NET Cacheระดับ

MemoryCacheชั้นจะมีคุณสมบัติหลายอย่างและวิธีการในการเข้าถึงของแคชที่จะคุ้นเคยกับคุณถ้าคุณได้ใช้ของ ASP.NET Cacheระดับ

ความแตกต่างที่สำคัญระหว่างHttpRuntime.CacheและMemoryCacheคือส่วนหลังได้รับการเปลี่ยนแปลงเพื่อให้สามารถใช้งานได้โดยแอปพลิเคชัน. NET Framework ที่ไม่ใช่แอปพลิเคชัน ASP.NET

สำหรับการอ่านเพิ่มเติม:

อัปเดต:

ตามความคิดเห็นของผู้ใช้บางครั้งบล็อก Jon davis ไม่ทำงานดังนั้นฉันจึงใส่บทความทั้งหมดเป็นรูปภาพโปรดดูที่

หมายเหตุ:หากยังไม่ชัดเจนให้คลิกที่ภาพหลังจากนั้นจะเปิดบนเบราว์เซอร์จากนั้นคลิกอีกครั้งเพื่อซูม :)

ใส่คำอธิบายภาพที่นี่


บทความของ John Davis นั้นอ่านได้ดีมาก - มีข้อดีข้อเสียที่ชัดเจนในที่เดียว
Giedrius

ทุกอย่างอยู่ในที่เดียวดีมาก นอกจากนี้เดวิสยังกล่าวถึง 4 วิธีการแคชที่แตกต่างกันด้วย
Sampath

2
@Spikeh มันโหลดได้ดีสำหรับฉัน
user247702

1
@Stijn ขอบคุณไม่ได้โหลดเมื่อวันก่อน แต่กลับมาแล้ว :)
Spikeh

1
@sampath มันใช้งานได้แล้ว เมื่อวานดูเหมือนว่าไซต์ถูกแฮ็ก ขอบคุณสำหรับความช่วยเหลือของคุณ!
Baga

25

นี่คือบทความของ 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 จะบอกอย่างชัดเจนว่า:

หมายเหตุ: คลาสแคชไม่ได้มีไว้สำหรับใช้ภายนอกแอปพลิเคชัน ASP.NET ได้รับการออกแบบและทดสอบสำหรับใช้ใน ASP.NET เพื่อจัดทำแคชสำหรับเว็บแอปพลิเคชัน ในแอปพลิเคชันประเภทอื่นเช่นแอปพลิเคชันคอนโซลหรือแอปพลิเคชัน Windows Forms การแคช ASP.NET อาจทำงานไม่ถูกต้อง

คลาสสำหรับแคช ASP.NET คือ System.Web.Caching.Cache ใน System.Web.dll อย่างไรก็ตามคุณไม่สามารถสร้างวัตถุแคชขึ้นมาใหม่ได้ คุณต้องได้รับจาก System.Web.HttpRuntime.Cache

Cache cache = System.Web.HttpRuntime.Cache;

การทำงานกับแคช ASP.NET เป็นเอกสารใน MSDN ที่นี่

ข้อดี:

  1. มันอยู่ในตัว
  2. แม้จะมีไวยากรณ์ .NET 1.0 ก็ค่อนข้างง่ายกับการใช้งาน
  3. เมื่อใช้ในบริบทของเว็บจะได้รับการทดสอบอย่างดี นอกเหนือจากบริบทของเว็บตามการค้นหาของ Google มักไม่ทราบว่าก่อให้เกิดปัญหาแม้ว่า Microsoft จะแนะนำให้ต่อต้านก็ตามตราบใดที่คุณใช้. NET 2.0 หรือใหม่กว่า
  4. คุณสามารถรับการแจ้งเตือนผ่านผู้รับมอบสิทธิ์เมื่อมีการนำรายการออกซึ่งจำเป็นหากคุณต้องการให้มีชีวิตอยู่และคุณไม่สามารถกำหนดลำดับความสำคัญของรายการล่วงหน้าได้
  5. แต่ละรายการมีความยืดหยุ่นของ (a) (b) หรือ (c) วิธีการหมดอายุและการนำออกในรายการวิธีการนำออกที่ด้านบนของบทความนี้ คุณยังสามารถเชื่อมโยงพฤติกรรมการหมดอายุกับการมีอยู่ของฟิสิคัลไฟล์

จุดด้อย:

  1. ไม่เพียง แต่เป็นแบบคงที่มันมีเพียงคนเดียว คุณไม่สามารถสร้างประเภทของคุณเองด้วยอินสแตนซ์แบบคงที่ของแคช คุณสามารถมีที่เก็บข้อมูลเดียวสำหรับทั้งแอปช่วงเวลา คุณสามารถห่อที่เก็บข้อมูลด้วยกระดาษห่อของคุณเองซึ่งทำสิ่งต่างๆเช่นคำนำหน้าแบบฉีดล่วงหน้าในคีย์และลบคำนำหน้าเหล่านี้ออกเมื่อคุณดึงคู่คีย์ / ค่ากลับ แต่ยังมีเพียงถังเดียว ทุกอย่างรวมกันเป็นก้อน สิ่งนี้อาจสร้างความรำคาญอย่างแท้จริงหากคุณมีบริการที่ต้องแคชข้อมูลสามหรือสี่ประเภทแยกกัน นี่ไม่ควรเป็นปัญหาใหญ่สำหรับโครงการที่เรียบง่ายอย่างน่าสมเพช แต่ถ้าโปรเจ็กต์มีระดับความซับซ้อนอย่างมีนัยสำคัญเนื่องจากข้อกำหนดของมันแคช ASP.NET มักจะไม่เพียงพอ
  2. ไอเท็มสามารถหายไปโดยจำใจ. หลายคนไม่ทราบเรื่องนี้ - ฉันไม่ทราบจนกว่าฉันจะรีเฟรชความรู้เกี่ยวกับการใช้งานแคชนี้ โดยค่าเริ่มต้นแคช ASP.NET ได้รับการออกแบบมาเพื่อทำลายรายการเมื่อ "รู้สึก" เช่นนั้น โดยเฉพาะอย่างยิ่งโปรดดู (c) ในคำจำกัดความของตารางแคชที่ด้านบนของบทความนี้ หากเธรดอื่นในกระบวนการเดียวกันกำลังทำงานกับสิ่งที่แตกต่างไปจากเดิมอย่างสิ้นเชิงและมันทิ้งรายการที่มีลำดับความสำคัญสูงลงในแคชทันทีที่. NET ตัดสินใจว่าจำเป็นต้องใช้หน่วยความจำบางส่วนมันจะเริ่มทำลายบางรายการในแคชตาม ลำดับความสำคัญของพวกเขาลำดับความสำคัญต่ำก่อน ตัวอย่างทั้งหมดที่บันทึกไว้ในที่นี้สำหรับการเพิ่มรายการแคชใช้ลำดับความสำคัญเริ่มต้นแทนที่จะเป็นค่าลำดับความสำคัญ NotRemovable ซึ่งป้องกันไม่ให้ถูกลบออกเพื่อวัตถุประสงค์ในการล้างหน่วยความจำ แต่จะยังคงลบออกตามนโยบายการหมดอายุ
  3. คีย์ต้องเป็นสตริง ตัวอย่างเช่นหากคุณกำลังแคชเรกคอร์ดข้อมูลที่เร็กคอร์ดถูกคีย์เป็น long หรือจำนวนเต็มคุณต้องแปลงคีย์เป็นสตริงก่อน
  4. ไวยากรณ์ไม่อัปเดต มันเป็นไวยากรณ์. NET 1.0 แม้จะผิดกว่า ArrayList หรือ Hashtable ก็ตาม ไม่มีชื่อสามัญที่นี่ไม่มีอินเทอร์เฟซ IDictionary <> ไม่มีวิธีการประกอบด้วย () ไม่มีการรวบรวมคีย์ไม่มีเหตุการณ์มาตรฐาน มันมีเฉพาะเมธอด Get () บวกกับตัวสร้างดัชนีที่ทำสิ่งเดียวกับ Get () โดยส่งคืนค่าว่างหากไม่มีการจับคู่บวก Add (), Insert () (ซ้ำซ้อน?), Remove () และ GetEnumerator () .
  5. ละเว้นหลักการ DRYในการตั้งค่าพฤติกรรมการหมดอายุ / การนำออกเริ่มต้นเพื่อให้คุณลืมสิ่งเหล่านี้ได้ คุณต้องบอกแคชอย่างชัดเจนว่าคุณต้องการให้รายการที่คุณเพิ่มนั้นหมดอายุหรือถูกลบออกทุกครั้งที่คุณเพิ่มเพิ่มรายการ
  6. ไม่มีวิธีใดในการเข้าถึงรายละเอียดการแคชของรายการที่แคชเช่นการประทับเวลาของเวลาที่เพิ่ม Encapsulation ไปที่นี่เล็กน้อยทำให้ยากที่จะใช้แคชเมื่ออยู่ในโค้ดที่คุณกำลังพยายามพิจารณาว่ารายการที่แคชควรจะไม่ถูกต้องกับกลไกการแคชอื่น (เช่นการรวบรวมเซสชัน) หรือไม่
  7. เหตุการณ์การนำออกจะไม่ถูกเปิดเผยว่าเป็นเหตุการณ์และต้องติดตามเมื่อเพิ่ม
  8. และถ้าฉันยังไม่ได้พูดเพียงพอMicrosoft ขอแนะนำอย่างชัดเจนนอกเว็บ และหากคุณถูกสาปด้วย. NET 1.1 คุณไม่ควรใช้มันด้วยความมั่นใจในความเสถียรใด ๆ เลยนอกเว็บดังนั้นอย่าไปกังวล

ObjectCache / MemoryCache ของ. NET 4.0

ในที่สุด Microsoft ก็ใช้คลาส ObjectCache แบบนามธรรมใน. NET Framework เวอร์ชันล่าสุดและการใช้งาน MemoryCache ที่สืบทอดและใช้ ObjectCache เพื่อวัตถุประสงค์ในหน่วยความจำในการตั้งค่าที่ไม่ใช่เว็บ

System.Runtime.Caching.ObjectCache อยู่ในแอสเซมบลี System.Runtime.Caching.dll เป็นคลาสนามธรรมที่ประกาศโดยพื้นฐานแล้วว่าอินเตอร์เฟสสไตล์. NET 1.0 เดียวกันกับที่พบในแคช ASP.NET System.Runtime.Caching.MemoryCacheเป็นการนำ ObjectCache มาใช้ในหน่วยความจำและคล้ายกับแคช 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 ได้

    หมายเหตุ: มันไม่จำเป็นต้องเป็นแบบคงที่ แต่มันควรจะเป็นนั่นคือคำแนะนำของไมโครซอฟท์ (ดูข้อควรระวังสีเหลือง)

  3. มีการปรับปรุงเล็กน้อยเมื่อเทียบกับอินเทอร์เฟซของแคช ASP.NET เช่นความสามารถในการสมัครรับเหตุการณ์การลบโดยไม่จำเป็นต้องอยู่ที่นั่นเมื่อมีการเพิ่มรายการการแทรกที่ซ้ำซ้อน () ถูกลบออกรายการสามารถเพิ่มได้ด้วย CacheItem วัตถุที่มีตัวเริ่มต้นที่กำหนดกลยุทธ์การแคชและมีการเพิ่ม ()

จุดด้อย:

  1. ยังเสริมความดรายได้ไม่เต็มที่ จากประสบการณ์เพียงเล็กน้อยของฉันคุณยังไม่สามารถตั้งค่า TimeSpan หมดอายุของเลื่อนเพียงครั้งเดียวและลืมมันไป และตรงไปตรงมาแม้ว่านโยบายในตัวอย่างการเพิ่มรายการด้านบนจะอ่านได้ง่ายกว่า แต่ก็จำเป็นต้องใช้คำฟุ่มเฟือยอย่างน่ากลัว
  2. มันยังไม่ได้คีย์ทั่วไป ต้องใช้สตริงเป็นคีย์ ดังนั้นคุณจึงไม่สามารถจัดเก็บได้นานหรือ int หากคุณกำลังแคชระเบียนข้อมูลเว้นแต่คุณจะแปลงเป็นสตริง

DIY: สร้างด้วยตัวคุณเอง

จริงๆแล้วมันค่อนข้างง่ายที่จะสร้างพจนานุกรมการแคชที่มีการหมดอายุอย่างชัดเจนหรือเลื่อน (มันจะยากขึ้นมากถ้าคุณต้องการให้รายการถูกลบโดยอัตโนมัติเพื่อจุดประสงค์ในการล้างหน่วยความจำ) นี่คือสิ่งที่คุณต้องทำ:

  1. สร้างคลาสคอนเทนเนอร์ค่าที่เรียกว่า Expiring หรือ Expired ซึ่งจะมีค่าประเภท T คุณสมบัติ TimeStamp ของประเภท DateTime เพื่อจัดเก็บเมื่อค่าถูกเพิ่มลงในแคชและ TimeSpan ที่จะระบุระยะห่างจากการประทับเวลานั้น รายการควรหมดอายุ สำหรับการหมดอายุอย่างชัดเจนคุณสามารถแสดงตัวตั้งค่าคุณสมบัติที่ตั้งค่า TimeSpan ที่กำหนดวันที่ลบด้วยการประทับเวลา
  2. สร้างคลาสเรียกมันว่า ExpiredItemsDictionary ที่ใช้ IDictionary ฉันต้องการทำให้เป็นคลาสทั่วไปที่กำหนดโดยผู้บริโภค
  3. ในคลาสที่สร้างใน # 2 ให้เพิ่ม Dictionary> เป็นคุณสมบัติและเรียกมันว่า InnerDictionary
  4. การนำไปใช้ถ้า IDictionary ในคลาสที่สร้างใน # 2 ควรใช้ InnerDictionary เพื่อจัดเก็บรายการแคช การห่อหุ้มจะซ่อนรายละเอียดวิธีการแคชผ่านอินสแตนซ์ของประเภทที่สร้างใน # 1 ด้านบน
  5. ตรวจสอบให้แน่ใจว่าตัวสร้างดัชนี (นี้ []), มีคีย์ () ฯลฯ ระมัดระวังในการล้างรายการที่หมดอายุและนำรายการที่หมดอายุออกก่อนที่จะส่งคืนค่า คืนค่า null ใน getters หากรายการถูกลบ
  6. ใช้เธรดล็อกกับ getters, setters, containsKey () และโดยเฉพาะอย่างยิ่งเมื่อเคลียร์ไอเท็มที่หมดอายุ
  7. เพิ่มเหตุการณ์เมื่อใดก็ตามที่ไอเท็มถูกลบเนื่องจากการหมดอายุ
  8. เพิ่มอินสแตนซ์ System.Threading.Timer และปรับแต่งระหว่างการเริ่มต้นเพื่อลบรายการที่หมดอายุโดยอัตโนมัติทุกๆ 15 วินาที นี่เป็นลักษณะการทำงานเดียวกันกับแคช ASP.NET
  9. คุณอาจต้องการเพิ่มรูทีน AddOrUpdate () ที่ดันการหมดอายุของการเลื่อนออกโดยการแทนที่การประทับเวลาบนคอนเทนเนอร์ของรายการ (อินสแตนซ์การหมดอายุ) หากมีอยู่แล้ว

Microsoft ต้องสนับสนุนการออกแบบดั้งเดิมเนื่องจากฐานผู้ใช้สร้างการพึ่งพา แต่ไม่ได้หมายความว่าเป็นการออกแบบที่ดี

ข้อดี:

  1. คุณสามารถควบคุมการนำไปใช้งานได้อย่างสมบูรณ์
  2. สามารถเสริมสร้าง DRYโดยการตั้งค่าพฤติกรรมการแคชเริ่มต้นจากนั้นเพียงแค่วางคู่คีย์ / ค่าลงในโดยไม่ต้องประกาศรายละเอียดการแคชทุกครั้งที่คุณเพิ่มรายการ
  3. สามารถใช้อินเทอร์เฟซที่ทันสมัยได้แก่IDictionary<K,T>. สิ่งนี้ทำให้ง่ายต่อการบริโภคเนื่องจากอินเทอร์เฟซสามารถคาดเดาได้มากขึ้นในฐานะอินเทอร์เฟซพจนานุกรมนอกจากนี้ยังช่วยให้สามารถเข้าถึงผู้ช่วยเหลือและวิธีการขยายที่ทำงานกับ IDictionary <> ได้มากขึ้น
  4. รายละเอียดการแคชสามารถไม่มีการเข้ารหัสได้เช่นโดยการเปิดเผย InnerDictionary ของคุณผ่านคุณสมบัติแบบอ่านอย่างเดียวแบบสาธารณะทำให้คุณสามารถเขียนการทดสอบหน่วยที่ชัดเจนกับกลยุทธ์การแคชของคุณรวมทั้งขยายการใช้งานแคชพื้นฐานของคุณด้วยกลยุทธ์การแคชเพิ่มเติมที่สร้างขึ้น
  5. แม้ว่าจะไม่จำเป็นต้องเป็นอินเทอร์เฟซที่คุ้นเคยสำหรับผู้ที่ทำให้ตัวเองคุ้นเคยกับไวยากรณ์สไตล์. NET 1.0 ของแคช ASP.NET หรือ Caching Application Block แต่คุณสามารถกำหนดอินเทอร์เฟซให้มีลักษณะตามที่คุณต้องการได้
  6. สามารถใช้คีย์ประเภทใดก็ได้ นี่เป็นสาเหตุหนึ่งที่ทำให้เกิดยาชื่อสามัญ ไม่ใช่ทุกอย่างที่ควรคีย์ด้วยสตริง

จุดด้อย:

  1. ไม่ได้คิดค้นโดยหรือรับรองโดย Microsoftดังนั้นจึงไม่มีการรับรองคุณภาพเช่นเดียวกัน
  2. สมมติว่ามีการใช้เฉพาะคำแนะนำที่ฉันอธิบายไว้ข้างต้นเท่านั้นไม่ได้ "จงใจ" ล้างรายการสำหรับการล้างหน่วยความจำตามลำดับความสำคัญ (ซึ่งเป็นฟังก์ชันยูทิลิตี้ในกรณีที่มุมของแคชอยู่แล้ว .. ซื้อ RAM ที่คุณจะใช้แคช , แรมถูก).

ในบรรดาสี่ตัวเลือกเหล่านี้นี่คือความชอบของฉัน ฉันได้ใช้โซลูชันการแคชขั้นพื้นฐานนี้แล้ว จนถึงตอนนี้ดูเหมือนว่าจะทำงานได้อย่างสมบูรณ์ไม่มีจุดบกพร่องที่เป็นที่รู้จัก (โปรดติดต่อฉันด้วยความคิดเห็นด้านล่างหรือที่ jon-at-jondavis ถ้ามี !!) และฉันตั้งใจจะใช้มันในโครงการขนาดเล็กทั้งหมดของฉันที่ต้องการ แคชพื้นฐาน นี่คือ:

ลิงค์ Github: https://github.com/kroimon/ExpantedItemDictionary

ลิงก์เก่า: ExpiredItemDictionary.zip

ควรค่าแก่การกล่าวถึง: AppFabric, NoSQL, Et Al

โปรดสังเกตว่าชื่อบทความของบล็อกนี้ระบุว่า“ Simple Caching” ไม่ใช่“ Heavy-Duty Caching” หากคุณต้องการทำสิ่งที่ต้องใช้งานหนักคุณควรมองหาโซลูชันที่ทุ่มเทและขยายขนาดออกไป



3

MemoryCache คือสิ่งที่บอกว่ามันคือแคชที่เก็บไว้ในหน่วยความจำ

HttpRuntime.Cache (ดูhttp://msdn.microsoft.com/en-us/library/system.web.httpruntime.cache(v=vs.100).aspxและhttp://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


1
อืมไม่แน่ใจว่าลิงค์ที่สองไม่ทำให้เข้าใจผิดหรือเปล่าเพราะมีการพูดถึง OutputCache และการใช้งาน OutputCacheProvider
Giedrius

หืมฉันไม่พบที่ที่จะบอกว่าคุณสามารถคง System.Web.Caching.Cache โดยใช้การกำหนดค่าที่แตกต่างกัน
Giedrius

2

MemoryCache.Default ยังสามารถใช้เป็น "สะพาน" ได้หากคุณกำลังย้ายแอป ASP.NET MVC แบบคลาสสิกไปยัง ASP.NET Core เนื่องจากไม่มี "System.Web.Caching" และ "HttpRuntime" ใน Core

ฉันยังเขียนเกณฑ์มาตรฐานขนาดเล็กเพื่อจัดเก็บboolรายการ 20,000 ครั้ง (และเกณฑ์มาตรฐานอื่นเพื่อดึงข้อมูล) และ MemoryCache ดูเหมือนว่าจะช้าลงสองเท่า (27ms เทียบกับ 13ms - ซึ่งรวมสำหรับการทำซ้ำทั้งหมด 20k) แต่ทั้งสองอย่างเร็วมากและสิ่งนี้ อาจถูกเพิกเฉย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.