欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

J2Cache整合springboot

程序员文章站 2022-04-28 18:30:58
...

J2Cache

框架介绍

J2Cache是一个两级缓存框架(要求至少 Java 8)。第一级缓存使用内存(同时支持 Ehcache 2.x、Ehcache 3.x 和 Caffeine),第二级缓存使用 Redis(推荐)/Memcached**(默认使用Caffeine作为一级缓存,使用redis作为二级缓存)** 。主要用于集群环境中。

为什么要使用J2Cache框架

  1. 仅适用内存缓存时:一旦应用重启后,由于缓存数据丢失,缓存雪崩,给数据库造成巨大压力,导致应用堵塞,多个应用节点无法共享缓存数据
  2. 仅使用集中式缓存,由于大量的数据通过缓存获取,导致缓存服务的数据吞吐量太大,带宽跑满。现象就是 Redis 服务负载不高,但是由于机器网卡带宽跑满,导致数据读取非常慢

框架作用

主要为了在读取缓存时先读取本地缓存,减少网络io,避免因为网络io造成的性能瓶颈。

J2Cache使用注意事项

应用节点内存占用问题:

  • 可通过配置来控制内存中存储数据量,避免内存溢出

各个节点数据一致性问题:

  • J2Cache 目前提供两种节点间数据同步的方案 —— Redis Pub/Sub 和 JGroups 。当某个节点的缓存数据需要更新时,J2Cache 会通过 Redis 的消息订阅机制或者是 JGroups 的组播来通知集群内其他节点。当其他节点收到缓存数据更新的通知时,它会清掉自己内存里的数据,然后重新从 Redis 中读取最新数据。(节点之间传输的仅仅是缓存的Key,相比Ehcache 的集群模式,J2Cache 要传输的数据极其小,对节点间的数据通信完全不会产生大的影响)

springboot整合J2Cache

  • pom文件

    <!--j2cache依赖-->
            <!--fastjson如果外部未导入,请勿排除-->
            <dependency>
                <groupId>net.oschina.j2cache</groupId>
                <artifactId>j2cache-spring-boot2-starter</artifactId>
                <version>2.7.6-release</version>
          </dependency>
            <dependency>
                <groupId>net.oschina.j2cache</groupId>
                <artifactId>j2cache-core</artifactId>
                <version>2.7.8-release</version>
                <exclusions>
                    <exclusion>
                        <groupId>org.slf4j</groupId>
                        <artifactId>slf4j-simple</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>org.slf4j</groupId>
                        <artifactId>slf4j-api</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>com.alibaba</groupId>
                        <artifactId>fastjson</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
    
  • j2cache配置文件
    application.yml
    spring:
      profiles:
        active: dev
      cache:
        type: none
    j2cache:
      config-location: classpath:/config/j2cache-${spring.profiles.active}-multi.properties
      open-spring-cache: true
      redis-client: lettuce
    

    j2cache-dev–multi.properties

    j2cache.broadcast = redis
    j2cache.L1.provider_class = caffeine
    j2cache.L2.provider_class = redis
    j2cache.sync_ttl_to_redis = true
    j2cache.default_cache_null_object = true
    j2cache.serialization = json
    caffeine.properties = /config/caffeine.properties
    redis.mode = single
    redis.storage = generic
    redis.channel = j2cache
    redis.channel.host =
    redis.cluster_name = j2cache
    redis.namespace =
    redis.hosts = 192.168.200.128:6379
    redis.timeout = 2000
    redis.password =
    redis.database = 0
    redis.ssl = false
    ## redis pool properties
    redis.maxTotal = 100
    redis.maxIdle = 10
    redis.maxWaitMillis = 5000
    redis.minEvictableIdleTimeMillis = 60000
    redis.minIdle = 1
    redis.numTestsPerEvictionRun = 10
    redis.lifo = false
    redis.softMinEvictableIdleTimeMillis = 10
    redis.testOnBorrow = true
    redis.testOnReturn = false
    redis.testWhileIdle = true
    redis.timeBetweenEvictionRunsMillis = 300000
    redis.blockWhenExhausted = false
    redis.jmxEnabled = false
    

    caffeine.properties

    #########################################
    # Caffeine configuration
    # [name] = size, xxxx[s|m|h|d]
    # size是region中存放key的个数,如果此配置文件没有配置region,跟随default的配置;
    #########################################
    default=1000, 10s
    testCache=10000, 6s
    student=2,5d
    
  • 核心代码

    @Service
    public class StudentServiceImpl implements StudentService {
    
        @Autowired
        private StudentMapper studentMapper;
        //j2cache核心对象
        @Autowired
        private CacheChannel cacheChannel;
    
        @Override
        public void addStudent(Student student) {
            studentMapper.insert(student);
        }
    
        @Override
        public void deleteStudentById(Integer id) {
            //studentMapper.deleteByPrimaryKey(id);
            cacheChannel.evict("student",id.toString());
        }
    
        @Override
        public Student selectStudentById(Integer id) {
            CacheObject cache = cacheChannel.get("student", id.toString());
            System.out.println(cache);
            if (cache.getValue() != null) return (Student)cache.getValue();
            Student student = studentMapper.selectByPrimaryKey(id);
            cacheChannel.set("student",student.getId().toString(),student);
            return student;
        }
    
        @Override
        public void updateStudent(Student student) {
            studentMapper.updateByPrimaryKeySelective(student);
            cacheChannel.set("student",student.getId().toString(),student);
        }
    }