首页 > 其他分享 >jetcache缓存使用

jetcache缓存使用

时间:2024-08-12 19:48:51浏览次数:5  
标签:缓存 jetcache cache qz 使用 import com

1、简介

​ jetcache 是阿里开源的一个缓存框架,支持像guava的cache、caffeine的Cache 用法,也可以集成springboot,像spring的@Cache 注解一样进行使用。

​ jetcache的缓存类似于map,提供了get、put、putAll、computeIfAbsent等方法, 另外还提供了单机锁、分布式锁机制,一般也不用这个做锁就先不研究了。

2、简单使用

1、直接cache 用法

1、pom

<!-- https://mvnrepository.com/artifact/com.alicp.jetcache/jetcache-core -->
        <dependency>
            <groupId>com.alicp.jetcache</groupId>
            <artifactId>jetcache-core</artifactId>
            <version>2.6.7</version>
        </dependency>

2、简单用法

1》创建缓存的操作类似guava/caffeine cache,例如下面的代码创建基于内存的LinkedHashMapCache

package qz.jetcache;

import com.alicp.jetcache.Cache;
import com.alicp.jetcache.CacheConfig;
import com.alicp.jetcache.embedded.EmbeddedCacheConfig;
import com.alicp.jetcache.embedded.LinkedHashMapCacheBuilder;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;

@Slf4j
public class CacheClient {

    public static void main(String[] args) throws InterruptedException {
        Cache<String, String> cache = LinkedHashMapCacheBuilder.createLinkedHashMapCacheBuilder()
                .limit(20)
                .expireAfterWrite(10, TimeUnit.SECONDS)
                .buildCache();

        // 每个cache 都有个配置,包括缓存的大小、过期时间、刷新时间、刷新加载开关、刷新加载线程池、刷新加载策略、key/value转换器等
        CacheConfig<String, String> config = cache.config();

        // 第三个参数表示是否要缓存null值
        log.info(cache.computeIfAbsent("1", k -> doGetFromDB(k), true));
        log.info(cache.computeIfAbsent("1", k -> doGetFromDB(k), true));
        log.info(cache.computeIfAbsent("2", k -> doGetFromDB(k), true));
        log.info(cache.computeIfAbsent("2", k -> doGetFromDB(k), true));
        log.info(cache.computeIfAbsent("3", k -> doGetFromDB(k), false));
        log.info(cache.computeIfAbsent("3", k -> doGetFromDB(k), false));
        /**
         * 2024-08-01 16:35:36 [main] [qz.jetcache.CacheClient]-[INFO] doGetFromDB, key: 1
         * 2024-08-01 16:35:36 [main] [qz.jetcache.CacheClient]-[INFO] 1_1
         * 2024-08-01 16:35:36 [main] [qz.jetcache.CacheClient]-[INFO] 1_1
         * 2024-08-01 16:35:36 [main] [qz.jetcache.CacheClient]-[INFO] doGetFromDB, key: 2
         * 2024-08-01 16:35:36 [main] [qz.jetcache.CacheClient]-[INFO]
         * 2024-08-01 16:35:36 [main] [qz.jetcache.CacheClient]-[INFO]
         * 2024-08-01 16:35:36 [main] [qz.jetcache.CacheClient]-[INFO] doGetFromDB, key: 3
         * 2024-08-01 16:35:36 [main] [qz.jetcache.CacheClient]-[INFO]
         * 2024-08-01 16:35:36 [main] [qz.jetcache.CacheClient]-[INFO] doGetFromDB, key: 3
         * 2024-08-01 16:35:36 [main] [qz.jetcache.CacheClient]-[INFO]
         */
    }

    private static String doGetFromDB(String k) {
        log.info("doGetFromDB, key: {}", k);
        if ("1".equals(k)) {
            return "1_1";
        }

        return null;
    }
}

2》也能用caffeine, jetcache 做了整合

        Cache<String, String> cache = CaffeineCacheBuilder.createCaffeineCacheBuilder()
                .limit(20)
                .buildCache();

2、整合springboot 使用

可以作为本地缓存使用,也可以作为分布式缓存使用,也可以本地和远程同时写。

1、pom依赖

				<dependency>
            <groupId>com.alicp.jetcache</groupId>
            <artifactId>jetcache-starter-redis-lettuce</artifactId>
            <version>2.6.0</version>
        </dependency>

2、增加配置类

package cn.qz.cloud.alibaba.config;

import com.alicp.jetcache.CacheBuilder;
import com.alicp.jetcache.RefreshPolicy;
import com.alicp.jetcache.anno.CacheConsts;
import com.alicp.jetcache.anno.support.GlobalCacheConfig;
import com.alicp.jetcache.anno.support.SpringConfigProvider;
import com.alicp.jetcache.embedded.EmbeddedCacheBuilder;
import com.alicp.jetcache.embedded.LinkedHashMapCacheBuilder;
import com.alicp.jetcache.redis.lettuce.RedisLettuceCacheBuilder;
import com.alicp.jetcache.support.FastjsonKeyConvertor;
import com.alicp.jetcache.support.JetCacheExecutor;
import com.alicp.jetcache.support.KryoValueDecoder;
import com.alicp.jetcache.support.KryoValueEncoder;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisURI;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;

@Configuration
@Slf4j
public class JetcacheConfig {

    @Bean
    public RedisClient redisClient() {
        // 创建 RedisClient
        RedisClient redisClient = RedisClient.create(RedisURI.create("redis://127.0.0.1:6379"));
        return redisClient;
    }

    @Bean
    public SpringConfigProvider springConfigProvider() {
        return new SpringConfigProvider();
    }

    @Bean
    public GlobalCacheConfig config(RedisClient redisClient, @Qualifier("cache-reader") ScheduledExecutorService reader, @Qualifier("cache-refresh") ScheduledExecutorService refresh) {
        JetCacheExecutor.setDefaultExecutor(reader);
        JetCacheExecutor.setHeavyIOExecutor(refresh);
        Map<String, CacheBuilder> localBuilders = new HashMap<>();
        EmbeddedCacheBuilder localBuilder = LinkedHashMapCacheBuilder
                .createLinkedHashMapCacheBuilder()
                .keyConvertor(FastjsonKeyConvertor.INSTANCE)
                .limit(100)
                .expireAfterWrite(30, TimeUnit.SECONDS);
        localBuilders.put(CacheConsts.DEFAULT_AREA, localBuilder);

        Map<String, CacheBuilder> remoteBuilders = new HashMap<>();
        RefreshPolicy refreshPolicy = RefreshPolicy.newPolicy(1, TimeUnit.HOURS);
        RedisLettuceCacheBuilder remoteCacheBuilder = RedisLettuceCacheBuilder.createRedisLettuceCacheBuilder()
                .keyConvertor(FastjsonKeyConvertor.INSTANCE)
                .valueEncoder(KryoValueEncoder.INSTANCE)
                .valueDecoder(KryoValueDecoder.INSTANCE)
                .refreshPolicy(refreshPolicy)
                .expireAfterWrite(10, TimeUnit.SECONDS)
                .redisClient(redisClient);
        remoteBuilders.put(CacheConsts.DEFAULT_AREA, remoteCacheBuilder);

        GlobalCacheConfig globalCacheConfig = new GlobalCacheConfig();
        globalCacheConfig.setLocalCacheBuilders(localBuilders);
        globalCacheConfig.setRemoteCacheBuilders(remoteBuilders);
        globalCacheConfig.setStatIntervalMinutes(15);
        globalCacheConfig.setAreaInCacheName(false);

        return globalCacheConfig;
    }

    @Bean("cache-reader")
    public ScheduledExecutorService cacheReaderExecutor() {
        log.info("cacheReaderExecutor");
        ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("cache-reader-thread-pool-%d").setDaemon(true).build();
        return new ScheduledThreadPoolExecutor(10, threadFactory, (r, executor) -> {
            log.info("cacheReaderExecutor executorActiveCount={} Task={} rejected from{}", executor.getActiveCount(), r.toString(), executor.toString());
        });
    }

    @Bean("cache-refresh")
    public ScheduledExecutorService cacheRefreshExecutor() {
        log.info("cacheRefreshExecutor");
        ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("cache-refresh-thread-pool-%d").setDaemon(true).build();
        return new ScheduledThreadPoolExecutor(10, threadFactory, (r, executor) -> {
            log.info("cacheRefreshExecutor executorActiveCount={} Task={} rejected from{}", executor.getActiveCount(), r.toString(), executor.toString());
        });
    }
}

3、测试类:

package cn.qz.cloud.alibaba.controller;

import cn.qz.cloud.alibaba.bean.User;
import com.alicp.jetcache.anno.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@RequestMapping("/user")
@RestController
@Slf4j
public class UserController {

    private static final String cacheKeyPrefix = "user:cache:";

    private Map<String, User> userMap = new HashMap() {
        {
            put("qz", new User("qz", 18));
            put("zs", new User("zs", 18));
            put("ww", new User("ww", 18));
        }
    };

    /**
     * 查看所有,默认是存在远程缓存remote 种
     *
     * @return
     */
    @RequestMapping("/lists")
    @Cached(name = cacheKeyPrefix + "listUser", expire = 60, timeUnit = TimeUnit.MINUTES)
    public List<User> listUser() {
        log.info("获取用户集合listUser");
        return new ArrayList<>(userMap.values());
    }

    /**
     * 缓存到本地
     *
     * @return
     */
    @RequestMapping("/lists2")
    @Cached(name = cacheKeyPrefix + "listUser2", expire = 60, timeUnit = TimeUnit.MINUTES, cacheType = CacheType.LOCAL)
    public List<User> listUser2() {
        log.info("获取用户集合listUser2");
        return new ArrayList<>(userMap.values());
    }

    @RequestMapping("/find")
    @CachePenetrationProtect // 防止缓存击穿,通过在多个并发请求中只有一个请求去加载数据,其他请求等待加载完成后直接从缓存获取 (参数相同的时候只有一个线程能获取到)
    @Cached(name = cacheKeyPrefix + "find:", key = "#name", expire = 120, timeUnit = TimeUnit.SECONDS, postCondition = "T(cn.qz.cloud.alibaba.config.CacheCondition).checkNeedCache(#result)")
    // cacheNullValue = true 标识是否结果为null 的情况
    @CacheRefresh(refresh = 60, stopRefreshAfterLastAccess = 300, timeUnit = TimeUnit.SECONDS)
    //60秒刷新一次,如果300秒内没有访问,则停止刷新。刷新机制: 框架自己异步调用该方法进行刷新缓存
    public User find(@RequestParam String name) throws InterruptedException {
        log.info("查找用户, name: {}", name);
        Thread.sleep(2 * 1000);
        return userMap.get(name);
    }

    /**
     * 清除多个缓存,拼接固定的key和带参数的用户详情
     *
     * @param name
     */
    @RequestMapping("/del")
    @CacheInvalidate(name = cacheKeyPrefix + "listUser", key = "'[]'")
    @CacheInvalidate(name = cacheKeyPrefix + "find:", key = "#name")
    @CacheInvalidate(name = cacheKeyPrefix + "listUser2", key = "'[]'")
    public void del(@RequestParam String name) {
        log.info("清除缓存");
    }

}

4、工具类

package cn.qz.cloud.alibaba.config;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class CacheCondition {

    /**
     * 检查是否需要缓存
     * <p>
     * 可以根据返回的结果进行判断
     *
     * @param object
     * @return
     */
    public static boolean checkNeedCache(Object object) {
        log.info("checkNeedCache: {}", object);
        if (object == null) {
            return false;
        }
        return true;
    }
}

5、相关注解解释:

1、@Cached(name = cacheKeyPrefix + "find:", key = "#name", expire = 120, timeUnit = TimeUnit.SECONDS, postCondition = "T(cn.qz.cloud.alibaba.config.CacheCondition).checkNeedCache(#result)")
缓存注解,可以设置缓存的key(可以加参数)、时间、单位、postCondition 指定检查的方法,可以设置是否对结果进行缓存
2、@CachePenetrationProtect // 防止缓存击穿,通过在多个并发请求中只有一个请求去加载数据,其他请求等待加载完成后直接从缓存获取 (参数相同的时候只有一个线程能获取到)
3、@CacheRefresh(refresh = 60, stopRefreshAfterLastAccess = 300, timeUnit = TimeUnit.SECONDS)
	60秒刷新一次,如果300秒内没有访问,则停止刷新。刷新机制: 框架自己异步调用该方法进行刷新缓存
	cacheType为REMOTE或者BOTH的时候,刷新行为是全局唯一的,也就是说,即使应用服务器是一个集群,也不会出现多个服务器同时去刷新一个key的情况。
	一个key的刷新任务,自该key首次被访问后初始化,如果该key长时间不被访问,在stopRefreshAfterLastAccess指定的时间后,相关的刷新任务就会被自动移除,这样就避免了浪费资源去进行没有意义的刷新。
4、CacheInvalidate
清除缓存,拼接固定的key和带参数的用户详情


rediskey的结构:
1) "user:cache:listUser[]"
2) "user:cache:find:zs"

标签:缓存,jetcache,cache,qz,使用,import,com
From: https://www.cnblogs.com/qlqwjy/p/18350556

相关文章

  • python-xlsxwriter的基本使用
    安装xlsxwriter:pipinstallXlsxWriter简单实例:#coding:utf-8importxlsxwriterworkbook=xlsxwriter.Workbook('demo1.xlsx')#创建一个Excel文件worksheet=workbook.add_worksheet()#创建一个工作表对象worksheet.set_column('A:A',20)#设定第一列(A)宽度为20像素bold=......
  • 成功安装torch但使用却Error loading “..\Lib\site-packages\torch\lib\fbgemm.
    OSError:[WinError126]找不到指定的模块。Errorloading"..\lib\fbgemm.dll"1.问题不大,实际上是fbgemm.dll缺少了一个依赖文件。可以用Dependencies来查看。下载地址:https://github.com/lucasg/Dependencies/releases选择你电脑喜欢的配置下载一个release.zip下......
  • mysql数据库:使用Python操作MySQL
    mysql数据库:使用Python操作MySQL安装第三方模块pymysqlpipinstallpymysql操作MySQLimportpymysql#创建连接#需要传入一些参数:#hostmysql所在的主机名或者是域名或者是ip地址#portmysql运行的端口号#ps-aux|grepmysql找到MySQL运行的进程......
  • 使用PaddleHub生成证件照
       飞桨是百度自主研发的开源深度学习平台。包含深度学习核心训练和推理框架、工具组件、基础模型库、端到端开发套件、预测部署和开发训练。    今天要说的PaddleHub是飞桨中的一个工具组件,包含了大量的预训练模型,不需要自己训练可以拿来直接使用,也可以根据自......
  • windows C++-使用 C++/WinRT 的集合
    在内部,Windows运行时集合具有大量复杂的移动部件。但要将集合对象传递到Windows运行时函数,或要实现自己的集合属性和集合类型时,C++/WinRT中有函数和基类可以提供支持。这些功能消除复杂性,并节省大量时间和精力上的开销。IVector是由元素的任意随机访问集合实现的Windo......
  • 使用Mask R-CNN实现图像分割
    使用MaskR-CNN实现分割步骤1.导入依赖项import osimport torchimport numpy as npimport matplotlib.pyplot as pltfrom PIL import Imagefrom torch.utils.data import Dataset, DataLoaderfrom torchvision.transforms import Compose, ToTe......
  • 使用Vite+TS+Antd构建React项目
    安装Vitenpminstall-gvite#yarnglobaladdvite创建React项目vitecreatemy-react-app--templatereact-ts安装ReactRouternpminstallreact-router-dom@types/react-router-dom#yarnaddreact-router-dom@types/react-router-dom安装AntDesign......
  • .NET8 缓存的使用
    .NET8下面的几种缓存的使用。(1)ICache.cs   usingSystem;usingSystem.Threading.Tasks;publicinterfaceICache{#region设置缓存///<summary>///设置缓存///</summary>///<paramname="key"&......
  • java .stream(). 使用介绍 Streams API
    Java8引入了StreamsAPI,它允许我们以声明性方式处理序列的数据。.stream()是这一API的核心方法,用于从一个数据源(如数组、集合等)创建一个流(Stream)。以下是.stream()方法的一些基本使用介绍:1.从集合创建流List<String>myList=Arrays.asList("a","b","c");Stream<S......
  • BOOST c++库学习 之 boost.thread入门实战指南 使用boost.thread库以及读写锁mutex的
    Boost.Thread库简介1.概述Boost.Thread库是Boost库中专门用于处理多线程编程的模块。它提供了一组跨平台的线程管理和同步工具,帮助开发者在C++中更轻松地编写多线程程序。Boost.Thread的设计目标是使多线程编程更加简单、可靠,同时保持高效和可移植性。2.Boost.Thread......