1.什么是缓存?
把一些经常访问的数据放入缓存中,减少访问数据库的频率,减少数据库的压力,从而提高程序的性能。【内存中存储】
2.缓存的原理
通过上图可以看出程序首先访问缓存,如果缓存中有访问的数据会直接方会给客户端,不需要访问数据库,如果缓存中没有需要的数据则访问数据库,命中后返回给客户端的同时存放到缓存当中,方便下次访问直接命中缓存,减少数据库的压力。
3.什么样的数据适合放入缓存中?
3.1 访问频率高且修改频率低的数据。
3.2 数据安全性低的数据。
4. 哪些组件可以用作缓存?
4.1 redis组件
4.2 memory组件
4.3 ehcache组件等
5.Java如何使用redis实现缓存功能?
package com.wzy.springrediscache.service.impl; import com.wzy.springrediscache.dao.UserDao; import com.wzy.springrediscache.entity.User; import com.wzy.springrediscache.service.UserService; import com.wzy.springrediscache.vo.R; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.stereotype.Service; /** * @program: spring-redisCache * @description: * @author: 顾安 * @create: 2024-07-25 09:49 **/ @Service public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Autowired private RedisTemplate redisTemplate; @Override public R getUser(Integer id) { ValueOperations<String, Object> forValue = redisTemplate.opsForValue(); Object o = forValue.get("user::" + id); //判断是否为空,如果不为空直接返回 if (o != null) { User user = (User) o; return new R(200, "success", user); } //缓存没有命中 User user = userDao.selectById(id); //判断数据库是否为空 if (user!=null){ //放入缓存中 forValue.set("user::"+id,user); } return new R(200,"查询成功",user); } //添加操作不适合做缓存 @Override public R add(User user) { int insert = userDao.insert(user); return new R(200,"添加成功",insert); } @Override public R update(User user) { int i = userDao.updateById(user); //判断是否为空 if (i>0){ //把修改后的对象放入缓存中 redisTemplate.opsForValue().set("user::"+user.getId(),user); } return new R(200,"修改成功",i); } @Override public R delete(Integer id) { int i = userDao.deleteById(id); //判断是否删除成功 if (i>0){ //删除缓存中的key redisTemplate.delete("user::"+id); } return new R(200,"删除成功",i); } }
使用这种可以方式实现缓存,但是业务代码除了需要维护核心业务功能外,还需要维护缓存的代码
还可以使用aop切面编程解决以上问题,spring提供了aop缓存注解
以下是配置注解的配置类
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// 配置序列化(解决乱码的问题),过期时间600秒
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(600)) //缓存过期10分钟 ---- 业务需求。
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))//设置key的序列化方式
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)) //设置value的序列化
.disableCachingNullValues();
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
return cacheManager;
}
并需要在启动类上加上@EnableCaching该注解
package com.wzy.springrediscache.service.impl; import com.wzy.springrediscache.dao.UserDao; import com.wzy.springrediscache.entity.User; import com.wzy.springrediscache.service.UserService; import com.wzy.springrediscache.vo.R; 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.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.stereotype.Service; /** * @program: spring-redisCache * @description: * @author: 顾安 * @create: 2024-07-25 09:49 **/ @Service public class UserServiceImpl01 implements UserService { @Autowired private UserDao userDao; @Autowired private RedisTemplate redisTemplate; //该注解用于查询 cacheNames 表示指定了缓存的名称 key 表示存入哪个条目的键 @Cacheable(cacheNames = "user",key = "#id") @Override public R getUser(Integer id) { User user = userDao.selectById(id); return new R(200,"查询成功",user); } @Override public R add(User user) { int insert = userDao.insert(user); return new R(200,"添加成功",insert); } //改注解用于修改 @CachePut(cacheNames = "user",key = "#user.id") @Override public R update(User user) { int i = userDao.updateById(user); return new R(200,"修改成功",i); } //该注解用于删除 @CacheEvict(cacheNames = "user",key = "#id") @Override public R delete(Integer id) { int i = userDao.deleteById(id); return new R(200,"删除成功",i); } }