标签:增加 oms username div mod gen 工具 灵活 manage
系统环境:
参考地址:
1、是什么缓存
我们日常生活中,经常会接触听到缓存这个词,例如,浏览器清空缓存,处理器缓存大小,磁盘缓存等等。经过分类,可以将缓存分为:
2、为什么使用缓存
用缓存,主要有解决 高性能 与 高并发 与 减少数据库压力。缓存本质就是将数据存储在内存中,当数据没有发生本质变化的时候,我们应尽量避免直接连接数据库进行查询,因为并发高时很可能会将数据库压塌,而是应去缓存中读取数据,只有缓存中未查找到时再去数据库中查询,这样就大大降低了数据库的读写次数,增加系统的性能和能提供的并发量。
3、缓存的优缺点
优点:
缺点:
1、什么是 Redis
Redis 是一个高性能的 Key-Value 数据库,它是完全开源免费的,而且 Redis 是一个 NoSQL 类型数据库,是为了解决 高并发、高扩展,大数据存储 等一系列的问题而产生的数据库解决方案,是一个非关系型的数据库。但是,它也是不能替代关系型数据库,只能作为特定环境下的扩充。
2、为什么使用 Redis 作为缓存
3、Redis 支持的数据类型
Redis 支持的数据结构类型包括:
为了保证读取的效率,Redis 把数据对象都存储在内存当中,它可以支持周期性的把更新的数据写入磁盘文件中。而且它还提供了交集和并集,以及一些不同方式排序的操作。
1、缓存穿透
缓存穿透: 指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿透。
缓存穿透几种解决办法:
2、缓存击穿
缓存击穿: 某个 key 非常热点,访问非常频繁,处于集中式高并发访问的情况,当这个 key 在失效的瞬间,大量的请求就击穿了缓存,直接请求数据库,就像是在一道屏障上凿开了一个洞。
缓存击穿几种解决办法:
3、缓存雪崩
缓存雪崩: 当缓存服务器重启、或者大量缓存集中在某一个时间段失效,这样在失效的时候,也会给后端系统(比如DB)带来很大压力,造成数据库后端故障,从而引起应用服务器雪崩。
缓存雪崩几种解决办法:
4、缓存一致性
使用缓存很大可能导致数据不一致问题,如下:
所以使用缓存时候,应该结合实际情况,考虑缓存的数据是否有一致性需求。
1、Mavne 引入相关依赖
2、配置 Redis 参数
application 文件中添加连接 Redis 的配置参数
3、配置 Spring 缓存管理器
@Configurationpublic class RedisConfig { /** * 配置缓存管理器 * @param factory Redis 线程安全连接工厂 * @return 缓存管理器 */ @Bean public CacheManager cacheManager(RedisConnectionFactory factory) { // 生成两套默认配置,通过 Config 对象即可对缓存进行自定义配置 RedisCacheConfiguration cacheConfig = RedisCacheConfiguration.defaultCacheConfig() // 设置过期时间 10 分钟 .entryTtl(Duration.ofMinutes(10)) // 设置缓存前缀 .prefixKeysWith("cache:user:") // 禁止缓存 null 值 .disableCachingNullValues() // 设置 key 序列化 .serializeKeysWith(keyPair()) // 设置 value 序列化 .serializeValuesWith(valuePair()); // 返回 Redis 缓存管理器 return RedisCacheManager.builder(factory) .withCacheConfiguration("user", cacheConfig).build(); } /** * 配置键序列化 * @return StringRedisSerializer */ private RedisSerializationContext.SerializationPair<String> keyPair() { return RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()); } /** * 配置值序列化,使用 GenericJackson2JsonRedisSerializer 替换默认序列化 * @return GenericJackson2JsonRedisSerializer */ private RedisSerializationContext.SerializationPair<Object> valuePair() { return RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()); }}
4、服务中使用 SpringCache 的注解
@Service@CacheConfig(cacheNames = "user")public class UserServiceImpl implements UserService { /** * 新增用户 */ public User addUser(User user) { ...... } /** * 查询用户 */ @Cacheable(key = "#username") public User getUserByUsername(String username) { ...... } /** * 更新用户 */ @CachePut(key = "#user.username") public User updateUser(User user) { ...... } /** * 删除用户 */ @CacheEvict(key = "#username") public void deleteByUsername(String username) { ...... }}
注解说明:
上面注解中的常用配置参数:
5、启动类添加开启缓存注解
使用 Spring Cache 虽然方便,但是也有很多局限性,因为它多是根据请求参数命名 key,根据返回指设置 value,这样很多情况下,我们想方法内部进行命名和操作有一定的限制。如果我们需要灵活设置缓存,可以不用 SpringCache 提供的注解,直接在代码中使用 Spring-data-redis 包提供的方法,手动操作 key 与 value。
还有经常要批量设置、读取缓存,可以使用:
下面是一个简单的 SpringBoot 项目,用于对用户的增删改查,这里使用 SpringCache 来模拟对数据进行缓存,示例如下:
1、Mavne 引入相关依赖
Maven 中引入 SpringBoot 和 Redis 依赖,因为使用了
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.2.RELEASE</version> </parent> <groupId>mydlq.club</groupId> <artifactId>springboot-redis-example</artifactId> <version>0.0.1</version> <name>springboot-redis-example</name> <description>Demo project for Spring Boot Redis</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <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.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build></project>
2、配置连接 Redis 参数
3、配置 Spring 缓存管理器
缓存配置类,里面配置缓存管理器,配置缓存的全局过期时间、序列化等参数。
import org.springframework.cache.CacheManager;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.cache.RedisCacheConfiguration;import org.springframework.data.redis.cache.RedisCacheManager;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.serializer.*;import java.time.Duration;/** * Redis 配置类 */@Configurationpublic class RedisConfig { /** * 配置缓存管理器 * @param factory Redis 线程安全连接工厂 * @return 缓存管理器 */ @Bean public CacheManager cacheManager(RedisConnectionFactory factory) { // 生成两套默认配置,通过 Config 对象即可对缓存进行自定义配置 RedisCacheConfiguration cacheConfig1 = RedisCacheConfiguration.defaultCacheConfig() // 设置过期时间 10 分钟 .entryTtl(Duration.ofMinutes(10)) // 设置缓存前缀 .prefixKeysWith("cache:user:") // 禁止缓存 null 值 .disableCachingNullValues() // 设置 key 序列化 .serializeKeysWith(keyPair()) // 设置 value 序列化 .serializeValuesWith(valuePair()); RedisCacheConfiguration cacheConfig2 = RedisCacheConfiguration.defaultCacheConfig() // 设置过期时间 30 秒 .entryTtl(Duration.ofSeconds(30)) .prefixKeysWith("cache:user_info:") .disableCachingNullValues() .serializeKeysWith(keyPair()) .serializeValuesWith(valuePair()); // 返回 Redis 缓存管理器 return RedisCacheManager.builder(factory) .withCacheConfiguration("user", cacheConfig1) .withCacheConfiguration("userInfo", cacheConfig2) .build(); } /** * 配置键序列化 * @return StringRedisSerializer */ private RedisSerializationContext.SerializationPair<String> keyPair() { return RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()); } /** * 配置值序列化,使用 GenericJackson2JsonRedisSerializer 替换默认序列化 * @return GenericJackson2JsonRedisSerializer */ private RedisSerializationContext.SerializationPair<Object> valuePair() { return RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()); }}
4、定义实体类
用户实体类
User
用户信息实体类
UserInfo
5、定义服务接口
UserService
import mydlq.club.example.entity.User;/** * 用户业务接口 */public interface UserService { /** * 增加账户 * * @param user 账户 */ void addUser(User user); /** * 获取账户 * * @param username 用户名 * @return 用户信息 */ User getUserByUsername(String username); /** * 修改账户 * * @param user 用户信息 * @return 用户信息 */ User updateUser(User user); /** * 删除账户 * @param username 用户名 */ void deleteByUsername(String username);}
UserInfoService
import mydlq.club.example.entity.UserInfo;/** * 用户信息业务接口 */public interface UserInfoService { /** * 增加用户信息 * * @param userInfo 用户信息 */ void addUserInfo(UserInfo userInfo); /** * 获取用户信息 * * @param name 姓名 * @return 用户信息 */ UserInfo getByName(String name); /** * 修改用户信息 * * @param userInfo 用户信息 * @return 用户信息 */ UserInfo updateUserInfo(UserInfo userInfo); /** * 删除用户信息 * @param name 姓名 */ void deleteByName(String name);}
6、实现服务类
实现 UserService 与 UserInfoService 接口中的方法,里面使用 @Cacheable、@CachePut、@CacheEvict 三个注解完成对用户与用户信息数据的缓存。
UserServiceImpl(用户业务实现类)
注意,为了演示方便,没有连接数据库,临时创建了个成员变量 userMap 来模拟数据库存储。
import mydlq.club.example.entity.User;import mydlq.club.example.service.UserService;import org.springframework.beans.BeanUtils;import org.springframework.cache.annotation.CacheConfig;import org.springframework.cache.annotation.CacheEvict;import org.springframework.cache.annotation.CachePut;import org.springframework.cache.annotation.Cacheable;import org.springframework.stereotype.Service;import java.util.HashMap;@Service@CacheConfig(cacheNames = "user")public class UserServiceImpl implements UserService { private HashMap<String, User> userMap = new HashMap<>(); @Override public void addUser(User user) { userMap.put(user.getUsername(), user); } @Override @Cacheable(key = "#username",unless = "#result==null ") public User getUserByUsername(String username) { if (!userMap.containsKey(username)) { return null; } return userMap.get(username); } @Override @CachePut(key = "#user.username") public User updateUser(User user) { if (!userMap.containsKey(user.getUsername())){ throw new RuntimeException("不存在该用户"); } // 获取存储的对象 User newUser = userMap.get(user.getUsername()); // 复制要更新的数据到新对象,因为不能更改用户名信息,所以忽略 BeanUtils.copyProperties(user, newUser, "username"); // 将新的对象存储,更新旧对象信息 userMap.put(newUser.getUsername(), newUser); // 返回新对象信息 return newUser; } @Override @CacheEvict(key = "#username") public void deleteByUsername(String username) { userMap.remove(username); }}
UserInfoServiceImpl(用户信息业务实现)
注意,为了演示方便,没有连接数据库,临时创建了个成员变量 userInfoMap 来模拟数据库存储。
import mydlq.club.example.entity.UserInfo;import mydlq.club.example.service.UserInfoService;import org.springframework.beans.BeanUtils;import org.springframework.cache.annotation.CacheConfig;import org.springframework.cache.annotation.CacheEvict;import org.springframework.cache.annotation.CachePut;import org.springframework.cache.annotation.Cacheable;import org.springframework.stereotype.Service;import java.util.HashMap;@Service@CacheConfig(cacheNames = "userInfo")public class UserInfoServiceImpl implements UserInfoService { private HashMap<String, UserInfo> userInfoMap = new HashMap<>(); @Override public void addUserInfo(UserInfo userInfo) { userInfoMap.put(userInfo.getName(), userInfo); } @Override @Cacheable(key = "#name", unless = "#result==null") public UserInfo getByName(String name) { if (!userInfoMap.containsKey(name)) { return null; } return userInfoMap.get(name); } @Override @CachePut(key = "#userInfo.name") public UserInfo updateUserInfo(UserInfo userInfo) { if (!userInfoMap.containsKey(userInfo.getName())) { throw new RuntimeException("该用户信息没有找到"); } // 获取存储的对象 UserInfo newUserInfo = userInfoMap.get(userInfo.getName()); // 复制要更新的数据到新对象,因为不能更改用户名信息,所以忽略 BeanUtils.copyProperties(userInfo, newUserInfo, "name"); // 将新的对象存储,更新旧对象信息 userInfoMap.put(newUserInfo.getName(), newUserInfo); // 返回新对象信息 return newUserInfo; } @Override @CacheEvict(key = "#name") public void deleteByName(String name) { userInfoMap.remove(name); }}
7、创建 Controller
UserController
import mydlq.club.example.entity.User;import mydlq.club.example.service.UserService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;/** * 用户 Controller */@RestControllerpublic class UserController { @Autowired private UserService userService; @GetMapping("/user/{username}") public User getUser(@PathVariable String username) { return userService.getUserByUsername(username); } @PostMapping("/user") public String createUser(@RequestBody User user) { userService.addUser(user); return "SUCCESS"; } @PutMapping("/user") public User updateUser(@RequestBody User user) { return userService.updateUser(user); } @DeleteMapping("/user/{username}") public String deleteUser(@PathVariable String username) { userService.deleteByUsername(username); return "SUCCESS"; }}
UserInfoController
import mydlq.club.example.entity.UserInfo;import mydlq.club.example.service.UserInfoService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;/** * 用户信息 Controller */@RestControllerpublic class UserInfoController { @Autowired private UserInfoService userInfoService; @GetMapping("/userInfo/{name}") public UserInfo getUserInfo(@PathVariable String name) { return userInfoService.getByName(name); } @PostMapping("/userInfo") public String createUserInfo(@RequestBody UserInfo userInfo) { userInfoService.addUserInfo(userInfo); return "SUCCESS"; } @PutMapping("/userInfo") public UserInfo updateUserInfo(@RequestBody UserInfo userInfo) { return userInfoService.updateUserInfo(userInfo); } @DeleteMapping("/userInfo/{name}") public String deleteUserInfo(@PathVariable String name) { userInfoService.deleteByName(name); return "SUCCESS"; }}
8、启动类
启动类中添加 @EnableCaching 注解开启缓存。
SpringBoot 结合 Spring Cache 操作 Redis 实现数据缓存
标签:增加 oms username div mod gen 工具 灵活 manage
原文地址:https://www.cnblogs.com/CQqfjy/p/12394098.html