Spring Boot Redis Cache
In questo post, installeremo un’applicazione di esempio Spring Boot e la integreremo con la Cache Redis. Mentre Redis è uno store di strutture dati in memoria open source, utilizzato come database, cache e message broker, questa lezione dimostrerà solo l’integrazione della cache. Faremo uso dello strumento Spring Initializr per configurare rapidamente il progetto.
Configurazione del Progetto Spring Boot Redis
Faremo uso dello strumento Spring Initializr per configurare rapidamente il progetto. Utilizzeremo 3 dipendenze come mostrato di seguito: Scaricare il progetto e decomprimerlo. Abbiamo utilizzato la dipendenza del database H2 poiché utilizzeremo un database integrato che perde tutti i dati una volta che l’applicazione viene arrestata.
Spring Boot Redis Cache Dipendenze Maven
Anche se abbiamo già completato la configurazione con lo strumento, se desideri configurarlo manualmente, utilizziamo il sistema di build Maven per questo progetto e ecco le dipendenze che abbiamo utilizzato:
<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>
Assicurati di utilizzare la versione stabile di Spring Boot dal repository maven centrale.
Definizione del Modello
Per salvare un oggetto nel database Redis, definiamo un oggetto modello Person con campi di base:
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;
}
// getter e setter standard
@Override
public String toString() {
return String.format("User{id=%d, name='%s', followers=%d}", id, name, followers);
}
}
Si tratta di un POJO standard con getter e setter.
Configurazione della Cache Redis
Con Spring Boot e la dipendenza richiesta già funzionante con Maven, possiamo configurare un’istanza locale di Redis con soli tre righe nel nostro file application.properties come segue:
# Configurazione Redis
spring.cache.type=redis
spring.redis.host=localhost
spring.redis.port=6379
Usa anche l’annotazione @EnableCaching
sulla classe principale di 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) {
// Popolamento del database integrato qui
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());
}
}
Abbiamo aggiunto un CommandLineRunner poiché desideriamo popolare alcuni dati di esempio nel database H2 integrato.
Definizione del Repository
Prima di mostrare come funziona Redis, definiremo un Repository per la funzionalità correlata a JPA:
package com.journaldev.rediscachedemo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository { }
Attualmente non contiene chiamate a metodi poiché non ne abbiamo bisogno.
Definizione del Controller
I controller sono il luogo in cui viene richiamata l’azione della cache di Redis. In realtà, questo è il posto migliore per farlo perché, essendo la cache direttamente associata ad esso, la richiesta non dovrà nemmeno entrare nel codice del servizio per attendere i risultati memorizzati nella cache. Ecco lo scheletro del controller:
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;
}
...
}
Ora, per inserire qualcosa nella cache, utilizziamo l’annotazione @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));
}
Nella mappatura sopra, il metodo getUser
inserirà una persona in una cache chiamata ‘users’, identificherà quella persona con la chiave ‘userId’ e memorizzerà solo un utente con più di 12000 follower. Questo garantisce che la cache sia popolata da utenti molto popolari e spesso interrogati. Inoltre, abbiamo aggiunto intenzionalmente un’istruzione di log nella chiamata API. Facciamo alcune chiamate API da Postman in questo momento. Queste sono le chiamate che abbiamo effettuato:
localhost:8090/1
localhost:8090/1
localhost:8090/2
localhost:8090/2
Se notiamo i log, saranno così:
... : Getting user with ID 1.
... : Getting user with ID 1.
... : Getting user with ID 2.
Nota qualcosa? Abbiamo effettuato quattro chiamate API ma sono presenti solo tre log. Ciò è dovuto al fatto che l’utente con ID 2 ha 29000 follower e quindi i suoi dati sono stati memorizzati nella cache. Ciò significa che quando è stata effettuata una chiamata API per esso, i dati sono stati restituiti dalla cache e non è stata effettuata alcuna chiamata al database per questo!
Aggiornamento della cache
I valori della cache dovrebbero essere aggiornati anche quando vengono aggiornati i valori effettivi degli oggetti. Questo può essere fatto utilizzando l’annotazione @CachePut:
@CachePut(value = "users", key = "#user.id")
@PutMapping("/update")
public User updatePersonByID(@RequestBody User user) {
userRepository.save(user);
return user;
}
Con questo, una persona è nuovamente identificata dal suo ID e viene aggiornata con i risultati.
Cancellazione della cache
Se alcuni dati devono essere eliminati dal database effettivo, non avrebbe senso tenerli in cache. Possiamo cancellare i dati della cache utilizzando l’annotazione @CacheEvict
:
@CacheEvict(value = "users", allEntries=true)
@DeleteMapping("/{id}")
public void deleteUserByID(@PathVariable Long id) {
LOG.info("deleting person with id {}", id);
userRepository.delete(id);
}
Nella mappatura precedente, abbiamo solo eliminato le voci della cache e non abbiamo fatto altro.
Esecuzione dell’applicazione Spring Boot Redis Cache
Possiamo eseguire questa app semplicemente usando un singolo comando:
mvn spring-boot:run
Limiti della Cache Redis
Anche se Redis è molto veloce, non ha limiti per memorizzare qualsiasi quantità di dati su un sistema a 64 bit. Può memorizzare solo 3 GB di dati su un sistema a 32 bit. Più memoria disponibile può portare a un maggiore rapporto di successo, ma questo tende a cessare una volta che troppa memoria è occupata da Redis. Quando la dimensione della cache raggiunge il limite di memoria, i dati vecchi vengono rimossi per fare spazio a quelli nuovi.
Riassunto
In questa lezione, abbiamo esaminato quale potenza ci fornisce la Cache Redis con un’interazione rapida dei dati e come possiamo integrarla con Spring Boot con una configurazione minima eppure potente. Sentitevi liberi di lasciare commenti qui sotto.
Source:
https://www.digitalocean.com/community/tutorials/spring-boot-redis-cache