1. Введение в Redis
Redis в настоящее время является наиболее широко используемым хранилищем данных памяти в отрасли. По сравнению с MEMCACHED Redis поддерживает более богатые структуры данных, такие как хэши, списки, наборы и т. Д., И поддерживает постоянство данных. Кроме того, Redis также предоставляет функции, такие как транзакции, га и основные библиотеки. Можно сказать, что Redis обладает некоторыми функциями системы и базы данных кеша, поэтому существует множество сценариев приложений. В этой статье представлены два типичных сценария приложений в весенний ботинок.
2. Знакомство с салатом
Если вы использовали кеш Redis в приложении Java, тоJedis
не должно быть незнакомым,Lettuce
иJedis
то же самое, подключитьRedis Server
клиентская программа.Jedis
Напрямую подключенRedis Server
, не потокобезопасный в многопоточной среде, если только не используется пул соединений, для каждогоJedis
Экземпляры увеличивают физические соединения.Lettuce
на основеNetty
К экземпляру соединения (StatefulRedisConnection) можно получить одновременный доступ между несколькими потоками, он является потокобезопасным и поддерживает параллельный доступ в многопоточной среде. В то же время это масштабируемый дизайн. Если одного экземпляра соединения недостаточно, вы также можете добавить экземпляры подключения по мере необходимости.
3. Как использовать в приложениях Spring Boot
- непосредственно через
RedisTemplate
использовать - использовать
Spring Cache
интегрированныйRedis
- пройти через
Spring Session
ДелатьSession
общий
4. Инженерная практика
4.1 Зависимость проекта pom.xml выглядит следующим образом:
Листинг кода: spring-boot-redis/pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
-
spring-boot-starter-data-redis: в
Spring Boot 2.x
После того, как нижний слой больше не используетсяJedis
, но заменен наLettuce
, как показано на рисунке: -
commons-pool2 : используется как
redis
Пул соединений, если он не введен, сообщит об ошибке. -
весенняя сессия-данные-redis:
Spring Session
импортировать, делитьсяSession
.
4.2 Конфигурационный файл application.yml
Листинг кода: spring-boot-redis/src/main/resources/application.yml
server:
port: 8080
servlet:
session:
timeout: 30m
spring:
application:
name: spring-boot-redis
cache:
# 使用了Spring Cache后,能指定spring.cache.type就手动指定一下,虽然它会自动去适配已有Cache的依赖,但先后顺序会对Redis使用有影响(JCache -> EhCache -> Redis -> Guava)
type: REDIS
redis:
host: 192.168.0.128
port: 6379
password: 123456
# 连接超时时间(ms)
timeout: 10000
# Redis默认情况下有16个分片,这里配置具体使用的分片,默认是0
database: 0
lettuce:
pool:
# 连接池最大连接数(使用负值表示没有限制) 默认 8
max-active: 100
# 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
max-wait: -1
# 连接池中的最大空闲连接 默认 8
max-idle: 8
# 连接池中的最小空闲连接 默认 0
min-idle: 0
Конфигурация здесь подробно не объясняется, а отмечены примечания, которые необходимо пояснить.
4.3 Как использовать RedisTemplate
4.3.1 Создание класса сущностей User.java
Листинг кода: spring-boot-redis/src/main/java/com/springboot/springbootredis/model/User.java
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
private static final long serialVersionUID = 662692455422902539L;
private Long id;
private String name;
private int age;
}
4.3.2 Пользовательские перераспределения
По умолчанию шаблон может поддерживать толькоRedisTemplate<String, String>
, то есть хранить можно только строки, что не удобно в разработке, поэтому необходимо настроить шаблон.Когда вы настраиваете шаблон и хотите его использоватьString
Хранилище можно использовать в это времяStringRedisTemplate
Кстати, они не конфликтуют, добавьте класс конфигурацииRedisCacheConfig.java
, код показан ниже:
Листинг кода: spring-boot-redis/src/main/java/com/springboot/springbootredis/config/RedisCacheConfig.java
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisCacheConfig {
@Bean
public RedisTemplate<String, Serializable> redisCacheTemplate(LettuceConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Serializable> template = new RedisTemplate<>();
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
4.3.3 Тестовый интерфейс UserController.java
Список кодов:
@RestController
@Slf4j
public class UserController {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
RedisTemplate<String, Serializable> redisCacheTemplate;
@Autowired
UserService userService;
@GetMapping("/test")
public void test() {
stringRedisTemplate.opsForValue().set("geekdigging", "https://www.geekdigging.com/");
log.info("当前获取对象:{}",stringRedisTemplate.opsForValue().get("geekdigging"));
redisCacheTemplate.opsForValue().set("geekdigging.com", new User(1L, "geekdigging", 18));
User user = (User) redisCacheTemplate.opsForValue().get("geekdigging.com");
log.info("当前获取对象:{}", user);
}
}
4.3.4 Тестирование
Запустите службу и откройте браузер, чтобы перейти по ссылке:http://localhost:8080/test, просмотрите печать журнала консоли следующим образом:
2019-09-24 23:49:30.191 INFO 19108 --- [nio-8080-exec-1] c.s.s.controller.UserController : 当前获取对象:https://www.geekdigging.com/
2019-09-24 23:49:30.243 INFO 19108 --- [nio-8080-exec-1] c.s.s.controller.UserController : 当前获取对象:User(id=1, name=geekdigging, age=18)
Успех теста.
4.4 Интегрируйте Redis с помощью пружинного кэша
4.4.1 Особенности Spring Cache
Spring 3.1 представляет захватывающую технологию кэширования на основе аннотаций, которая по сути не является конкретной реализацией кэша (например, EHCache или Redis), а представляет собой абстракцию использования кэша за счет использования существующего кода.Добавьте небольшое количество различных аннотаций, которые он определяет. , то есть может добиться эффекта кэширования возвращаемого объекта метода.
Spring Cache обладает значительной гибкостью: он может не только использовать SpEL (Spring Expression Language) для определения ключей кэша и различных условий, но также предоставлять готовые решения для временного хранения кэша, а также поддерживает основные профессиональные кэши, такие как EHCache, Интеграция Redis, Guava.
- Существующий код можно кэшировать на основе аннотаций.
- Out-of-The-Box прямо из коробки для использования кэширования без установки и развертывания дополнительных сторонних компонентов
- Поддержка Spring Express Language, вы можете использовать любое свойство или метод объекта для определения ключа и состояния кеша.
- Поддержка AspectJ и реализация поддержки кэширования для любого метода через него
- Поддерживает пользовательские ключи и настраиваемые менеджеры кеша со значительной гибкостью и расширяемостью.
4.4.2 Определение интерфейса UserService.java
Листинг кода: spring-boot-redis/src/main/java/com/springboot/springbootredis/service/UserService.java
public interface UserService {
User save(User user);
User get(Long id);
void delete(Long id);
}
4.4.3 Реализация интерфейса UserServiceImpl.java
Листинг кода: spring-boot-redis/src/main/java/com/springboot/springbootredis/service/impl/UserServiceImpl.java
@Service
@Slf4j
public class UserServiceImpl implements UserService {
private static final Map<Long, User> USER_MAP = new HashMap<>();
static {
USER_MAP.put(1L, new User(1L, "geekdigging.com", 18));
USER_MAP.put(2L, new User(2L, "geekdigging.com", 19));
USER_MAP.put(3L, new User(3L, "geekdigging.com", 20));
}
@CachePut(value = "user", key = "#user.id")
@Override
public User save(User user) {
USER_MAP.put(user.getId(), user);
log.info("进入 save 方法,当前存储对象:{}", user);
return user;
}
@Cacheable(value = "user", key = "#id")
@Override
public User get(Long id) {
log.info("进入 get 方法,当前获取对象:{}", USER_MAP.get(id));
return USER_MAP.get(id);
}
@CacheEvict(value = "user", key = "#id")
@Override
public void delete(Long id) {
USER_MAP.remove(id);
log.info("进入 delete 方法,删除成功");
}
}
Чтобы облегчить демонстрацию операций с базой данных, прямо определенныйMap<Long, User> USER_MAP
Ядро здесь три ноты@Cacheable
,@CachePut
,@CacheEvict
.
4.4.3.1 @Cacheable
Кэшировать результат метода на основе его параметров запроса
- key: Закэшированный ключ, который может быть пустым, если он указан, то должен быть записан согласно выражению SpEL, если не указан, то будет объединен по всем параметрам метода по умолчанию (например:
@Cacheable(value="user",key="#userName")
) - значение: имя кеша, хотя бы одно должно быть указано (например:
@Cacheable(value="user")
или@Cacheable(value={"user1","use2"})
) - условие: Состояние кеша, которое может быть пустым, записанное на SpEL, возвращает true или false и кэширует только если оно истинно (например:
@Cacheable(value = "user", key = "#id",condition = "#id < 10")
)
4.4.3.2 @CachePut
Результат кешируется в соответствии с параметрами запроса метода, в отличие от @Cacheable, он каждый раз вызывает вызов реального метода.
- ключ: такой же, как указано выше
- значение: то же, что и выше
- Состояние:
4.4.3.3 @CachEvict
Очистить кеш в зависимости от условий
- ключ: такой же, как указано выше
- значение: то же, что и выше
- состояние: то же, что и выше
- allEntries: очищать ли весь кешированный контент, по умолчанию установлено значение false, если указано значение true, все кеши будут очищены сразу после вызова метода (например:
@CacheEvict(value = "user", key = "#id", allEntries = true)
) - beforeInvocation: следует ли очищать перед выполнением метода, по умолчанию установлено значение false, если указано значение true, кеш будет очищен перед выполнением метода.По умолчанию, если выполнение метода вызывает исключение, кеш не будет очищается (например:
@CacheEvict(value = "user", key = "#id", beforeInvocation = true)
)
4.4.4 Запуск основного класса
Листинг кода: spring-boot-redis/src/main/java/com/springboot/springbootredis/SpringBootRedisApplication.java
@SpringBootApplication
@EnableCaching
public class SpringBootRedisApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootRedisApplication.class, args);
}
}
- Здесь необходимо добавить примечание
@EnableCaching
Начать весеннюю сессию.
4.4.5 Добавить тестовый интерфейс
Листинг кода: spring-boot-redis/src/main/java/com/springboot/springbootredis/controller/UserController.java
@GetMapping("/test1")
public void test1() {
User user = userService.save(new User(4L, "geekdigging.com", 35));
log.info("当前 save 对象:{}", user);
user = userService.get(1L);
log.info("当前 get 对象:{}", user);
userService.delete(5L);
}
4.4.6 Тестирование
Запустите службу и откройте браузер, чтобы перейти по ссылке:http://localhost:8080/test, обновите страницу, журнал консоли выводит следующее:
2019-09-25 00:07:21.887 INFO 21484 --- [nio-8080-exec-1] c.s.s.service.impl.UserServiceImpl : 进入 save 方法,当前存储对象:User(id=4, name=geekdigging.com, age=35)
2019-09-25 00:07:21.897 INFO 21484 --- [nio-8080-exec-1] c.s.s.controller.UserController : 当前 save 对象:User(id=4, name=geekdigging.com, age=35)
2019-09-25 00:07:21.899 INFO 21484 --- [nio-8080-exec-1] c.s.s.service.impl.UserServiceImpl : 进入 get 方法,当前获取对象:User(id=1, name=geekdigging.com, age=18)
2019-09-25 00:07:21.900 INFO 21484 --- [nio-8080-exec-1] c.s.s.controller.UserController : 当前 get 对象:User(id=1, name=geekdigging.com, age=18)
2019-09-25 00:07:21.901 INFO 21484 --- [nio-8080-exec-1] c.s.s.service.impl.UserServiceImpl : 进入 delete 方法,删除成功
Обновите страницу еще раз и просмотрите журнал консоли:
2019-09-25 00:08:54.076 INFO 21484 --- [nio-8080-exec-7] c.s.s.service.impl.UserServiceImpl : 进入 save 方法,当前存储对象:User(id=4, name=geekdigging.com, age=35)
2019-09-25 00:08:54.077 INFO 21484 --- [nio-8080-exec-7] c.s.s.controller.UserController : 当前 save 对象:User(id=4, name=geekdigging.com, age=35)
2019-09-25 00:08:54.079 INFO 21484 --- [nio-8080-exec-7] c.s.s.controller.UserController : 当前 get 对象:User(id=1, name=geekdigging.com, age=18)
2019-09-25 00:08:54.079 INFO 21484 --- [nio-8080-exec-7] c.s.s.service.impl.UserServiceImpl : 进入 delete 方法,删除成功
Результаты согласуются с нашими ожиданиями.Видно, что при добавлении, удалении, изменении и запросе запрос не имеет вывода журнала, потому что он напрямую получает данные из кеша, а добавление, изменение и удаление будут все входитьUserServiceImpl
Выполнение определенного бизнес-кода в методе.
4.5 Совместное использование сеанса
4.5.1 Введение в Spring Session
Spring Session предоставляет решение для создания и управления Servlet HttpSessions. Spring Session предоставляет функцию кластеризованного сеанса (Clustered Sessions).По умолчанию внешний Redis используется для хранения данных сеанса для решения проблемы совместного использования сеанса.
4.5.2 Запустите основной класс SpringBootRedisApplication.java
Листинг кода: spring-boot-redis/src/main/java/com/springboot/springbootredis/SpringBootRedisApplication.java
@SpringBootApplication
@EnableCaching
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)
public class SpringBootRedisApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootRedisApplication.class, args);
}
}
- maxInactiveIntervalInSeconds: установите время истечения сеанса.После использования Spring Session исходный файл конфигурации Spring Boot
application.yml
серединаserver.session.timeout
Свойства больше не действуют.
4.5.3 Добавить тестовый интерфейс
Листинг кода: spring-boot-redis/src/main/java/com/springboot/springbootredis/controller/UserController.java
@GetMapping("/getBlogUrl")
public String getSessionId(HttpServletRequest request) {
String url = (String) request.getSession().getAttribute("url");
if (StringUtils.isEmpty(url)) {
request.getSession().setAttribute("url", "https://www.geekdigging.com/");
}
log.info("获取session内容为: {}", request.getSession().getAttribute("url"));
return request.getRequestedSessionId();
}
4.5.4 Тестирование
Запустите службу и откройте браузер, чтобы перейти по ссылке:http://localhost:8080/getBlogUrl, чтобы просмотреть текущее содержимое хранилища Redis, как показано ниже:
Среди них 1569339180000 — это время истечения, что означает, что Session истечет по истечении этого времени, а b2522824-1094-478e-a435-554a551bc8bb — это SessionId.
4.5.6 Как разделить сеансы между несколькими службами
Выполните описанные выше шаги, чтобы снова настроить его в другом проекте, и совместное использование сеанса будет автоматически выполнено после запуска.
5. Пример кода
6. Ссылка
E Mom COO Талант /задняя часть/SPR… блог Bringing Pain to Talent.com/2018/05/11/…
Если моя статья была вам полезна, отсканируйте код и подпишитесь на официальный аккаунт автора: Получите последние новости о галантерейных товарах :)