SpringBoot(五)

发布时间 2023-03-26 00:14:44作者: 22-10-21

5.整合第三方技术

5.1缓存

缓存是一种介于数据永久存储介质与应用程序之间的数据临时存储介质,使用缓存可以有效的减少低速数据读取过程的次数(例如磁盘IO),提高系统性能。此外缓存不仅可以用于提高永久性存储介质的数据读取效率,还可以提供临时的数据存储空间。而springboot提供了对市面上几乎所有的缓存技术进行整合的方案

  • 企业级应用主要作用是信息处理,当需要读取数据时,由于受限于数据库的访问效率,导致整体系统性能偏低。

    image-20220226154148303
    • 应用程序直接与数据库打交道,访问效率低
  • 为了改善上述现象,开发者通常会在应用程序与数据库之间建立一种临时的数据存储机制,该区域中的数据在内存中保存,读写速度较快,可以有效解决数据库访问效率低下的问题。这一块临时存储数据的区域就是缓存。

    image-20220226154233010
    • 使用缓存后,应用程序与缓存打交道,缓存与数据库打交道,数据访问效率提高

①SpringBoot内置缓存解决方案

springboot技术提供有内置的缓存解决方案,可以帮助开发者快速开启缓存技术,并使用缓存技术进行数据的快速操作,例如读取缓存数据和写入数据到缓存。

  1. 导入springboot提供的缓存技术对应的starter

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-cache</artifactId>
    </dependency>
    
  2. 启用缓存,在引导类上方标注注解@EnableCaching配置springboot程序中可以使用缓存

    @SpringBootApplication
    //开启缓存功能
    @EnableCaching
    public class Springboot19CacheApplication {
        public static void main(String[] args) {
            SpringApplication.run(Springboot19CacheApplication.class, args);
        }
    }
    
  3. 设置操作的数据是否使用缓存

    @Service
    public class BookServiceImpl implements BookService {
        @Autowired
        private BookDao bookDao;
    	/*@Cacheable声明当前方法的返回值放入缓存中,其中要指定缓存的存储位置,以	  及缓存中保存当前方法返回值对应的名称。
    	value属性描述缓存的存储位置,可以理解为是一个存储空间名
    	key属性描述了缓存中保存数据的名称,使用#id读取形参中的id值作为缓存名称*/
        @Cacheable(value="cacheSpace",key="#id")
        public Book getById(Integer id) {
            return bookDao.selectById(id);
        }
    }
    

    使用@Cacheable注解后,执行当前操作,如果发现对应名称在缓存中没有数据,就正常读取数据,然后放入缓存;如果对应名称在缓存中有数据,就终止当前业务方法执行,直接返回缓存中的数据。

②SpringBoot整合Ehcache缓存

Ehcache是一种缓存技术,使用springboot整合Ehcache其实就是变更一下缓存技术的实现方式

  1. 导入Ehcache的坐标

    <dependency>
        <groupId>net.sf.ehcache</groupId>
        <artifactId>ehcache</artifactId>
    </dependency>
    

    此处为什么不是导入Ehcache的starter,而是导入技术坐标呢?其实springboot整合缓存技术做的是通用格式,不管你整合哪种缓存技术,只是实现变化了,操作方式一样。这也体现出springboot技术的优点,统一同类技术的整合方式。

  2. 配置缓存技术实现使用Ehcache

    spring:
      cache:
        type: ehcache
        ehcache:
          config: ehcache.xml
    
    • 配置缓存的类型type为ehcache,此处需要说明一下,当前springboot可以整合的缓存技术中包含有ehcach,所以可以这样书写。其实这个type不可以随便写的,不是随便写一个名称就可以整合的。

    • 由于ehcache的配置有独立的配置文件格式,因此还需要指定ehcache的配置文件,以便于读取相应配置

      <?xml version="1.0" encoding="UTF-8"?>
      <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
               updateCheck="false">
          <diskStore path="D:\ehcache" />
      
          <!--默认缓存策略 -->
          <!-- external:是否永久存在,设置为true则不会被清除,此时与timeout冲突,通常设置为false-->
          <!-- diskPersistent:是否启用磁盘持久化-->
          <!-- maxElementsInMemory:最大缓存数量-->
          <!-- overflowToDisk:超过最大缓存数量是否持久化到磁盘-->
          <!-- timeToIdleSeconds:最大不活动间隔,设置过长缓存容易溢出,设置过短无效果,可用于记录时效性数据,例如验证码-->
          <!-- timeToLiveSeconds:最大存活时间-->
          <!-- memoryStoreEvictionPolicy:缓存清除策略-->
          <defaultCache
              eternal="false"
              diskPersistent="false"
              maxElementsInMemory="1000"
              overflowToDisk="false"
              timeToIdleSeconds="60"
              timeToLiveSeconds="60"
              memoryStoreEvictionPolicy="LRU" />
      
          <cache
              name="smsCode"
              eternal="false"
              diskPersistent="false"
              maxElementsInMemory="1000"
              overflowToDisk="false"
              timeToIdleSeconds="10"
              timeToLiveSeconds="10"
              memoryStoreEvictionPolicy="LRU" />
      </ehcache>
      

③SpringBoot整合Redis缓存

使用Ehcache的过程,加坐标,改缓存实现类型为ehcache,做Ehcache的配置。如果还成redis做缓存呢?

一模一样,加坐标,改缓存实现类型为redis,做redis的配置。差别之处只有一点,redis的配置可以在yml文件中直接进行配置,无需制作独立的配置文件。

  1. 导入redis的坐标

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    
  2. 配置缓存技术实现使用redis

    spring:
      redis:
        host: localhost
        port: 6379
      cache:
        type: redis
    
    • 如果需要对redis作为缓存进行配置,注意不是对原始的redis进行配置,而是配置redis作为缓存使用相关的配置,隶属于spring.cache.redis节点下,注意不要写错位置了。

      spring:
        redis:
          host: localhost
          port: 6379
        cache:
          type: redis
          redis:
            use-key-prefix: false
            key-prefix: sms_
            cache-null-values: false
            time-to-live: 10s
      

④SpringBoot整合Memcached缓存

springboot并没有支持使用memcached作为其缓存解决方案,也就是说在type属性中没有memcached的配置选项,这里就需要更变一下处理方式了。在整合之前先安装memcached。

安装

windows版安装包下载地址:https://www.runoob.com/memcached/window-install-memcached.html

  1. 下载的安装包是解压缩就能使用的zip文件,解压缩完毕后会得到如下文件

    image-20220226174957040

  2. 可执行文件只有一个memcached.exe,使用该文件可以将memcached作为系统服务启动,执行此文件时会出现报错信息

    image-20220226175141986
  3. 此处出现问题的原因是注册系统服务时需要使用管理员权限,当前账号权限不足导致安装服务失败,切换管理员账号权限启动命令行

    image-20220226175302903
  4. 然后再次执行安装服务的命令即可

    memcached.exe -d install
    
  5. 服务安装完毕后可以启动和停止服务

    1. 命令行启动和停止

      memcached.exe -d start		# 启动服务
      memcached.exe -d stop		# 停止服务
      
    2. 任务管理器启动和停止

      image-20220226175441675
变更缓存为Memcached

memcached目前提供有三种客户端技术,分别是Memcached Client for Java、SpyMemcached和Xmemcached,其中性能指标各方面最好的客户端是Xmemcached,本次整合就使用这个作为客户端实现技术了。

  1. 导入xmemcached的坐标

    <dependency>
        <groupId>com.googlecode.xmemcached</groupId>
        <artifactId>xmemcached</artifactId>
        <version>2.4.7</version>
    </dependency>
    
  2. 配置memcached,制作memcached的配置类

    @Configuration
    public class XMemcachedConfig {
        @Bean
        public MemcachedClient getMemcachedClient() throws IOException {
            //memcached默认对外服务端口11211。
            MemcachedClientBuilder memcachedClientBuilder = new XMemcachedClientBuilder("localhost:11211");
            MemcachedClient memcachedClient = memcachedClientBuilder.build();
            return memcachedClient;
        }
    }
    
  3. 使用xmemcached客户端操作缓存,注入MemcachedClient对象

    @Service
    public class SMSCodeServiceImpl implements SMSCodeService {
        @Autowired
        private CodeUtils codeUtils;
        @Autowired
        private MemcachedClient memcachedClient;
    
        public String sendCodeToSMS(String tele) {
            String code = codeUtils.generator(tele);
            try {
                memcachedClient.set(tele,10,code);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return code;
        }
    
        public boolean checkCode(SMSCode smsCode) {
            String code = null;
            try {
                code = memcachedClient.get(smsCode.getTele()).toString();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return smsCode.getCode().equals(code);
        }
    }
    
定义配置属性
  1. 定义配置类,加载必要的配置属性,读取配置文件中memcached节点信息

    @Component
    @ConfigurationProperties(prefix = "memcached")
    @Data
    public class XMemcachedProperties {
        private String servers;
        private int poolSize;
        private long opTimeout;
    }
    
  2. 定义memcached节点信息

    memcached:
      servers: localhost:11211
      poolSize: 10
      opTimeout: 3000
    
  3. 在memcached配置类中加载信息

    @Configuration
    public class XMemcachedConfig {
        @Autowired
        private XMemcachedProperties props;
        @Bean
        public MemcachedClient getMemcachedClient() throws IOException {
            MemcachedClientBuilder memcachedClientBuilder = new XMemcachedClientBuilder(props.getServers());
            memcachedClientBuilder.setConnectionPoolSize(props.getPoolSize());
            memcachedClientBuilder.setOpTimeout(props.getOpTimeout());
            MemcachedClient memcachedClient = memcachedClientBuilder.build();
            return memcachedClient;
        }
    }
    

⑤SpringBoot整合jetcache缓存

jetcache严格意义上来说,并不是一个缓存解决方案,只能说他算是一个缓存框架,然后把别的缓存放到jetcache中管理,这样就可以支持两个缓存一起用了。并且jetcache参考了springboot整合缓存的思想,整体技术使用方式和springboot的缓存解决方案思想非常类似。

做之前要先明确一下,jetcache并不是随便拿两个缓存都能拼到一起去的。目前jetcache支持的缓存方案本地缓存支持两种,远程缓存支持两种

  • 本地缓存(Local)
    • LinkedHashMap
    • Caffeine
  • 远程缓存(Remote)
    • Redis
    • Tair
纯远程方案
  1. 导入springboot整合jetcache对应的坐标starter,当前坐标默认使用的远程方案是redis

    <dependency>
        <groupId>com.alicp.jetcache</groupId>
        <artifactId>jetcache-starter-redis</artifactId>
        <version>2.6.2</version>
    </dependency>
    
  2. 远程方案基本配置

    jetcache:
      remote:
      	#其中default是个名字,也可以起其他的名字,也可以添加第二种缓存模式,按照这个格式配置即可,使用时在注解`@CreateCache`的name前面添加一个参数area="你起的名字即可"
        default:
          type: redis
          host: localhost
          port: 6379
          #poolConfig是必配项,否则会报错
          poolConfig:
            maxTotal: 50
    
  3. 启用缓存,在引导类上方标注注解@EnableCreateCacheAnnotation配置springboot程序中可以使用注解的形式创建缓存

    @SpringBootApplication
    //jetcache启用缓存的主开关
    @EnableCreateCacheAnnotation
    public class Springboot20JetCacheApplication {
        public static void main(String[] args) {
            SpringApplication.run(Springboot20JetCacheApplication.class, args);
        }
    }
    
  4. 创建缓存对象Cache,并使用注解@CreateCache标记当前缓存的信息,然后使用Cache对象的API操作缓存,put写缓存,get读缓存。

    @Service
    public class SMSCodeServiceImpl implements SMSCodeService {
        @Autowired
        private CodeUtils codeUtils;
        /*这里的name和上面的default要相对应,其中,当设置的为default时,一般为jetCanche_,此处的下划线一定要带,或者改为::,如果是area设置的名字则不用带下划线
        expire属性指定了缓存过期时间,timeUnit属性指定了过期时间的单位为秒。*/
        @CreateCache(name="jetCache_",expire = 10,timeUnit = TimeUnit.SECONDS)
        private Cache<String ,String> jetCache;
    
        public String sendCodeToSMS(String tele) {
            String code = codeUtils.generator(tele);
            jetCache.put(tele,code);
            return code;
        }
        public boolean checkCode(SMSCode smsCode) {
            String code = jetCache.get(smsCode.getTele());
            return smsCode.getCode().equals(code);
        }
    }
    
纯本地方案

远程方案中,配置中使用remote表示远程,换成local就是本地,只不过类型不一样而已。

  1. 导入springboot整合jetcache对应的坐标starter

    <dependency>
        <groupId>com.alicp.jetcache</groupId>
        <artifactId>jetcache-starter-redis</artifactId>
        <version>2.6.2</version>
    </dependency>
    
  2. 本地缓存基本配置

    jetcache:
      local:
        default:
          type: linkedhashmap
          #为了加速数据获取时key的匹配速度,jetcache要求指定key的类型转换器。
          #简单说就是,如果你给了一个Object作为key的话,我先用key的类型转换器给转换成字符串,然后再保存。
          #等到获取数据时,仍然是先使用给定的Object转换成字符串,然后根据字符串匹配。
          #由于jetcache是阿里的技术,这里推荐key的类型转换器使用阿里的fastjson。
          keyConvertor: fastjson
    
  3. 启用缓存

    @SpringBootApplication
    //jetcache启用缓存的主开关
    @EnableCreateCacheAnnotation
    public class Springboot20JetCacheApplication {
        public static void main(String[] args) {
            SpringApplication.run(Springboot20JetCacheApplication.class, args);
        }
    }
    
  4. 创建缓存对象Cache时,标注当前使用本地缓存

    @Service
    public class SMSCodeServiceImpl implements SMSCodeService {
        //cacheType控制当前缓存使用本地缓存还是远程缓存,配置cacheType=CacheType.LOCAL即使用本地缓存。
        @CreateCache(name="jetCache_",expire = 1000,timeUnit = TimeUnit.SECONDS,cacheType = CacheType.LOCAL)
        private Cache<String ,String> jetCache;
    
        public String sendCodeToSMS(String tele) {
            String code = codeUtils.generator(tele);
            jetCache.put(tele,code);
            return code;
        }
    
        public boolean checkCode(SMSCode smsCode) {
            String code = jetCache.get(smsCode.getTele());
            return smsCode.getCode().equals(code);
        }
    }
    
本地+远程方案

本地和远程方法都有了,两种方案一起使用如何配置呢?其实就是将两种配置合并到一起就可以了。

  1. 导入坐标

    <dependency>
        <groupId>com.alicp.jetcache</groupId>
        <artifactId>jetcache-starter-redis</artifactId>
        <version>2.6.2</version>
    </dependency>
    <dependency>
        <groupId>com.alicp.jetcache</groupId>
        <artifactId>jetcache-starter-redis</artifactId>
        <version>2.6.2</version>
    </dependency>
    
  2. 配置

    jetcache:
      local:
        default:
          type: linkedhashmap
          keyConvertor: fastjson
      remote:
        default:
          type: redis
          host: localhost
          port: 6379
          poolConfig:
            maxTotal: 50
        sms:
          type: redis
          host: localhost
          port: 6379
          poolConfig:
            maxTotal: 50
    
  3. 在创建缓存的时候,配置cacheType为BOTH即则本地缓存与远程缓存同时使用。

    @Service
    public class SMSCodeServiceImpl implements SMSCodeService {
        //cacheType如果不进行配置,默认值是REMOTE,即仅使用远程缓存方案。
        @CreateCache(name="jetCache_",expire = 1000,timeUnit = TimeUnit.SECONDS,cacheType = CacheType.BOTH)
        private Cache<String ,String> jetCache;
    }
    

    关于jetcache的配置,参考以下信息

    属性 默认值 说明
    jetcache.statIntervalMinutes 0 统计间隔,0表示不统计
    jetcache.hiddenPackages 自动生成name时,隐藏指定的包名前缀
    jetcache.[local|remote].${area}.type 缓存类型,本地支持linkedhashmap、caffeine,远程支持redis、tair
    jetcache.[local|remote].${area}.keyConvertor key转换器,当前仅支持fastjson
    jetcache.[local|remote].${area}.valueEncoder java 仅remote类型的缓存需要指定,可选java和kryo
    jetcache.[local|remote].${area}.valueDecoder java 仅remote类型的缓存需要指定,可选java和kryo
    jetcache.[local|remote].${area}.limit 100 仅local类型的缓存需要指定,缓存实例最大元素数
    jetcache.[local|remote].${area}.expireAfterWriteInMillis 无穷大 默认过期时间,毫秒单位
    jetcache.local.${area}.expireAfterAccessInMillis 0 仅local类型的缓存有效,毫秒单位,最大不活动间隔

    以上方案仅支持手工控制缓存,但是springcache方案中的方法缓存特别好用,给一个方法添加一个注解,方法就会自动使用缓存。jetcache也提供了对应的功能,即方法缓存。

方法缓存

jetcache提供了方法缓存方案,只不过名称变更了而已。在对应的操作接口上方使用注解@Cached即可

  1. 导入springboot整合jetcache对应的坐标starter

    <dependency>
        <groupId>com.alicp.jetcache</groupId>
        <artifactId>jetcache-starter-redis</artifactId>
        <version>2.6.2</version>
    </dependency>
    
  2. 配置缓存

    jetcache:
      local:
        default:
          type: linkedhashmap
          keyConvertor: fastjson
      remote:
        default:
          type: redis
          host: localhost
          port: 6379
          keyConvertor: fastjson
          valueEncode: java
          valueDecode: java
          poolConfig:
            maxTotal: 50
        sms:
          type: redis
          host: localhost
          port: 6379
          poolConfig:
            maxTotal: 50
    
    • 由于redis缓存中不支持保存对象,因此需要对redis设置当Object类型数据进入到redis中时如何进行类型转换。需要配置keyConvertor表示key的类型转换方式,同时标注value的转换类型方式,值进入redis时是java类型,标注valueEncode为java,值从redis中读取时转换成java,标注valueDecode为java。

    • 注意,为了实现Object类型的值进出redis,需要保障进出redis的Object类型的数据必须实现序列化接口。

      @Data
      public class Book implements Serializable {
          private Integer id;
          private String type;
          private String name;
          private String description;
      }
      
  3. 启用缓存时开启方法缓存功能,并配置basePackages,说明在哪些包中开启方法缓存

    @SpringBootApplication
    //jetcache启用缓存的主开关
    @EnableCreateCacheAnnotation
    //开启方法注解缓存
    @EnableMethodCache(basePackages = "com.itheima")
    public class Springboot20JetCacheApplication {
        public static void main(String[] args) {
            SpringApplication.run(Springboot20JetCacheApplication.class, args);
        }
    }
    
  4. 使用注解@Cached标注当前方法使用缓存

    @Service
    public class BookServiceImpl implements BookService {
        @Autowired
        private BookDao bookDao;
        
        @Override
        @Cached(name="book_",key="#id",expire = 3600,cacheType = CacheType.REMOTE)
        public Book getById(Integer id) {
            return bookDao.selectById(id);
        }
    }
    
远程方案的数据同步

由于远程方案中redis保存的数据可以被多个客户端共享,这就存在了数据同步问题。jetcache提供了3个注解解决此问题,分别在更新、删除操作时同步缓存数据,和读取缓存时定时刷新数据

  1. 更新缓存

    @CacheUpdate(name="book_",key="#book.id",value="#book")
    public boolean update(Book book) {
        return bookDao.updateById(book) > 0;
    }
    
  2. 删除缓存

    @CacheInvalidate(name="book_",key = "#id")
    public boolean delete(Integer id) {
        return bookDao.deleteById(id) > 0;
    }
    
  3. 定时刷新缓存

    @Cached(name="book_",key="#id",expire = 3600,cacheType = CacheType.REMOTE)
    @CacheRefresh(refresh = 5)
    public Book getById(Integer id) {
        return bookDao.selectById(id);
    }
    
数据报表
  • jetcache还提供有简单的数据报表功能,帮助开发者快速查看缓存命中信息,只需要添加一个配置即可

    jetcache:
      statIntervalMinutes: 1
    
  • 设置后,每1分钟在控制台输出缓存数据命中信息

    [DefaultExecutor] c.alicp.jetcache.support.StatInfoLogger  : jetcache stat from 2022-02-28 09:32:15,892 to 2022-02-28 09:33:00,003
    cache    |    qps|   rate|   get|    hit|   fail|   expire|   avgLoadTime|   maxLoadTime
    ---------+-------+-------+------+-------+-------+---------+--------------+--------------
    book_    |   0.66| 75.86%|    29|     22|      0|        0|          28.0|           188
    ---------+-------+-------+------+-------+-------+---------+--------------+--------------
    

⑥SpringBoot整合j2cache缓存

​ jetcache可以在限定范围内构建多级缓存,但是灵活性不足,不能随意搭配缓存,本节介绍一种可以随意搭配缓存解决方案的缓存整合框架,j2cache。

以Ehcache与redis整合为例

  1. 导入j2cache、redis、ehcache坐标

    <dependency>
        <groupId>net.oschina.j2cache</groupId>
        <artifactId>j2cache-core</artifactId>
        <version>2.8.4-release</version>
    </dependency>
    <dependency>
        <groupId>net.oschina.j2cache</groupId>
        <artifactId>j2cache-spring-boot2-starter</artifactId>
        <version>2.8.0-release</version>
    </dependency>
    <dependency>
        <groupId>net.sf.ehcache</groupId>
        <artifactId>ehcache</artifactId>
    </dependency>
    

    j2cache的starter中默认包含了redis坐标,官方推荐使用redis作为二级缓存,因此此处无需导入redis坐标

  2. 配置一级与二级缓存,并配置一二级缓存间数据传递方式,配置书写在名称为j2cache.properties的文件中。如果使用ehcache还需要单独添加ehcache的配置文件

    # 1级缓存
    j2cache.L1.provider_class = ehcache
    ehcache.configXml = ehcache.xml
    
    # 2级缓存
    j2cache.L2.provider_class = net.oschina.j2cache.cache.support.redis.SpringRedisProvider
    j2cache.L2.config_section = redis
    redis.hosts = localhost:6379
    
    # 1级缓存中的数据如何到达二级缓存
    j2cache.broadcast = net.oschina.j2cache.cache.support.redis.SpringRedisPubSubPolicy
    
    • 此处配置不能乱配置,需要参照官方给出的配置说明进行。例如1级供应商选择ehcache,供应商名称仅仅是一个ehcache,但是2级供应商选择redis时要写专用的Spring整合Redis的供应商类名SpringRedisProvider,而且这个名称并不是所有的redis包中能提供的,也不是spring包中提供的。因此配置j2cache必须参照官方文档配置,而且还要去找专用的整合包,导入对应坐标才可以使用。

    • 一级与二级缓存最重要的一个配置就是两者之间的数据沟通方式,此类配置也不是随意配置的,并且不同的缓存解决方案提供的数据沟通方式差异化很大,需要查询官方文档进行设置。

  3. 使用缓存

    @Service
    public class SMSCodeServiceImpl implements SMSCodeService {
        @Autowired
        private CodeUtils codeUtils;
    
        @Autowired
        private CacheChannel cacheChannel;
    
        public String sendCodeToSMS(String tele) {
            String code = codeUtils.generator(tele);
            cacheChannel.set("sms",tele,code);
            return code;
        }
    
        public boolean checkCode(SMSCode smsCode) {
            String code = cacheChannel.get("sms",smsCode.getTele()).asString();
            return smsCode.getCode().equals(code);
        }
    }
    
    • j2cache的使用和jetcache比较类似,但是无需开启使用的开关,直接定义缓存对象即可使用,缓存对象名CacheChannel。

    • j2cache的使用不复杂,配置是j2cache的核心,毕竟是一个整合型的缓存框架。缓存相关的配置过多,可以查阅j2cache-core核心包中的j2cache.properties文件中的说明。

    #J2Cache configuration
    #########################################
    # Cache Broadcast Method
    # values:
    # jgroups -> use jgroups's multicast
    # redis -> use redis publish/subscribe mechanism (using jedis)
    # lettuce -> use redis publish/subscribe mechanism (using lettuce, Recommend)
    # rabbitmq -> use RabbitMQ publisher/consumer mechanism
    # rocketmq -> use RocketMQ publisher/consumer mechanism
    # none -> don't notify the other nodes in cluster
    # xx.xxxx.xxxx.Xxxxx your own cache broadcast policy classname that implement net.oschina.j2cache.cluster.ClusterPolicy
    #########################################
    j2cache.broadcast = redis
    
    # jgroups properties
    jgroups.channel.name = j2cache
    jgroups.configXml = /network.xml
    
    # RabbitMQ properties
    rabbitmq.exchange = j2cache
    rabbitmq.host = localhost
    rabbitmq.port = 5672
    rabbitmq.username = guest
    rabbitmq.password = guest
    
    # RocketMQ properties
    rocketmq.name = j2cache
    rocketmq.topic = j2cache
    # use ; to split multi hosts
    rocketmq.hosts = 127.0.0.1:9876
    
    #########################################
    # Level 1&2 provider
    # values:
    # none -> disable this level cache
    # ehcache -> use ehcache2 as level 1 cache
    # ehcache3 -> use ehcache3 as level 1 cache
    # caffeine -> use caffeine as level 1 cache(only in memory)
    # redis -> use redis as level 2 cache (using jedis)
    # lettuce -> use redis as level 2 cache (using lettuce)
    # readonly-redis -> use redis as level 2 cache ,but never write data to it. if use this provider, you must uncomment `j2cache.L2.config_section` to make the redis configurations available.
    # memcached -> use memcached as level 2 cache (xmemcached),
    # [classname] -> use custom provider
    #########################################
    
    j2cache.L1.provider_class = caffeine
    j2cache.L2.provider_class = redis
    
    # When L2 provider isn't `redis`, using `L2.config_section = redis` to read redis configurations
    # j2cache.L2.config_section = redis
    
    # Enable/Disable ttl in redis cache data (if disabled, the object in redis will never expire, default:true)
    # NOTICE: redis hash mode (redis.storage = hash) do not support this feature)
    j2cache.sync_ttl_to_redis = true
    
    # Whether to cache null objects by default (default false)
    j2cache.default_cache_null_object = true
    
    #########################################
    # Cache Serialization Provider
    # values:
    # fst -> using fast-serialization (recommend)
    # kryo -> using kryo serialization
    # json -> using fst's json serialization (testing)
    # fastjson -> using fastjson serialization (embed non-static class not support)
    # java -> java standard
    # fse -> using fse serialization
    # [classname implements Serializer]
    #########################################
    
    j2cache.serialization = json
    #json.map.person = net.oschina.j2cache.demo.Person
    
    #########################################
    # Ehcache configuration
    #########################################
    
    # ehcache.configXml = /ehcache.xml
    
    # ehcache3.configXml = /ehcache3.xml
    # ehcache3.defaultHeapSize = 1000
    
    #########################################
    # Caffeine configuration
    # caffeine.region.[name] = size, xxxx[s|m|h|d]
    #
    #########################################
    caffeine.properties = /caffeine.properties
    
    #########################################
    # Redis connection configuration
    #########################################
    
    #########################################
    # Redis Cluster Mode
    #
    # single -> single redis server
    # sentinel -> master-slaves servers
    # cluster -> cluster servers (数据库配置无效,使用 database = 0)
    # sharded -> sharded servers  (密码、数据库必须在 hosts 中指定,且连接池配置无效 ; redis://user:password@127.0.0.1:6379/0)
    #
    #########################################
    
    redis.mode = single
    
    #redis storage mode (generic|hash)
    redis.storage = generic
    
    ## redis pub/sub channel name
    redis.channel = j2cache
    ## redis pub/sub server (using redis.hosts when empty)
    redis.channel.host =
    
    #cluster name just for sharded
    redis.cluster_name = j2cache
    
    ## redis cache namespace optional, default[empty]
    redis.namespace =
    
    ## redis command scan parameter count, default[1000]
    #redis.scanCount = 1000
    
    ## connection
    # Separate multiple redis nodes with commas, such as 192.168.0.10:6379,192.168.0.11:6379,192.168.0.12:6379
    
    redis.hosts = 127.0.0.1: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
    
    #########################################
    # Lettuce scheme
    #
    # redis -> single redis server
    # rediss -> single redis server with ssl
    # redis-sentinel -> redis sentinel
    # redis-cluster -> cluster servers
    #
    #########################################
    
    #########################################
    # Lettuce Mode
    #
    # single -> single redis server
    # sentinel -> master-slaves servers
    # cluster -> cluster servers (数据库配置无效,使用 database = 0)
    # sharded -> sharded servers  (密码、数据库必须在 hosts 中指定,且连接池配置无效 ; redis://user:password@127.0.0.1:6379/0)
    #
    #########################################
    
    ## redis command scan parameter count, default[1000]
    #lettuce.scanCount = 1000
    lettuce.mode = single
    lettuce.namespace =
    lettuce.storage = hash
    lettuce.channel = j2cache
    lettuce.scheme = redis
    lettuce.hosts = 127.0.0.1:6379
    lettuce.password =
    lettuce.database = 0
    lettuce.sentinelMasterId =
    lettuce.maxTotal = 100
    lettuce.maxIdle = 10
    lettuce.minIdle = 10
    # timeout in milliseconds
    lettuce.timeout = 10000
    # redis cluster topology refresh interval in milliseconds
    lettuce.clusterTopologyRefresh = 3000
    
    #########################################
    # memcached server configurations
    # refer to https://gitee.com/mirrors/XMemcached
    #########################################
    
    memcached.servers = 127.0.0.1:11211
    memcached.username =
    memcached.password =
    memcached.connectionPoolSize = 10
    memcached.connectTimeout = 1000
    memcached.failureMode = false
    memcached.healSessionInterval = 1000
    memcached.maxQueuedNoReplyOperations = 100
    memcached.opTimeout = 100
    memcached.sanitizeKeys = false