1. แคชแคชคืออะไร
คำว่าแคชครั้งแรกมาจากการออกแบบ CPU
เมื่อซีพียูต้องการอ่านข้อมูลก่อนอื่นจะค้นหาจากแคช CPU และอ่านทันทีและส่งไปยัง CPU เพื่อประมวลผลหากพบ หากไม่พบมันจะถูกอ่านจากหน่วยความจำที่ค่อนข้างช้าและส่งไปยัง CPU สำหรับการประมวลผล ในเวลาเดียวกันบล็อกข้อมูลที่ข้อมูลนี้ถูกเรียกเข้าสู่แคชเพื่อให้บล็อกข้อมูลทั้งหมดสามารถอ่านได้จากแคชในอนาคตโดยไม่ต้องโทรหน่วยความจำ มันเป็นกลไกการอ่านที่ทำให้อัตราการตีแคช CPU สูงมาก (ซีพียูส่วนใหญ่สามารถเข้าถึงได้ประมาณ 90%) ซึ่งหมายความว่า 90% ของข้อมูล CPU จะอ่านในครั้งต่อไปอยู่ในแคช CPU และต้องอ่านเพียงประมาณ 10% จากหน่วยความจำ สิ่งนี้จะช่วยประหยัดเวลา CPU ในการอ่านหน่วยความจำโดยตรงและทำให้ CPU เป็นไปไม่ได้ที่จะอ่านข้อมูลโดยไม่ต้องรอ โดยทั่วไปลำดับที่ CPU อ่านข้อมูลจะถูกแคชก่อนและจากนั้นหน่วยความจำ
ต่อมาเราไปที่แคชฮาร์ดดิสก์ก่อนจากนั้นไปที่แอปพลิเคชันแคชแคชเบราว์เซอร์แคชเว็บ ฯลฯ !
แคชเป็นราชา! -
แคชสปริง
Spring Cache เป็นชุดโซลูชั่นแคชแอปพลิเคชันที่สมบูรณ์แบบที่กำหนดโดยแอปพลิเคชันฤดูใบไม้ผลิ
Spring Cache เองไม่ได้ให้การใช้งานแคช แต่ใช้อินเทอร์เฟซแบบครบวงจรและข้อกำหนดรหัสการกำหนดค่าคำอธิบายประกอบ ฯลฯ เพื่อให้คุณสามารถใช้แคชต่างๆในแอปพลิเคชันฤดูใบไม้ผลิโดยไม่ต้องใส่ใจในรายละเอียดของแคชมากเกินไป ด้วยสปริงแคชคุณสามารถใช้งานได้อย่างง่ายดาย
การใช้งานแคชต่างๆรวมถึงพร้อมกัน Map, Ehcache 2.x, JCache, Redis ฯลฯ
คำจำกัดความของแคชในฤดูใบไม้ผลิ
คำจำกัดความของแคชในฤดูใบไม้ผลิรวมถึงในอินเตอร์เฟส org.springframework.cache.cache
ส่วนใหญ่ให้วิธีการต่อไปนี้
// รับค่าตามคีย์ที่ระบุ <t> t get (คีย์วัตถุ, คลาส <t> ประเภท) // บันทึกค่าที่ระบุไปยังแคชตาม void คีย์ที่สอดคล้องกันใส่ (คีย์วัตถุ, ค่าวัตถุ); // รีไซเคิลค่าที่ระบุ
ไม่ยากที่จะเห็นจากคำจำกัดความที่ว่าแคชเป็นโครงสร้างคีย์-ค่า เราใช้ค่าที่สอดคล้องกันผ่านคีย์ที่ระบุ
Cache Manager
แคชเป็นชุดของค่าคีย์ แต่ในโครงการของเราอาจมีแคชที่แตกต่างกันของหัวข้อธุรกิจต่าง ๆ เช่นแคชผู้ใช้แคชแผนก ฯลฯ แคชเหล่านี้แยกกันอย่างมีเหตุผล เพื่อที่จะแยกแยะแคชเหล่านี้ org.springframework.cache.cachemanager มีไว้เพื่อจัดการแคชต่างๆ อินเทอร์เฟซนี้มีเพียงสองวิธีเท่านั้น
// รับแคชของหัวข้อที่เกี่ยวข้องตามชื่อแคช getCache (ชื่อสตริง); // รับแคชของคอลเลกชันหัวข้อทั้งหมด <String> getCachenames ();
ในอินเทอร์เฟซนี้การเพิ่มและการลบการดำเนินการจะไม่ได้รับอนุญาตให้ดำเนินการกับแคช การดำเนินการเหล่านี้ควรจะเสร็จสิ้นภายในโดยการใช้งาน cachemanager ต่างๆและไม่ควรเปิดเผย
แคชที่ใช้คำอธิบายประกอบ
ในทางทฤษฎีการดำเนินการแคชของข้อมูลไม่เกี่ยวข้องกับธุรกิจมากนัก เราควรแยกการดำเนินการอ่านและเขียนของแคชออกจากตรรกะรหัสหลัก วิธีการแยกสปริงขึ้นอยู่กับคำอธิบายประกอบ (แน่นอนเช่น JSR-107 ฯลฯ ก็ขึ้นอยู่กับคำอธิบายประกอบ)
ฤดูใบไม้ผลิมีชุดคำอธิบายประกอบรวมถึง @Cacheable, @CachePut, @CacheEvict และคำอธิบายประกอบอื่น ๆ เพื่อลดความซับซ้อนของการทำงานของแคชของเรา คำอธิบายประกอบเหล่านี้อยู่ในแพ็คเกจ org.springframework.cache.annotation
2. ตัวอย่าง
ตัวอย่างง่ายๆของการใช้สปริงบูตโดยใช้สปริงแคช
มาสร้างตัวอย่างโดยใช้สปริงบูตแคชทีละขั้นตอน
สร้างโครงการสปริงบูตใหม่และแนะนำการพึ่งพาต่อไปนี้
<การพึ่งพา> <การพึ่งพา> <roupId> org.springframework.boot </groupId> <ratifactid> Spring-Boot-Starter-Cache </artifactid> </dependency> <การพึ่งพา> <roupid> org.springframework.boot </groupid> <RoupID> org.springframework.boot </groupid> <ratifactid> การทดสอบสปริง-สตาร์เทสต์ </artifactid> <scope> ทดสอบ </cope>
ในหมู่พวกเขา-สปริง-สตาร์เทอร์-แคชคือการพึ่งพาคีย์ของแคช
แก้ไขคลาสแอปพลิเคชันและเพิ่มคำอธิบายประกอบที่เปิดใช้งาน CACHE @ENABLECACHING
@springbootapplication@enablecachingpublic คลาส cachesimpleapplication {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {springapplication.run (cachesimpleapplication.class, args); -@EnableCache คำอธิบายประกอบเริ่มกลไกการแคชของ Spring ซึ่งจะช่วยให้แอปพลิเคชันสามารถตรวจจับคำอธิบายประกอบที่เกี่ยวข้องกับแคชทั้งหมดและเริ่มทำงาน นอกจากนี้ยังจะสร้างถั่ว cachemanager ที่สามารถฉีดและใช้งานโดยแอปพลิเคชันของเรา
สร้างคลาส RestController ใหม่
@restcontroller @requestmapping ("/") คลาสสาธารณะ cachecontroller {@autowired ส่วนตัว cachetestservice cachetestservice; / ** * รับข้อมูลตาม ID * * @param id * @return */ @getMapping ("{id}") การทดสอบสตริงสาธารณะ (@PathVariable ("id") id id) {return cachetestService.get (id); } / ** * ลบข้อมูลเกี่ยวกับ ID * * @param id * @return * / @deletemapping ("{id}") การลบสตริงสาธารณะ (@PathVariable ("id") id id) {return cachetestService.delete (id); } / ** * บันทึกข้อมูลเกี่ยวกับ ID * * @param id * @return * / @postmapping สตริงสาธารณะบันทึก (@requestparam ("id") id id, @requestparam ("value") ค่าสตริง) {return cachetestservice.save (id, value); } / ** * ข้อมูลเกี่ยวกับ ID ใหม่ * * @param id * @return * / @putMapping ("{id}") การอัปเดตสตริงสาธารณะ (@PathVariable ("id") สตริง @RequestParam ("ค่า") ค่าสตริง) -คลาสนี้เรียกใช้บริการเพื่อใช้การดำเนินการจริงของการเพิ่มลบแก้ไขและตรวจสอบ
การใช้บริการ
ต่อไปเราต้องการใช้บริการของเรา
@ServicePublic คลาส SimpleCachetestServiceImpl ใช้ cachetestService {ส่วนตัว logger logger สุดท้ายคงที่ = loggerFactory.getLogger (SimpleCachetestServiceImpl.class); แผนที่สุดท้ายส่วนตัว <สตริงสตริง> เอนทิตี = ใหม่ hashmap <> (); Public SimpleCachetestServiceImpl () {entities.put ("1", "นี่คือหมายเลข 1"); } @autowired cachemanager ส่วนตัว cachemanager; @Override @Cacheable (cachenames = "test") สตริงสาธารณะรับ (string id) {// บันทึกเวลาของการสร้างข้อมูลใช้เพื่อทดสอบและเปรียบเทียบเวลายาว = new date (). getTime (); // พิมพ์ cachemanager logger.info ("The CacheManager คือ" + CacheManager); // พิมพ์ logger.info ("รับค่าโดย id =" + id + "เวลาคือ" + เวลา); ส่งคืน "รับค่าโดย id =" + id + "ค่าคือ" + entities.get (id); } @Override สตริงสาธารณะลบ (รหัสสตริง) {return entities.remove (id); } @Override สตริงสาธารณะบันทึก (รหัสสตริง, ค่าสตริง) {logger.info ("บันทึกค่า" + ค่า + "ด้วยคีย์" + id); entities.put (id, value); ค่าส่งคืน; } @Override การอัปเดตสตริงสาธารณะ (รหัสสตริง, ค่าสตริง) {return entities.put (id, value); -แคช
ก่อนอื่นให้เพิ่มคำอธิบายประกอบ @Cacheable ลงในวิธี GET และเรียกใช้การทดสอบรหัส
เราใช้บุรุษไปรษณีย์สำหรับการทดสอบที่อยู่ทดสอบคือ http: // localhost: 8080/1, เบราว์เซอร์ตอบสนองเพื่อรับค่าโดย id = 1 ค่า ISHIS NO 1, เซิร์ฟเวอร์คอนโซลพิมพ์สองบรรทัดของบันทึก
รับค่าโดย id = 1 ค่านี้คือหมายเลข 1 รับค่าโดย id = 1 เวลาคือ 1516004770216
แต่เมื่อเรารีเฟรชที่อยู่เบราว์เซอร์อีกครั้งเบราว์เซอร์จะกลับมาตามปกติ แต่คอนโซลจะไม่พิมพ์อีกต่อไป เหตุผลก็คือเมื่อเราเรียกมันว่าครั้งที่สองสปริงจะไม่ดำเนินการวิธีการอีกต่อไป แต่ได้รับค่าแคชโดยตรง แคชสปริงแคชค่าส่งคืนของฟังก์ชั่นเป็นคีย์ในแคชที่มีชื่อว่าการทดสอบ
ที่นี่เราใช้คำอธิบายประกอบ @cacheable และ cachenames ในคำอธิบายประกอบระบุว่าแคชที่อ่านได้ที่นี่ ที่นี่เราจะค้นหาวัตถุแคชที่คีย์คือรหัสใน cachename = "ทดสอบ"
ลบข้อมูลที่แคช
ในโปรแกรมข้างต้นหากเราลบค่าที่ระบุผ่านคำขอลบและส่งคำขอลบไปยัง http: // localhost: 8080/1 ในเวลานี้ค่าจะถูกลบออกจากแผนที่ แต่เมื่อเราได้รับคำขอ http: // localhost: 8080/1 นี่เป็นเพราะเมื่อเราลบข้อมูลเราไม่ได้ลบข้อมูลในแคช ในวิธีการก่อนหน้านี้ผลการดำเนินการของวิธีการยังคงถูกบันทึกไว้ ฤดูใบไม้ผลิจะไม่อ่านอีกครั้ง แต่จะอ่านแคชโดยตรง ในเวลานี้เราเพิ่มคำอธิบายประกอบก่อนวิธีการ
@override@cacheevict (cachenames = "test") การลบสตริงสาธารณะ (string id) {return entities.remove (id);}หลังจากการทดสอบการโทรครั้งแรกการร้องขอ GET ค่าส่งคืนจะแสดงอย่างถูกต้องเป็นค่า GET โดย ID = 1 ค่าคือ 1
จากนั้นโทรขอลบคำขอ ลบข้อมูลออกจากแคชและแผนที่และโทรขอขออีกครั้ง ในเวลานี้ค่า GET โดย ID = 1 ค่าเป็นโมฆะซึ่งหมายความว่าค่าได้ถูกลบออกจากแคชอย่างแน่นอน
ที่นี่เราใช้คำอธิบายประกอบ @cacheevict Cachenames ระบุว่าข้อมูลแคชใดที่จะลบ โดยค่าเริ่มต้นพารามิเตอร์เมธอดจะถูกใช้เป็นคีย์ที่ถูกลบ
อัปเดตแคช
เมื่อโปรแกรมมาถึงจุดนี้หากเราเรียกใช้การร้องขอโพสต์ร่างกายคำขอคือ id = 1 & value = new1 ในเวลานี้คอนโซลจะบันทึกค่าใหม่ค่า 1 ด้วยคีย์ 1 และรหัสจะบันทึกค่าไปยังแผนที่ แต่เมื่อเราเรียกใช้คำขอ GET เราจะพบว่าค่าส่งคืนยังคงอยู่ในสถานะก่อนหน้า นี่คือสิ่งที่เราสามารถใช้ได้
@override@cacheput (cachenames = "test", key = "#id") สตริงสาธารณะบันทึก (รหัสสตริง, ค่าสตริง) {logger.info ("บันทึกค่า" + value + "ด้วยคีย์" + id); return entities.put (id, value);}เรียกใช้รหัสอีกครั้งก่อนอื่นเราส่งคำขอลบเพื่อลบข้อมูลออกจากแผนที่และแคช จากนั้นส่งคำขอโพสต์และเขียนข้อมูลไปยังแผนที่ สุดท้ายหากคุณส่งคำขอ GET คุณจะพบว่าสามารถเรียกคืนค่าได้อย่างถูกต้องและคอนโซลไม่ได้พิมพ์บันทึกของข้อมูลที่ได้จากแผนที่
มีการใช้คำอธิบายประกอบ @CachePut ที่นี่ ฟังก์ชั่นของคำอธิบายประกอบนี้คือการเขียนค่าส่งคืนของวิธีลงในแคชที่ระบุโดย Cachenames ตามคีย์ที่กำหนด
ในทำนองเดียวกันเราจำเป็นต้องเพิ่มคำอธิบายประกอบ @CachePut ลงในวิธีการวางเพื่อให้การดัดแปลงสามารถรีเฟรชข้อมูลแคช
ณ จุดนี้แอปพลิเคชันแคชอย่างง่ายรวมถึงการเพิ่มการลบการดัดแปลงและการสืบค้นจะเสร็จสมบูรณ์
3. ประเด็นสำคัญ
บันทึกย่อสองสามฉบับ
สังเกต
@Cacheable และ @CachePut จะนำผลการดำเนินการของวิธีลงในแคชตามคีย์ที่ระบุ เมื่อ @Cacheable ถูกดำเนินการก่อนจะตรวจพบว่ามีข้อมูลในแคชหรือไม่ ถ้าเป็นเช่นนั้นจะอ่านโดยตรงจากแคช ถ้าไม่ดำเนินการวิธีการและใส่ค่าส่งคืนลงในแคช @CachePut จะดำเนินการวิธีการก่อนจากนั้นเขียนผลลัพธ์การดำเนินการไปยังแคช วิธีการใช้ @CachePut จะถูกดำเนินการอย่างแน่นอน
รหัสตัวอย่างที่สมบูรณ์อยู่ที่ https://github.com/ldwqh0/cache-test
สรุป
ด้านบนเป็นวิธีการใช้แคชแคชในการบูตสปริงแนะนำโดยตัวแก้ไข ฉันหวังว่ามันจะเป็นประโยชน์กับคุณ หากคุณมีคำถามใด ๆ โปรดฝากข้อความถึงฉันและบรรณาธิการจะตอบกลับคุณทันเวลา ขอบคุณมากสำหรับการสนับสนุนเว็บไซต์ Wulin.com!