J2Cache 知识点总结

J2Cache 知识点总结,第1张

J2Cache 知识点总结

一个简洁的博客网站: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 中清除指定的缓存信息

2. 构建测试环境

    创建一个 Spring Boot 项目,引入缓存所需要的依赖

    Spring Boot 版本:2.2.5.RELEASE


    org.springframework.boot
    spring-boot-starter-data-redis


    org.springframework.boot
    spring-boot-starter-cache


    org.springframework.boot
    spring-boot-starter-web


    mysql
    mysql-connector-java
    runtime


    com.baomidou
    mybatis-plus-boot-starter
    3.5.0


    org.springframework.boot
    spring-boot-starter-test
    test


    org.projectlombok
    lombok
    1.18.22


    org.junit.jupiter
    junit-jupiter
    RELEASE
    test



    com.alibaba
    fastjson
    1.2.60


    net.oschina.j2cache
    j2cache-spring-boot2-starter
    2.7.6-release


    net.oschina.j2cache
    j2cache-core
    2.8.2-release
    
        
            org.slf4j
            slf4j-simple
        
        
            org.slf4j
            slf4j-api
        
        
            com.alibaba
            fastjson
        
        
            redis.clients
            jedis
        
    


    redis.clients
    jedis
    2.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 FastJsonRedisSerializer implements 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 RedisTemplate redisTemplate() {
        FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
        RedisTemplate redisTemplate = new RedisTemplate<>();
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(fastJsonRedisSerializer);
        redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        return redisTemplate;
    }
    @Bean
    public CacheChannel channel() {
        CacheChannel channel = null;
        try {
            String configUrl = environment.resolvePlaceholders("${j2cache.config-location}");
            J2CacheConfig config = J2CacheConfig.initFromConfig(configUrl);
            J2CacheBuilder j2CacheBuilder = J2CacheBuilder.init(config);
            channel = j2CacheBuilder.getChannel();
//            log.info("j2cache建立CacheChannel成功->" + "configUrl->" + configUrl + " 一级缓存->" + config.getL1CacheName() + " 二级缓存->" + config.getL2CacheName());
        } catch (IOException e) {
//            log.error("j2cache建立CacheChannel报错->" + e);
        }
        return channel;
    }
}
 
    数据库对应的实体类 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!!!

有什么不对的地方欢迎大家留言

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5708197.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-18

发表评论

登录后才能评论

评论列表(0条)