CaffeineCache詳解

一、CaffeineCache排序

CaffeineCache是一個高性能的本地緩存工具,它作為一個新興的緩存框架,性能表現高於Guava Cache等前輩,其中緩存項的排序也是CaffeineCache比較顯著的特點,下面是一個簡單的使用代碼實例:

Cache cache = Caffeine.newBuilder().maximumSize(10)
            .expireAfterWrite(5, TimeUnit.MINUTES)
            .removalListener((key, value, cause) ->
                    log.info("key:{} value:{} 被移除,原因:{}", key, value, cause))
            .build();
cache.put("a", 10);
cache.put("b", 20);
cache.put("c", 30);
Map map = cache.asMap();
List<Entry> entries = new ArrayList(map.entrySet());
entries.sort(Entry.comparingByValue());

這裡我們使用了Java的Map數據結構,通過將Map轉化成List,利用Java8的stream API進行排序。當然,CaffeineCache也可以自定義比較器實現排序。

二、CaffeineCache Spring Boot

當然,CaffeineCache也可以和Spring Boot集成,實現更便捷的使用方式,並可以利用Spring Boot提供的一些特性。具體的使用步驟如下:

1、首先在pom.xml中引入相關依賴:

<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
    <version>2.8.8</version>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

2、在Spring Boot項目的配置文件中配置CaffeineCache屬性:

spring.cache.type=caffeine
spring.cache.caffeine.spec=maximumSize=100,expireAfterAccess=5s

3、在需要啟用CaffeineCache的Bean上添加@Cacheable註解即可:

@Cacheable(value="user-key")
public User getUserById(String userId) {
    log.info("UserServiceImpl.getUserById() id: "+ userId);
    return userDao.queryUserById(userId);
}

三、CaffeineCache使用

CaffeineCache的使用非常簡單,只需要按照下面的步驟操作即可:

1、我們需要創建一個CaffeineCache對象:

LoadingCache cache = Caffeine.newBuilder()
        .maximumSize(100)
        .expireAfterAccess(1, TimeUnit.DAYS)
        .build(new CacheLoader<String, String>() {
            public String load(String key) throws Exception {
                return createExpensiveGraph(key);
            }
        });

2、我們可以訪問緩存中的對象:

try {
    String result = cache.get(key);
    // Do something with result
} catch (ExecutionException e) {
    throw new RuntimeException(e);
}

3、我們也可以手動刷新緩存中的對象:

cache.refresh(key);

四、CaffeineCache源碼

CaffeineCache的源碼具有一定的複雜性,主要是由於其採用了CAS等技術實現了高性能以及線程安全等特性。下面是CaffeineCache的一個簡單單例模式實現代碼:

public class CaffeineCache {
    private static Cache cache;

    public static synchronized Cache getInstance() {
        if (cache == null) {
            cache = Caffeine.newBuilder()
                    .maximumSize(1000)
                    .build();
        }
        return cache;
    }
}

五、CaffeineCacheLoad

CaffeineCache的載入機制也是其性能表現優異的原因之一,與Guava Cache類似,CaffeineCache也支持自定義載入機制,只需要實現CacheLoader介面即可:

LoadingCache graphs = Caffeine.newBuilder()
        .maximumSize(10_000)
        .build(key -> createExpensiveGraph(key));

private Graph createExpensiveGraph(Key key) {
    return new Graph(key);
}

六、CaffeineCacheManager

CaffeineCache的管理器CaffeineCacheManager實現了Spring CacheManager的介面,可以與Spring Boot集成,由Spring Boot自動裝配。下面是CaffeineCacheManager的代碼示例:

@Bean
public CacheManager cacheManager() {
    CaffeineCacheManager cacheManager = new CaffeineCacheManager();
    cacheManager.setCaffeine(Caffeine.newBuilder().expireAfterWrite(2, TimeUnit.HOURS));
    return cacheManager;
}

七、CaffeineCache線程安全

CaffeineCache支持線程安全,通過重載CacheLoader和RemovalListener介面實現:

LoadingCache graphs = Caffeine.newBuilder()
        .maximumSize(10_000)
        .executor(Runnable::run)  // DirectExecutor
        .removalListener((key, graph, cause) -> {
            if (cause.wasEvicted()) {
                log.info("Graph with key {} was evicted ({})", key, cause.getCause());
            }
        })
        .build(new CacheLoader() {
            public Graph load(Key key) throws AnyException {
                return createExpensiveGraph(key);
            }
        });

八、CaffeineCacheManager Redis

與Redis集成,需要引入以下依賴:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
    <version>2.8.8</version>
</dependency>
<dependency>
    <groupId>io.lettuce</groupId>
    <artifactId>lettuce-core</artifactId>
</dependency>

然後在Spring Boot項目的配置文件中增加如下配置:

spring.cache.cache-names=cache_a,cache_b
spring.cache.type=redis
spring.redis.host=localhost
spring.redis.password=password
spring.redis.port=6379
spring.redis.database=1
spring.cache.redis.use-key-prefix=true
spring.cache.redis.key-prefix=my_app_prefix
spring.cache.redis.cache-null-values=true

最後,我們可以創建RedisCache對象並設置CaffeineCache為其CacheLoader:

CacheLoader<Object, Object> myCacheLoader = new CacheLoader<Object, Object>() {
    public Object load(Object key) {
        // do something to load cache
        ...
    }
};
RedisCache myCache = new RedisCache("cacheName", lettuceConnectionFactory, myCacheConfig);
LoadingCache<Object, Object> cache = Caffeine.newBuilder().maximumSize(10000).build(myCacheLoader);
myCache.setCaffeineCache(cache);

九、CaffeineCache本地調試不生效

如果我們在本地調試時,發現CaffeineCache不生效,可以嘗試以下方式進行解決:

1、確認是否注入了CaffeineCacheManager,以及是否配置了有效的屬性。

@Bean
public CacheManager cacheManager() {
    CaffeineCacheManager cacheManager = new CaffeineCacheManager();
    cacheManager.setCaffeine(Caffeine.newBuilder().expireAfterWrite(2, TimeUnit.HOURS));
    return cacheManager;
}

2、確認是否在啟動類中添加@EnableCaching註解。

@SpringBootApplication
@EnableCaching
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

3、如果使用了Spring Boot,可以在application.yml或者application.properties中增加如下代碼:

management:
  endpoints:
    web:
      exposure:
        include: "*"

以上就是對CaffeineCache的詳細介紹,我們可以根據不同的需求,選擇不同的使用方式以及相關配置,並可以利用其提供的高性能、線程安全等特性,優化我們的應用程序性能。

原創文章,作者:XTMJA,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/317023.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
XTMJA的頭像XTMJA
上一篇 2025-01-09 12:15
下一篇 2025-01-09 12:23

相關推薦

  • 神經網路代碼詳解

    神經網路作為一種人工智慧技術,被廣泛應用於語音識別、圖像識別、自然語言處理等領域。而神經網路的模型編寫,離不開代碼。本文將從多個方面詳細闡述神經網路模型編寫的代碼技術。 一、神經網…

    編程 2025-04-25
  • Linux sync詳解

    一、sync概述 sync是Linux中一個非常重要的命令,它可以將文件系統緩存中的內容,強制寫入磁碟中。在執行sync之前,所有的文件系統更新將不會立即寫入磁碟,而是先緩存在內存…

    編程 2025-04-25
  • Python輸入輸出詳解

    一、文件讀寫 Python中文件的讀寫操作是必不可少的基本技能之一。讀寫文件分別使用open()函數中的’r’和’w’參數,讀取文件…

    編程 2025-04-25
  • git config user.name的詳解

    一、為什麼要使用git config user.name? git是一個非常流行的分散式版本控制系統,很多程序員都會用到它。在使用git commit提交代碼時,需要記錄commi…

    編程 2025-04-25
  • 詳解eclipse設置

    一、安裝與基礎設置 1、下載eclipse並進行安裝。 2、打開eclipse,選擇對應的工作空間路徑。 File -> Switch Workspace -> [選擇…

    編程 2025-04-25
  • MPU6050工作原理詳解

    一、什麼是MPU6050 MPU6050是一種六軸慣性感測器,能夠同時測量加速度和角速度。它由三個感測器組成:一個三軸加速度計和一個三軸陀螺儀。這個組合提供了非常精細的姿態解算,其…

    編程 2025-04-25
  • C語言貪吃蛇詳解

    一、數據結構和演算法 C語言貪吃蛇主要運用了以下數據結構和演算法: 1. 鏈表 typedef struct body { int x; int y; struct body *nex…

    編程 2025-04-25
  • Linux修改文件名命令詳解

    在Linux系統中,修改文件名是一個很常見的操作。Linux提供了多種方式來修改文件名,這篇文章將介紹Linux修改文件名的詳細操作。 一、mv命令 mv命令是Linux下的常用命…

    編程 2025-04-25
  • Java BigDecimal 精度詳解

    一、基礎概念 Java BigDecimal 是一個用於高精度計算的類。普通的 double 或 float 類型只能精確表示有限的數字,而對於需要高精度計算的場景,BigDeci…

    編程 2025-04-25
  • nginx與apache應用開發詳解

    一、概述 nginx和apache都是常見的web伺服器。nginx是一個高性能的反向代理web伺服器,將負載均衡和緩存集成在了一起,可以動靜分離。apache是一個可擴展的web…

    編程 2025-04-25

發表回復

登錄後才能評論