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 {@Autowiredprivate UserDao userDao;@Autowiredprivate RedisTemplate redisTemplate;@Overridepublic 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);}//添加操作不适合做缓存@Overridepublic R add(User user) {int insert = userDao.insert(user);return new R(200,"添加成功",insert);}@Overridepublic R update(User user) {int i = userDao.updateById(user); //判断是否为空if (i>0){ //把修改后的对象放入缓存中redisTemplate.opsForValue().set("user::"+user.getId(),user);}return new R(200,"修改成功",i);}@Overridepublic R delete(Integer id) {int i = userDao.deleteById(id); //判断是否删除成功if (i>0){ //删除缓存中的keyredisTemplate.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 {@Autowiredprivate UserDao userDao;@Autowiredprivate RedisTemplate redisTemplate; //该注解用于查询 cacheNames 表示指定了缓存的名称 key 表示存入哪个条目的键@Cacheable(cacheNames = "user",key = "#id")@Overridepublic R getUser(Integer id) {User user = userDao.selectById(id);return new R(200,"查询成功",user);}@Overridepublic R add(User user) {int insert = userDao.insert(user);return new R(200,"添加成功",insert);} //改注解用于修改@CachePut(cacheNames = "user",key = "#user.id")@Overridepublic R update(User user) {int i = userDao.updateById(user);return new R(200,"修改成功",i);} //该注解用于删除@CacheEvict(cacheNames = "user",key = "#id")@Overridepublic R delete(Integer id) {int i = userDao.deleteById(id);return new R(200,"删除成功",i);} }