Spring Boot Redis Cache
في هذا المنشور، سنقوم بإعداد تطبيق عيني لـ Spring Boot ودمجه مع ذاكرة التخزين المؤقتة Redis. في حين أن Redis هو متجر بيانات في الذاكرة مفتوح المصدر، يُستخدم كقاعدة بيانات وكمخزن ذاكرة مؤقتة ووسيط رسائل، ستظهر هذه الدرس فقط التكامل مع التخزين المؤقت. سنستخدم أداة Spring Initializr لإعداد المشروع بسرعة.
إعداد مشروع Spring Boot Redis
سنستخدم أداة Spring Initializr لإعداد المشروع بسرعة. سنستخدم 3 تبعيات كما هو موضح أدناه: قم بتنزيل المشروع وفك الضغط عنه. لقد استخدمنا تبعية قاعدة بيانات H2 حيث سنستخدم قاعدة بيانات مضمنة تفقد جميع البيانات بمجرد إيقاف التطبيق.
تبعيات تخزين مؤقت Redis Cache Maven Dependencies ل Spring Boot
رغم أننا قمنا بالفعل بإكمال الإعداد باستخدام الأداة، إذا كنت ترغب في إعدادها يدويًا، نستخدم نظام تجميع Maven لهذا المشروع وفيما يلي التبعيات التي استخدمناها:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- for JPA support -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- for embedded database support -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
تأكد من استخدام الإصدار الثابت لـ Spring Boot من المركز المركزي لـ Maven.
تحديد النموذج
لحفظ كائن في قاعدة بيانات Redis، نقوم بتعريف كائن نموذج شخص بحقول أساسية:
package com.journaldev.rediscachedemo;
import javax.persistence.*;
import java.io.Serializable;
@Entity
public class User implements Serializable {
private static final long serialVersionUID = 7156526077883281623L;
@Id
@SequenceGenerator(name = "SEQ_GEN", sequenceName = "SEQ_USER", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_GEN")
private Long id;
private String name;
private long followers;
public User() {
}
public User(String name, long followers) {
this.name = name;
this.followers = followers;
}
//معيار الجلالة والمجاعين
@Override
public String toString() {
return String.format("User{id=%d, name='%s', followers=%d}", id, name, followers);
}
}
إنها POJO قياسية مع الجلالة والمجاعين.
تكوين تخزين مؤقت Redis
مع Spring Boot والتبعية المطلوبة بالفعل في العمل مع Maven، يمكننا تكوين نسخة Redis المحلية بثلاثة أسطر فقط في ملف application.properties كالتالي:
# تكوين Redis
spring.cache.type=redis
spring.redis.host=localhost
spring.redis.port=6379
كما يجب استخدام تعليق @EnableCaching
على فئة Spring Boot الرئيسية:
package com.journaldev.rediscachedemo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
@EnableCaching
public class Application implements CommandLineRunner {
private final Logger LOG = LoggerFactory.getLogger(getClass());
private final UserRepository userRepository;
@Autowired
public Application(UserRepository userRepository) {
this.userRepository = userRepository;
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
public void run(String... strings) {
//تعبئة قاعدة البيانات المضمنة هنا
LOG.info("Saving users. Current user count is {}.", userRepository.count());
User shubham = new User("Shubham", 2000);
User pankaj = new User("Pankaj", 29000);
User lewis = new User("Lewis", 550);
userRepository.save(shubham);
userRepository.save(pankaj);
userRepository.save(lewis);
LOG.info("Done saving users. Data: {}.", userRepository.findAll());
}
}
لقد قمنا بإضافة CommandLineRunner حيث نرغب في ملء بعض البيانات العينية في قاعدة بيانات H2 المضمنة.
تحديد المستودع
قبل أن نوضح كيف يعمل Redis ، سنقوم فقط بتحديد مستودع لوظائف JPA ذات الصلة:
package com.journaldev.rediscachedemo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository { }
ليس لديها استدعاءات الطرود حاليًا لأننا لا نحتاج إليها.
تحديد المتحكم
المتحكمون هم المكان الذي يتم فيه استدعاء ذاكرة التخزين المؤقتة لـ Redis للعمل. في الواقع ، هذا هو أفضل مكان للقيام بذلك لأن ذاكرة التخزين المؤقتة مرتبطة مباشرة بها ، لذا لن يكون على الطلب أن يدخل حتى في كود الخدمة لانتظار النتائج المخزنة في الذاكرة المؤقتة. فيما يلي هيكل المتحكم:
package com.journaldev.rediscachedemo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.*;
@RestController
public class UserController {
private final Logger LOG = LoggerFactory.getLogger(getClass());
private final UserRepository userRepository;
@Autowired
public UserController(UserRepository userRepository) {
this.userRepository = userRepository;
}
...
}
الآن ، لوضع شيء في الذاكرة المؤقتة ، نستخدم تعليق @Cacheable
:
@Cacheable(value = "users", key = "#userId", unless = "#result.followers < 12000")
@RequestMapping(value = "/{userId}", method = RequestMethod.GET)
public User getUser(@PathVariable String userId) {
LOG.info("Getting user with ID {}.", userId);
return userRepository.findOne(Long.valueOf(userId));
}
في الربط أعلاه ، سيقوم الطريق بوضع شخص في ذاكرة مؤقتة باسم ‘المستخدمين’ ، ويحدد هذا الشخص بمفتاح ‘معرف المستخدم’ وسيقوم بتخزين مستخدم فقط لديه أتباع أكثر من 12000. وهذا يتأكد من أن الذاكرة المؤقتة ممتلئة بالمستخدمين الذين هم شهيرين جدًا ويتم استعلامهم في كثير من الأحيان. أيضًا ، لقد أضفنا بشكل متعمد عبارة تسجيل في استدعاء واجهة برمجة التطبيق. دعونا نقوم ببعض الاستدعاءات لواجهة برمجة التطبيق من Postman في هذه اللحظة. إليك الاستدعاءات التي قمنا بها:
localhost:8090/1
localhost:8090/1
localhost:8090/2
localhost:8090/2
إذا لاحظنا السجلات ، ستكون كالتالي:
... : Getting user with ID 1.
... : Getting user with ID 1.
... : Getting user with ID 2.
لاحظ شيئا؟ قمنا بعمل أربع استدعاءات API ولكن كانت هناك ثلاثة بيانات تسجيل فقط. هذا لأن المستخدم ذو الهوية 2 لديه 29000 متابع، لذلك، تم تخزين بياناته في الذاكرة المؤقتة. وهذا يعني أنه عندما تمت استدعاء API له، تمت استعادة البيانات من الذاكرة المؤقتة ولم يتم عمل استدعاء لقاعدة البيانات لهذا!
تحديث الذاكرة المؤقتة
يجب أيضًا تحديث قيم الذاكرة المؤقتة عند تحديث قيم كائناتها الفعلية. يمكن القيام بذلك باستخدام تعليق @CachePut:
@CachePut(value = "users", key = "#user.id")
@PutMapping("/update")
public User updatePersonByID(@RequestBody User user) {
userRepository.save(user);
return user;
}
بهذا، يتم تحديث شخص مرة أخرى بواسطة هويته وتحديث النتائج.
مسح الذاكرة المؤقتة
إذا كان هناك بعض البيانات التي يجب حذفها من قاعدة البيانات الفعلية، فلن يكون هناك فائدة من الاحتفاظ بها في الذاكرة المؤقتة بعد الآن. يمكننا مسح بيانات الذاكرة المؤقتة باستخدام تعليق @CacheEvict
:
@CacheEvict(value = "users", allEntries=true)
@DeleteMapping("/{id}")
public void deleteUserByID(@PathVariable Long id) {
LOG.info("deleting person with id {}", id);
userRepository.delete(id);
}
في آخر تعيين، قمنا فقط بطرد مدخلات الذاكرة المؤقتة ولم نفعل شيئًا آخر.
تشغيل تطبيق Spring Boot Redis Cache
يمكننا تشغيل هذا التطبيق ببساطة باستخدام أمر واحد:
mvn spring-boot:run
حدود ذاكرة التخزين المؤقت لريديس
على الرغم من أن ريديس سريع جدًا، إلا أنه لا يزال لا يوجد لديه حدود على تخزين أي كمية من البيانات على نظام 64 بت. يمكنه تخزين 3 جيجابايت فقط من البيانات على نظام 32 بت. يمكن أن يؤدي المزيد من الذاكرة المتاحة إلى معدل إصابة أعلى ولكن هذا سيتوقف تدريجياً عندما يتم احتلال الذاكرة بشكل كبير من قبل ريديس. عندما تصل حجم التخزين المؤقت إلى الحد الأقصى للذاكرة، يتم إزالة البيانات القديمة لإفساح المجال للبيانات الجديدة.
الملخص
في هذا الدرس، نظرنا إلى الطاقة التي يوفرها ذاكرة التخزين المؤقت ريديس لنا في تفاعل البيانات السريع وكيف يمكننا دمجها مع Spring Boot بتكوين بسيط ولكن قوي. لا تتردد في ترك تعليقات أدناه.
Source:
https://www.digitalocean.com/community/tutorials/spring-boot-redis-cache