המטרה של הודעת זיכרון Redis של Spring Boot
בפוסט זה, נקים אפליקציית Spring Boot לדוגמה ונשתלב אותה עם הזיכרון של Redis. בעוד ש-Redis הוא כלי אחסון מבני נתונים בזיכרון מתוך המקור הפתוח, המשמש כמסד נתונים, זיכרון מטמון ושרת הודעות, השיעור הזה ידגים רק את אינטגרצית הזיכרון המטמון. נעשה שימוש בכלי ה-Spring Initializr להגדרת הפרויקט במהירות.
הגדרת פרויקט Spring Boot Redis
נעשה שימוש בכלי ה-Spring Initializr להגדרת הפרויקט במהירות. נשתמש ב-3 תלות כפי שמוצג למטה: הורד את הפרויקט ופתח אותו. עשינו שימוש בתלות במסד הנתונים H2 משום שנעשה שימוש במסד נתונים משולב המאבד את כל הנתונים לאחר שהאפליקציה נעצרה.
התקנת התלתם של Spring Boot Redis Cache בעזרת Maven
אם כבר השלמנו את ההתקנה עם הכלי, אם ברצונך להתקין באופן ידני, אנו משתמשים במערכת הבנייה של 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 עובד, נגדיר Repository לפונקציות הקשורות ל-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));
}
במיפוי לעיל, שיטת getUser
תשים אדם במטמון בשם 'users', תזהה את האדם לפי המפתח 'userId' ותאחסן רק משתמש עם עוקבים גדולים מ-12000. זה מבטיח שהמטמון מולא עם משתמשים שפופולריים מאוד ושנדרשים לעיתים תדירות לשאילתה. גם נוסף במכוון קוד יומץ בקריאת ה- API. בואו נבצע כמה קריאות ל- API מפוסטמן כרגע. אלו הם הקריאות שביצענו:
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
מגבלות מטמון Redis
אף על פי ש-Redis מהיר מאוד, עדיין אין לו הגבלות על אחסון כמות כלשהי של נתונים על מערכת בגודל 64 ביט. הוא יכול לאחסן רק 3GB של נתונים על מערכת בגודל 32 ביט. זיכרון זמין נוסף יכול להוביל ליחס פגיעה גבוה יותר, אך זה יפסיק לפעול כאשר יותר מדי זיכרון תפוס על ידי Redis. כאשר גודל המטמון מגיע למגבלת הזיכרון, נתונים ישנים נמחקים כדי להופיע לנתונים חדשים.
סיכום
בשיעור זה, בדקנו אילו כוח מציע לנו מטמון Redis עם אינטראקציה מהירה של נתונים ואיך אנו יכולים לאינטגרציה זו עם Spring Boot עם הגדרה מינימלית ועם תפוקה חזקה. נשמח לקבל הערות למטה.
Source:
https://www.digitalocean.com/community/tutorials/spring-boot-redis-cache