Репозиторий исходного кода:GitHub.com/Округ Чжашуй/…
Облако кода:git ee.com/иди туда/узнай…
В предыдущем разделе мы в основном реализовали глобальную обработку исключений Spring Boot.В этом разделе основное внимание уделяется интеграции Spring Boot с Redis, которая будет реализовывать следующие два контента:
- Spring Boot напрямую управляет Redis для реализации набора K-V NoSQL и получения
- Кэш базы данных Spring Boot
1. Введение и установка Redis
Redis является наиболее широко используемой и известной базой данных NoSQL в Интернете, а также наиболее широко используемым промежуточным программным обеспечением в системах хранения.
Redis — это сервер структуры данных в памяти с открытым исходным кодом (под лицензией BSD), который можно использовать, среди прочего, в качестве базы данных, кэша и посредника очередей сообщений. Он поддерживает несколько типов структур данных, таких как строки, хэши, списки, наборы, отсортированные наборы. Встроенная репликация, сценарии Lua, вытеснение LRU, транзакции и различные уровни сохраняемости диска, а также обеспечение высокой доступности с помощью Redis Sentinel и автоматическое разбиение на разделы с помощью Redis Cluster. «Ссылка 1»
1.1 Сценарии использования Redis
После появления микросервисов и распространения Redis все шире используется в интернет-компаниях, и сценариев использования становится все больше:
- тайник: это наиболее часто используемая область Redis. Redis хранит все данные непосредственно в памяти, и его скорость доступа намного выше, чем у баз данных, таких как MySQL, которые необходимо запрашивать с жесткого диска. Если вы записываете данные, обычно используемые в SQL в кеш можно значительно повысить производительность системы, снизить нагрузку на базу данных. В то же время обмен данными между процессами также может быть достигнут с помощью кэширования Redis;
- Упорство: Например: для каждого компонента микросервиса встроенный механизм сеанса не может быть разделен между процессами. Если сеанс записан в Redis, можно реализовать совместное использование сеанса различными процессами микросервиса. Путем сохранения его на жестком диске через Redis, этого можно избежать, сессия сервера теряется из-за простоя и перезапуска сервера;
- Распределенная блокировка: для данных, совместно используемых процессами, необходимо избегать генерации грязных данных с помощью блокировок.Однопоточная функция Redis может использоваться для блокировки и освобождения общих данных;
- опубликовать, подписаться: Да, Redis можно использовать как облегченную очередь сообщений;
- Более: ограничения на доступ к интерфейсу, кешированная история поведения пользователей, количество лайков контента, списки лидеров и т. д.
1.2, установка Redis
Здесь используется Linux.Для платформ Windows вы можете использовать WSL или виртуальную машину для установки дистрибутива Linux.
# 安装编译所需的软件
sudo apt install gcc g++ make
Официальный сайт Redis:redis.io/download
# 下载 Redis
wget http://download.redis.io/releases/redis-5.0.8.tar.gz
tar -xvf redis-5.0.8.tar.gz
cd redis-5.0.8
# 编译
mark
Простая конфигурация для Redis:vim redis.conf
# 添加, Redis 密码,默认为空
requirepass springboot
# 注释掉 bind,允许远程访问,或者空格隔开添加运行远程访问的 ip
# bind 127.0.0.1
# 修改为 no,保护模式关闭,允许通过 IP 访问
protected-mode no
Старт Redis
# 后台以服务的方式运行
src/redis-server redis.conf --daemonize yes
# 使用密码登录默认端口号 6379
src/redis-cli -p 6379 -a springboot
# 写入 Key = name,value = springboot
127.0.0.1:6379> set name springboot
OK
127.0.0.1:6379> get name
"springboot"
127.0.0.1:6379> del name
(integer) 1
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379>exit
# 关闭 Redis 服务,并把数据保存到硬盘
./src/redis-cli -p 6379 -a springboot shutdown save
2. Начните использовать Redis
Новый проект10-spring-boot-redis, добавьте следующие зависимости:
// Gradle
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.1'
// 刚开始是 MyBatis,但缓存部分写的有问题,删掉换了 JPA,最后有加上了 MyBatis,所以有两个
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'mysql:mysql-connector-java'
документapplication.properties
Конфигурация соединения Redis, соединения MySQL, MyBatis, JPA
# Redis host ip
spring.redis.host=wsl
# Redis 服务器连接端口
spring.redis.port=6379
# Redis 数据库索引(默认为 0)
spring.redis.database=0
# Redis 服务器连接密码(默认为空)
spring.redis.password=springboot
#连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=500
# 使用 Redis 缓存
spring.cache.type=redis
# 数据库 URL、用户名、密码、JDBC Driver更换数据库只需更改这些信息即可
# MySQL 8 需要指定 serverTimezone 才能连接成功
spring.datasource.url=jdbc:mysql://localhost:3306/spring?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.password=xiaoxian
spring.datasource.username=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# Hibernate 的一些配置
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
# 是否在 Log 显示 SQL 执行语句
spring.jpa.show-sql=true
# hibernate.ddl-auto 配置对数据库表的操作
spring.jpa.hibernate.ddl-auto=none
# MyBatis 驼峰命名转换
mybatis.configuration.map-underscore-to-camel-case=true
# 显示 Mybatis 的 SQL,Mapper 所在的包打印 debug 级别的代码
logging.level.org.xian.redis.repository=debug
стартовый классRedisApplication.java
Настройте картограф MyBatis и включите конфигурацию кэша.
@SpringBootApplication
@EnableCaching
@MapperScan("org.xian.redis.repository")
public class RedisApplication ......
2.1, конфигурация Redis
Новый RedisConfig.java
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfig {
@Bean
public RedisCacheConfiguration cacheConfiguration() {
// 设置缓存过期时间为 120 秒后
return RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(120)).disableCachingNullValues();
}
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory factory) {
// 使用 RedisCacheManager 作为缓存管理器
return RedisCacheManager.builder(factory).cacheDefaults(cacheConfiguration()).transactionAware().build();
}
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
// Jackson 序列方式
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
// Jackson 默认自动识别 Public 修饰的成员变量、getter、setter
// private、protected、public 修饰的成员变量都可以自动识别,无需都指定 getter、setter 或者 public。
// 参考 https://blog.csdn.net/sdyy321/article/details/40298081
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 对于 8 种基本数据类型及其封装类和 String ,其他的类型在序列化的时候带上该类型和值
// 参考 https://www.jianshu.com/p/c5fcd2a1ab49
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
RedisTemplate<String, Object> template = new RedisTemplate<>();
// Redis 链接
template.setConnectionFactory(redisConnectionFactory);
// Redis Key - Value 序列化使用 Jackson
template.setKeySerializer(jackson2JsonRedisSerializer);
template.setValueSerializer(jackson2JsonRedisSerializer);
// Redis HashKey - HashValue 序列化使用 Jackson
template.setHashKeySerializer(jackson2JsonRedisSerializer);
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
@Bean
@ConditionalOnMissingBean(StringRedisTemplate.class)
public StringRedisTemplate stringRedisTemplate(
RedisConnectionFactory redisConnectionFactory) {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
RedisTemplate по умолчанию — это RedisTemplate
Используйте Jackson в качестве сериализатора, потому что по умолчанию он используетJdkSerializationRedisSerializer, который сериализуется в двоичный файл и хранится в Redis, что не способствует просмотру исходного контента. Используя JSON в качестве инструмента сериализации, можно легко получить доступ и к другим языкам программирования.
2.2, Redis получить и установить
Здесь мы покажем, как хранить и читать данные Redis с помощью RedisTemplate и StringRedisTemplate.
@RestController
@CacheConfig(cacheNames = "users")
public class RedisController {
@Resource StringRedisTemplate stringTemplate;
@Resource RedisTemplate<String, User> redisTemplate;
@RequestMapping("/setString")
public String setString(@RequestParam(value = "key") String key,
@RequestParam(value = "value") String value) {
stringTemplate.opsForValue().set(key, value);
return "ok";
}
@RequestMapping("/getString")
public String getString(@RequestParam(value = "key") String key) {
return stringTemplate.opsForValue().get(key);
}
// User 类set、get 和时间限制
@RequestMapping(value = "/setUser")
public String setUser(@RequestBody User user) {
// 1 分钟后过期
redisTemplate.opsForValue().set(user.getUsername(), user, Duration.ofMinutes(1));
return "ok";
}
@RequestMapping("/getUser")
public User getUser(@RequestParam(value = "key") String key) {
return redisTemplate.opsForValue().get(key);
}
@RequestMapping("/delUser")
public User delUser(@RequestParam(value = "key") String key) {
User user = redisTemplate.opsForValue().get(key);
// 删除
redisTemplate.delete(key);
return user;
}
}
Анализ кода: set(key, value, time_out), время истечения срока действия Redis можно указать через третий параметр.
Запустите проект, посетите вышеуказанные URL-адреса соответственно и проверьте их действие.
2.2, кеш базы данных
документUser.java
, сценарий SQL находится вuser.sql
, Insert Controller здесь не прописан, а сервисный слой опущен.
@Entity
@Table(name = "user", schema = "spring")
public class User implements Serializable {
private static final long serialVersionUID = 413797298970501130L;
@Id private String username;
private Byte age;
// 省略 Getter setter
}
Файл UserMapper:
package org.xian.redis.repository;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.xian.redis.entity.User;
public interface UserMapper {
@Select("Select username, age From user Where username=#{username}")
User selectByUsername(String username);
@Update("Update user Set age=#{age} Where username=#{username}")
void update(User user);
@Delete("Delete From user where username=#{username}")
void delete(String username);
}
существуетRedisController
Добавьте следующее
@RequestMapping("/deleteAllCache")
@CacheEvict(allEntries = true)
public String deleteAllCache() {
// 删除所有缓存
return "OK";
}
@RequestMapping("/mySelect")
@Cacheable(key = "#username")
public User mySelect(@RequestParam(value = "username") String username) {
return userMapper.selectByUsername(username);
}
@RequestMapping("/myUpdate")
@CachePut(key = "#user.username")
public User myUpdate(@RequestBody User user) {
userMapper.update(user);
return userMapper.selectByUsername(user.getUsername());
}
@RequestMapping("/myDelete")
@CacheEvict(key = "#username")
public User myDelete(@RequestParam(value = "username") String username) {
userMapper.delete(username);
return userMapper.selectByUsername(username);
}
Разбор кода: кеширование трех часто используемых аннотаций.
@Cacheable(key = "#username")
Указывает, что имя пользователя используется в качестве ключа, а результат записывается в кэш Redis. Если это значение ключа уже есть в кеше, оно вернется напрямую без выполнения SQL-запроса.Когда в кеше нет данных, SQL-запрос будет выполнен. То есть сначала посмотрите, есть ли кеш, верните его напрямую, если есть, и запросите базу данных, если нет.
@CachePut(key = "#user.username")
, а также@Cacheable
Точно так же функция находится в myUpdate(), и содержимое в кеше не будет записано или обновлено до окончания выполнения.
@CacheEvict(key = "#username")
Удалить содержимое в кеше на основе значения ключа. Удаляет, если указано allEntries = true@CacheConfig(cacheNames = "users")
Все кэши под cacheNames.
Запустите проект, откройте /mySelect?username=boot , при первом доступе или доступе после истечения срока действия кеша терминал распечатает оператор SQL, запросит SQL, получит доступ в течение срока действия кеша и напрямую вернет содержимое в кеше. без обращения к базе данных.
Доступ к /select?username=boot, API-интерфейсу, использующему JPA, также не запрашивает базу данных в течение срока действия кэша. Заинтересованные друзья могут попробовать его, и соответствующий код был загружен в репозиторий GitHub.
Другие интерфейсы здесь не перечислены.
Ступай на яму: Кэшированный @Cache* используется не в интерфейсе Repository или Mapper, а в определенном методе. Например, на уровне службы интерфейса службы или на уровне интерфейса контроллера.
Кроме того, кеш может указать генератору ключей автоматически генерировать значение ключа, что здесь не реализовано, а задается вручную по ключу = "#username".
В соответствии с дополнительными операционными API Redis, такими как массивы, наборы, хэш, рекомендуется прочитать Справочник 1.
Ссылка 1: Понимание Redis и использование Redis в проектах Spring BootWoohoo. IBM.com/developer Я…"
Содержание следующего раздела — интеграция Spring Boot с MangoDB (еще один широко используемый NoSQL) или краткое введение в распределенные блокировки Redis. Для получения дополнительной информации вы можете обратить внимание на CSDN-блог Xiaoxian «Big Data Xiaoxian» или публичный аккаунт «Advanced Programming Technology».