Java中的多級快取設計與實現

省赚客开发者团队發表於2024-07-20

Java中的多級快取設計與實現

大家好,我是微賺淘客系統3.0的小編,是個冬天不穿秋褲,天冷也要風度的程式猿!

在現代應用程式中,多級快取設計是一種常見的效能最佳化技術。多級快取透過在不同層次上快取資料來減少對底層儲存系統的訪問次數,提高系統的整體效能。本文將展示如何在 Java 中設計和實現一個多級快取系統,包括記憶體快取和分散式快取的組合。

1. 設計多級快取

多級快取通常包括以下幾層:

  1. 本地快取(L1):直接在應用程式中儲存的快取,如使用 HashMapConcurrentHashMapCaffeine 等工具實現。
  2. 分散式快取(L2):如 Redis 或 Memcached,這種快取可供多個應用程式例項共享。

2. 新增依賴

首先,在 pom.xml 中新增需要的依賴:

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

3. 本地快取實現

我們可以使用 Caffeine 作為本地快取的實現。以下是一個使用 Caffeine 實現的本地快取示例:

package cn.juwatech.cache;

import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.Cache;
import org.springframework.stereotype.Component;

@Component
public class LocalCache {

    private final Cache<String, String> cache;

    public LocalCache() {
        this.cache = Caffeine.newBuilder()
                             .maximumSize(100) // 最大快取項數
                             .expireAfterWrite(10, java.util.concurrent.TimeUnit.MINUTES) // 10分鐘後過期
                             .build();
    }

    public void put(String key, String value) {
        cache.put(key, value);
    }

    public String get(String key) {
        return cache.getIfPresent(key);
    }
}

在這個例子中,我們建立了一個最大快取項數為 100,且每項在寫入後 10 分鐘過期的 Caffeine 快取例項。

4. 分散式快取實現

Redis 是一種流行的分散式快取解決方案。配置 Redis 客戶端(例如 Jedis 或 Lettuce)並進行連線:

spring:
  redis:
    host: localhost
    port: 6379

接著,建立一個 Redis 快取管理器:

package cn.juwatech.cache;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

@Component
public class RedisCache {

    private final RedisTemplate<String, String> redisTemplate;

    @Autowired
    public RedisCache(RedisConnectionFactory redisConnectionFactory) {
        this.redisTemplate = new RedisTemplate<>();
        this.redisTemplate.setConnectionFactory(redisConnectionFactory);
    }

    public void put(String key, String value) {
        redisTemplate.opsForValue().set(key, value);
    }

    public String get(String key) {
        return redisTemplate.opsForValue().get(key);
    }
}

5. 多級快取策略

在實現多級快取時,我們需要一個機制來協調本地快取和分散式快取。以下是一個示例實現,展示瞭如何使用本地快取作為第一級快取,當本地快取中不存在資料時,從分散式快取中載入資料:

package cn.juwatech.cache;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class MultiLevelCacheService {

    private final LocalCache localCache;
    private final RedisCache redisCache;

    @Autowired
    public MultiLevelCacheService(LocalCache localCache, RedisCache redisCache) {
        this.localCache = localCache;
        this.redisCache = redisCache;
    }

    public String get(String key) {
        // 嘗試從本地快取中獲取資料
        String value = localCache.get(key);
        if (value != null) {
            return value;
        }

        // 本地快取中沒有,從 Redis 中獲取
        value = redisCache.get(key);
        if (value != null) {
            // 更新本地快取
            localCache.put(key, value);
        }

        return value;
    }

    public void put(String key, String value) {
        // 更新本地快取和 Redis
        localCache.put(key, value);
        redisCache.put(key, value);
    }
}

在這個實現中,MultiLevelCacheService 類負責協調本地快取和 Redis 快取。當請求資料時,它首先嚐試從本地快取中獲取資料,如果本地快取中不存在資料,則從 Redis 中獲取,並將資料放入本地快取中。

6. 示例控制器

最後,我們可以建立一個控制器來展示如何使用這個多級快取服務:

package cn.juwatech.controller;

import cn.juwatech.cache.MultiLevelCacheService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class CacheController {

    private final MultiLevelCacheService multiLevelCacheService;

    public CacheController(MultiLevelCacheService multiLevelCacheService) {
        this.multiLevelCacheService = multiLevelCacheService;
    }

    @GetMapping("/cache")
    public String getCache(@RequestParam String key) {
        return multiLevelCacheService.get(key);
    }

    @GetMapping("/cache/put")
    public String putCache(@RequestParam String key, @RequestParam String value) {
        multiLevelCacheService.put(key, value);
        return "Cached " + key + " with value " + value;
    }
}

在這個控制器中,我們提供了兩個端點,一個用於獲取快取資料,另一個用於將資料儲存到快取中。

7. 總結

透過以上步驟,我們在 Java 中實現了一個多級快取系統,包括本地快取和分散式快取。使用 Caffeine 實現本地快取,Redis 作為分散式快取,並透過協調這兩者來最佳化快取效能。這種設計使得系統能夠在減少對底層儲存系統訪問的同時,提高響應速度和處理能力。

本文著作權歸聚娃科技微賺淘客系統開發者團隊,轉載請註明出處!

相關文章