iT邦幫忙

2024 iThome 鐵人賽

DAY 26
0

Redis是以key-value方式儲存,能夠快速存取,且資料結構相較傳統sql DB更加靈活,因此常用於緩存等場景。

Redis使用(Spring Boot)

依據專案配置加入依賴

// 採用Maven,於pom.xml加入
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
</dependency>

// 採用Gradle,於build.gradle加入
implementation 'org.springframework.data:spring-data-redis'

在Spring Boot配置Redis

spring.redis.host=localhost
spring.redis.port=6379

於場景應用

  • 緩存快取機制
@Service
public class TaskService {

// 啟用 Spring 的快取功能
@Cacheable(value = "tasks", key = "#taskId") 
public Task getTaskById(Long taskId) {
    // 資料庫查詢
    System.out.println("從DB查詢...");
    return new Task(taskId, "任務名稱");
    }
}

第一次使用getTaskById方法查詢時,查詢結果會被存入Redis,等下次調用同樣方法時,就會直接從Redis取出,而不用重新從DB當中查詢,提升效率減輕DB存取壓力。

  • "#taskId"表示快取的key將以taskId的值生成。*

  • 資料儲存

@Service 
public class RedisService {
    private final RedisTemplate<String, String> redisTemplate;
    
    public RedisService(RedisTemplate<String, String> redisTemplate) {
        this.redisTemplate =redisTemplate;
    }
    
    public void saveData(String key, String value) {
        redisTemplate.opsForValue().set(key, value);
        System.out.println("資料已存至Redis");
    }
    
    public String getDate(String key) {
        return redisTemplate.opsForValue().get(key);
    }
}

使用RedisTemplate操作Redis,將資料以Key-Value儲存,並透過opsForValue.set()寫入資料、opsForValue().get()讀出資料。

Redis如何取得新資料

將Redis應用於緩存快取要注意此一機制,避免都是查詢到舊資料。以下是幾個可以觸發從資料庫重新獲取新資料的方法:

  • 設定TTL(Time To Live)
    將快取配置存活時間,當時間一到,Redis會清除快取當中的數據,等下次查詢時,會重新從資料庫查詢獲取,再將此結果存入快取緩存使用。
@Cacheable(value = "tasks", key = "#taskId", cacheManager = "cacheManagerWithTtl")
public Task getTaskById(Long taskId) {
    // 從資料庫查詢
}

@Configuration
@EnableCaching
public class CacheConfig {

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
            .entryTtl(Duration.ofMinutes(10)); // 設置快取10分鐘存活時間
        return RedisCacheManager.builder(redisConnectionFactory)
            .cacheDefaults(config)
            .build();
    }
}
  • 手動清除緩存
    可設置在更新或是刪除資料庫數據時,快取數據會一併被清除,於下次查詢時,會重新從資料庫中查詢獲取新資料,在將結果存入快取緩存使用。
@CacheEvict(value = "tasks", key = "#taskId")
public void updateTask(Long taskId, Task updatedTask) {
    // 更新資料庫任務
}
  • 緩存未命中
    當Redis未尋找到對應的快取數據時,會重新從資料庫查詢並將結果存入快取。此為自動處理過程,不用額外設置。

  • 設置緩存條件
    設置哪些條件結果會被緩存。

@Cacheable(value = "tasks", key = "#taskId", condition = "#taskId > 15")
public Task gtTaskById(Long taskId) {
    // 當 taskId 大於 15 時才會快取該結果
    return new Task(taskId, "任務名稱");
}

若未使用Spring Boot配置

使用Spring框架

  • 同樣依據專案配置依賴
// 採用Maven,於pom.xml加入
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
</dependency>

// 採用Gradle,於build.gradle加入
implementation 'org.springframework.data:spring-data-redis'
  • 差異:手動配置Redis連接
@Configuration
public class RedisConfig {
    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        // 配置Redis的連線
        JedisConnectionFactory factory = new JedisConnectionFactory();
        factory.setHostName("localhost");
        factory.setPort(6379);
        return factory;
    }
}
  • 差異:額外配置RedisTemplate操作數據
@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
    RedisTemplate<String, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(redisConnectionFactory);
    // key與value序列化
    template.setKeySerializer(new StringRedisSerializer());
    template.setValueSerializer(new StringRedisSerializer()); 
    return template;
    }
}

序列化是指將java物件轉換為字節流,方便儲存以及傳輸用。Redis是以key-value存取,因此要將key、value序列化才能存入Redis。

  • 差異:若要啟用緩存,需額外配置
@Configuration
@EnableCaching
public class CacheConfig {
    // 缓存管理器
}

// 並在需要緩存快取的地方加上@Cacheable、@CacheEvict註解。

未使用Spring框架

未使用Spring框架,可以直接使用Jedis操作Redis。

  • 使用Jedis操作Redis
public class JedisExample {

    public static void main(String[] args) {
        // 連接Redis
        Jedis jedis = new Jedis("localhost", 6379);

        // 儲存數據於Redis
        jedis.set("name", "小明");
        System.out.println("Saved name in Redis: " + jedis.get("name"));

        // 連接關閉
        jedis.close();
    }
}

  • 使用JedisPool
public class JedisPoolExample {
    private static JedisPool pool = new JedisPool("localhost", 6379);
    public static void main(String[] args) {
        try (Jedis jedis = pool.getResource()) {
            jedis.set("task", "study");
            System.out.println("Task saved: " + jedis.get("task"));
        }
        pool.close();
    }
}

Redis是高效率的key-value儲存方式,適合快速讀寫以及頻繁查詢的場景,應用上也非常靈活,也有助於降低DB查詢的壓力,提高系統性能。
在使用Spring Boot的狀況下,Redis的配置以及操作上都更為便捷,開發效率更高,若未使用框架的狀況下,需額外配置,後續維護也會比較繁瑣。


上一篇
提升效率就靠-Spring Boot 的非同步處理
下一篇
凡走過需留下痕跡-Spring Boot 中的日誌管理
系列文
從卡關到通關的Spring Boot 腦內風暴30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言