一个简洁的博客网站:http://lss-coding.top,欢迎大家来访
学习娱乐导航页:http://miss123.top/
1. 简介
官方参考地址:https://gitee.com/ld/J2Cache
J2Cache —— 基于内存和 Redis 的两级 Java 缓存框架
J2Cache 是 OSChina 目前正在使用的两级缓存框架(要求至少 Java 8)。第一级缓存使用内存(同时支持 Ehcache 2.x、Ehcache 3.x 和 Caffeine),第二级缓存使用 Redis(推荐)/Memcached 。 由于大量的缓存读取会导致 L2 的网络成为整个系统的瓶颈,因此 L1 的目标是降低对 L2 的读取次数。 该缓存框架主要用于集群环境中。单机也可使用,用于避免应用重启导致的缓存冷启动后对后端业务的冲击。
数据读取
读取顺序 -> L1 -> L2 -> DB
数据更新
1 从数据库中读取最新数据,依次更新 L1 -> L2 ,发送广播清除某个缓存信息
2 接收到广播(手工清除缓存 & 一级缓存自动失效),从 L1 中清除指定的缓存信息
创建一个 Spring Boot 项目,引入缓存所需要的依赖
Spring Boot 版本:2.2.5.RELEASE
org.springframework.boot spring-boot-starter-data-redisorg.springframework.boot spring-boot-starter-cacheorg.springframework.boot spring-boot-starter-webmysql mysql-connector-javaruntime com.baomidou mybatis-plus-boot-starter3.5.0 org.springframework.boot spring-boot-starter-testtest org.projectlombok lombok1.18.22 org.junit.jupiter junit-jupiterRELEASE test com.alibaba fastjson1.2.60 net.oschina.j2cache j2cache-spring-boot2-starter2.7.6-release net.oschina.j2cache j2cache-core2.8.2-release org.slf4j slf4j-simpleorg.slf4j slf4j-apicom.alibaba fastjsonredis.clients jedisredis.clients jedis2.9.1 io.lettuce lettuce-core
- 创建一个 student-manager 数据库,创建表 user
CREATE TABLE `user` ( `id` bigint(10) NOT NULL, `name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8
- 在左侧源码部分找到 j2cache-core 包里面的 caffeine.properties、ehcache3.xml、j2cache.properties 三个配置文件复制到 resources 目录下
- application.yml 中配置数据源、redis、j2cache
spring: datasource: url: jdbc:mysql://localhost:3306/student-manager?userUnicode=true&characterEncoding=utf-8&serverTimezone=UTC username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver redis: host: 49.xxx.xxx.200 port: 6379 cache: type: none j2cache: config-location: /j2cache.properties redis-client: lettuce open-spring-cache: true
修改 caffeine.properties 中的 30m 为 30s,这个设置的是一级缓存的过期时间,30s 比较好进行测试修改 j2cache.properties 中的 redis 部分为自己的 redis 服务器的 ip 地址等信息ehcache3.xml 配置文件不需要动
创建 config、domain、mapper、service、impl、controller 各个分层的包,项目虽小,结构不能乱套
创建 FastJsonRedisSerializer 配置 Redis 存储的序列化
public class FastJsonRedisSerializerimplements RedisSerializer { public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; private Class clazz; public FastJsonRedisSerializer(Class clazz) { super(); this.clazz = clazz; } @Override public byte[] serialize(T t) throws SerializationException { if (t == null) { return new byte[0]; } return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); } @Override public T deserialize(byte[] bytes) throws SerializationException { if (bytes == null || bytes.length <= 0) { return null; } String str = new String(bytes, DEFAULT_CHARSET); return (T) JSON.parseObject(str, clazz); } }
- 创建 RedisConfig 配置类
@Configuration @Slf4j public class RedisConfig { @Autowired RedisConnectionFactory redisConnectionFactory; @Autowired Environment environment; @Bean(name = "redisTemplate") @ConditionalOnMissingBean(RedisTemplate.class) public RedisTemplateredisTemplate() { FastJsonRedisSerializer
- 数据库对应的实体类 User
@Data @AllArgsConstructor @NoArgsConstructor @TableName("user") public class User implements Serializable{ // 主键 用户id private Long id; // 用户名 private String name; }
- UserMapper 接口
@Mapper public interface UserMapper extends baseMapper{ }
- UserService 接口
public interface UserService { // 放入缓存 User getUser(Long id); // 清理缓存中的数据 public User userClear(Long id); }
- UserServiceImpl 接口实现类
@Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; // 加缓存 @Override @Cacheable(value = "userInfo", key = "#id") public User getUser(Long id) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String formatDate = simpleDateFormat.format(new Date()); System.out.println("访问数据库中的数据!!!" + formatDate); User user = userMapper.selectById(id); return user; } // 清缓存 @CacheEvict(value = "userInfo", key = "#id") public User userClear(Long id) { System.out.println("清理一级缓存中 id:" + id + "的数据"); User user = userMapper.selectById(id); return user; } }
- UserController
@RestController public class UserController { @Autowired private UserService userService; @RequestMapping("/user/{id}") public String getUserList(@PathVariable Long id) { System.out.println("查找id为:" + id + "的用户 " + new Date()); User user = null; try { user = userService.getUser(id); if (user == null) { return "您查询的用户不在!!!"; } return user.toString(); } catch (Exception e) { e.printStackTrace(); return "系统异常,请稍后重试!!!"; } } @RequestMapping("/user/clear/{id}") public String userClear(@PathVariable Long id) { System.out.println("清楚缓存id为:" + id + "的用户 " + new Date()); User user = null; try { user = userService.userClear(id); } catch (Exception e) { e.printStackTrace(); return "系统异常,请稍后重试!!!"; } return user.toString(); } }
至此测试项目的结构搭建完成
3. 启动项目进行测试- 当项目启动后,我们的一级缓存(jvm中) ehcache3 中是没有任何的缓存数据的,二级缓存 Redis 中也是没有数据的,所以当我们请求接口 http://localhost:8080/user/10001 的时候会先判断一级缓存没有数据,二级缓存没有数据,那么就会查询数据库中的数据来进行回显
Redis 中也会加入数据
- 当我们在数据库中对数据进行了修改的时候,我们再来请求,当一级缓存过期 访问数据库中的数据 的时候,就会进行缓存中数据的更新,同时 二级缓存 Redis 中的数据也会进行更新
这里的测试写的比较乱,大家可以参考上面给出的官方网址进行自行测试,我这里只是一个demo!!!
有什么不对的地方欢迎大家留言
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)