最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

解讀緩存db redis local的取舍之道

 更新時間:2024年05月06日 10:24:17   作者:Mr-Wanter  
這篇文章主要介紹了解讀緩存db redis local的取舍之道,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

前言

讓我們來聊一下數(shù)據(jù)緩存,它是如何為我們帶來快速的數(shù)據(jù)響應(yīng)的。

你知道嗎,為了提高數(shù)據(jù)的讀取速度,我們通常會引入數(shù)據(jù)緩存。

但是,你知道嗎,不是所有的數(shù)據(jù)都適合緩存,有些數(shù)據(jù)更適合直接從數(shù)據(jù)庫查詢。

現(xiàn)在,我們就來一起討論一下,什么樣的數(shù)據(jù)適合直接從數(shù)據(jù)庫查詢,什么樣的數(shù)據(jù)適合從緩存中讀取。

這將有助于我們更好地利用緩存,提高系統(tǒng)的性能。讓我們開始吧!

一、影響因素

當(dāng)涉及到數(shù)據(jù)查詢和緩存時,有幾個因素可以考慮來確定什么樣的數(shù)據(jù)適合直接從數(shù)據(jù)庫查詢,什么樣的數(shù)據(jù)適合從緩存中讀取。

  • 訪問頻率:如果某個數(shù)據(jù)被頻繁訪問,且對實時性要求不高,那么將其緩存在內(nèi)存中會顯著提高響應(yīng)速度。這樣的數(shù)據(jù)可以是經(jīng)常被查詢的熱點數(shù)據(jù),比如網(wǎng)站的熱門文章、商品信息等。
  • 數(shù)據(jù)更新頻率:如果某個數(shù)據(jù)經(jīng)常發(fā)生更新,那么將其緩存可能導(dǎo)致緩存和數(shù)據(jù)庫中的數(shù)據(jù)不一致。對于這種情況,最好直接從數(shù)據(jù)庫中查詢最新數(shù)據(jù)。比如用戶個人信息、訂單狀態(tài)等經(jīng)常變動的數(shù)據(jù)。
  • 數(shù)據(jù)大小:較大的數(shù)據(jù)對象,如圖片、視頻等,由于其體積較大,將其緩存到內(nèi)存中可能會占用大量資源。這種情況下,可以將這些數(shù)據(jù)存儲在分布式文件系統(tǒng)或云存儲中,并通過緩存存儲其訪問路徑或標(biāo)識符。
  • 數(shù)據(jù)一致性:一些數(shù)據(jù)在不同地方的多個副本可能會導(dǎo)致一致性問題。對于需要保持強(qiáng)一致性的數(shù)據(jù),建議直接從數(shù)據(jù)庫查詢。而對于可以容忍一定程度的數(shù)據(jù)不一致的場景,可以考慮將數(shù)據(jù)緩存。
  • 查詢復(fù)雜度:某些復(fù)雜的查詢操作可能會消耗大量的計算資源和時間,如果這些查詢結(jié)果需要頻繁訪問,可以將其緩存,避免重復(fù)計算,提高響應(yīng)速度。

需要注意的是,數(shù)據(jù)緩存并非適用于所有情況。緩存的使用需要謹(jǐn)慎,需要權(quán)衡數(shù)據(jù)的實時性、一致性和存儲成本等方面的需求。此外,對于緩存數(shù)據(jù)的更新和失效策略也需要考慮,以確保緩存數(shù)據(jù)的準(zhǔn)確性和及時性。

綜上所述,數(shù)據(jù)適合直接從數(shù)據(jù)庫查詢還是緩存讀取,取決于數(shù)據(jù)的訪問頻率、更新頻率、大小、一致性要求和查詢復(fù)雜度等因素。在實際應(yīng)用中,需要根據(jù)具體情況進(jìn)行綜合考慮和合理選擇。

二、db or redis or local

1.db

  • 查詢復(fù)雜度低
  • 字段少
  • sql執(zhí)行效率高
  • 實時性高

通常數(shù)據(jù)庫適合查詢字典類型數(shù)據(jù),如類似 key value 鍵值對,數(shù)據(jù)更新頻繁,實時性高的數(shù)據(jù)。

對于sql效率高的查詢,redis查詢不一定比db查詢快。

2.redis

  • 查詢復(fù)雜度高
  • 字段相對不多
  • 實時性低

Redis適合查詢復(fù)雜度較高、實時性要求較低的數(shù)據(jù)。當(dāng)SQL查詢效率較低,或者需要進(jìn)行字段code和value的轉(zhuǎn)換存儲時,Redis可以提供更高效的查詢方式。

不過,需要注意的是,Redis的主要瓶頸在于數(shù)據(jù)的序列化和反序列化過程。如果數(shù)據(jù)量較大,包含大量字段或者數(shù)據(jù)量巨大,那么Redis的查詢速度可能不一定比數(shù)據(jù)庫快,當(dāng)然此時數(shù)據(jù)庫本身執(zhí)行效率也低。

在這種情況下,我們需要綜合考慮數(shù)據(jù)的復(fù)雜度、實時性要求以及數(shù)據(jù)量的大小,選擇最適合的查詢方式。

有時候,可能需要在數(shù)據(jù)庫和Redis之間進(jìn)行權(quán)衡和折中,以找到最佳的性能和效率平衡點。因此,為了提高查詢速度,我們需要根據(jù)具體的業(yè)務(wù)需求和數(shù)據(jù)特性,選擇合適的存儲和查詢方案。

3. local

  • 查詢復(fù)雜度高
  • 字段多
  • 實時性低

本地緩存通常是最快的。它可以在內(nèi)存中直接讀取數(shù)據(jù),速度非???。然而,由于受限于內(nèi)存大小,本地緩存的數(shù)據(jù)量是有限的。

對于那些數(shù)據(jù)庫和Redis難以處理的大型數(shù)據(jù),我們可以考慮使用本地緩存。通過將一部分頻繁訪問的數(shù)據(jù)存儲在本地緩存中,可以大大提高系統(tǒng)的響應(yīng)速度。

這樣,我們可以在不犧牲太多內(nèi)存資源的情況下,快速獲取到需要的數(shù)據(jù)。當(dāng)然,需要注意的是,由于本地緩存的數(shù)據(jù)是存儲在內(nèi)存中的,所以在服務(wù)器重啟或緩存過期時,需要重新從數(shù)據(jù)庫或Redis中加載數(shù)據(jù)到本地緩存中。

因此,在使用本地緩存時,需要權(quán)衡數(shù)據(jù)的大小、更新頻率以及內(nèi)存資源的限制,以獲得最佳的性能和可用性。

三、redisson 和 CaffeineCache 封裝

提供緩存查詢封裝,查詢不到時直接查數(shù)據(jù)庫后存入緩存。

3.1 redisson

  • 3.1.1 maven
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-boot-starter</artifactId>
        </dependency>
  • 3.1.2 封裝
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.cuzue.common.core.exception.BusinessException;
import com.cuzue.dao.cache.redis.RedisClient;
import org.redisson.api.RBucket;
import org.redisson.api.RKeys;
import org.redisson.api.RedissonClient;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

public class RedisCacheProvider {

    private static RedissonClient redissonClient;

    public RedisCacheProvider(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    /**
     * 從redissonClient緩存中取數(shù)據(jù),如果沒有,查數(shù)據(jù)后存入
     *
     * @param key         redis key
     * @param dataFetcher 獲取數(shù)據(jù)
     * @param ttl         緩存時間
     * @param timeUnit    緩存時間單位
     * @param <T>
     * @return 數(shù)據(jù)
     */
    public <T> List<T> getCachedList(String key, Supplier<List<T>> dataFetcher, long ttl, TimeUnit timeUnit) {
        if (ObjectUtil.isNotNull(redissonClient)) {
            // 嘗試從緩存中獲取數(shù)據(jù)
            List<T> cachedData = redissonClient.getList(key);
            if (cachedData.size() > 0) {
                // 緩存中有數(shù)據(jù),直接返回
                return cachedData;
            } else {
                // 緩存中沒有數(shù)據(jù),調(diào)用數(shù)據(jù)提供者接口從數(shù)據(jù)庫中獲取
                List<T> data = dataFetcher.get();
                cachedData.clear();
                cachedData.addAll(data);
                // 將數(shù)據(jù)存入緩存,并設(shè)置存活時間
                // 獲取 bucket 對象,為了設(shè)置過期時間
                RBucket<List<T>> bucket = redissonClient.getBucket(key);
                // 為整個列表設(shè)置過期時間
                bucket.expire(ttl, timeUnit);
                // 返回新獲取的數(shù)據(jù)
                return data;
            }
        } else {
            throw new BusinessException("redissonClient has not initialized");
        }
    }

    /**
     * 刪除緩存
     *
     * @param key redis key
     */
    public void deleteCachedList(String systemName, String key) {
        if (ObjectUtil.isNotNull(redissonClient)) {
            RKeys keys = redissonClient.getKeys();
            keys.deleteByPattern(key);
        } else {
            throw new BusinessException("redis client has not initialized");
        }
    }
}
  • 3.1.3 使用

啟動類添加:@Import({RedissonConfig.class})

直接引用:

@Resource
private RedissonClient redissonClient;

//緩存數(shù)據(jù)獲取
public List<MatMaterialsResp> listCache(ListQO qo) {
    RedisCacheProvider cache = new RedisCacheProvider(redissonClient);
    List<MatMaterialsResp> resps = cache.getCachedList("testList", () -> {
        // 緩存數(shù)據(jù)查詢
    }, 20, TimeUnit.SECONDS);
    return resps;
}

3.2 CaffeineCache

也可以使用hashMap

  • 3.1.1 maven
       <dependency>
            <groupId>com.github.ben-manes.caffeine</groupId>
            <artifactId>caffeine</artifactId>
            <version>3.0.5</version>
        </dependency>
  • 3.1.2 封裝

CaffeineCache<K, V>

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.Weigher;

import java.util.concurrent.TimeUnit;
import java.util.function.Function;

public class CaffeineCache<K, V> {
    private final Cache<K, V> cache;

    /**
     * 不過期緩存
     *
     * @param maxSize 緩存條目數(shù)量 注意對象大小不要超過jvm內(nèi)存
     */
    public CaffeineCache(long maxSize) {
        this.cache = Caffeine.newBuilder()
                .maximumSize(maxSize)
                .build();
    }

    /**
     * 初始化Caffeine
     *
     * @param maxSize
     * @param expireAfterWriteDuration
     * @param unit
     */
    public CaffeineCache(long maxSize, long expireAfterWriteDuration, TimeUnit unit) {
        this.cache = Caffeine.newBuilder()
                .maximumSize(maxSize)
                .expireAfterWrite(expireAfterWriteDuration, unit)
                .build();
    }

    /**
     * 初始化Caffeine 帶權(quán)重
     *
     * @param maxSize
     * @param weigher                  權(quán)重
     * @param expireAfterWriteDuration
     * @param unit
     */
    public CaffeineCache(long maxSize, Weigher weigher, long expireAfterWriteDuration, TimeUnit unit) {
        this.cache = Caffeine.newBuilder()
                .maximumSize(maxSize)
                .weigher(weigher)
                .expireAfterWrite(expireAfterWriteDuration, unit)
                .build();
    }

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

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

    public void remove(K key) {
        cache.invalidate(key);
    }

    public void clear() {
        cache.invalidateAll();
    }

    // 如果你需要一個加載功能(當(dāng)緩存miss時自動加載值),你可以使用這個方法
    public V get(K key, Function<? super K, ? extends V> mappingFunction) {
        return cache.get(key, mappingFunction);
    }

    // 添加獲取緩存統(tǒng)計信息的方法
    public String stats() {
        return cache.stats().toString();
    }
}


LocalCacheProvider

import cn.hutool.core.util.ObjectUtil;
import com.cuzue.dao.cache.localcache.CaffeineCache;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 本地緩存
 */
public class LocalCacheProvider {

    private static CaffeineCache cache;

    /**
     * 無過期時間
     * @param maxSize 緩存最大條數(shù)
     */
    public LocalCacheProvider(long maxSize) {
        cache = new CaffeineCache(maxSize);
    }

    /**
     * 帶過期時間
     * @param maxSize 緩存最大條數(shù)
     * @param ttl 過期時間
     * @param timeUnit 時間單位
     */
    public LocalCacheProvider(long maxSize, long ttl, TimeUnit timeUnit) {
        cache = new CaffeineCache(maxSize, ttl, timeUnit);
    }

    public static <T> List<T> getCachedList(String key, Supplier<List<T>> dataFetcher) {
        if (ObjectUtil.isNotNull(cache.get(key))) {
            return (List<T>) cache.get(key);
        } else {
            List<T> data = dataFetcher.get();
            cache.put(key, data);
            return data;
        }
    }

    public static <T> List<T> getCachedList(String key, Function<String, List<T>> dataFetcher) {
        return (List<T>) cache.get(key, dataFetcher);
    }

    /**
     * 刪除緩存
     *
     * @param key redis key
     */
    public void deleteCachedList(String key) {
        cache.remove(key);
    }
}
  • 3.1.3 使用
//初始化caffeine對象
LocalCacheProvider cache = new LocalCacheProvider(5000, 20, TimeUnit.SECONDS);

//緩存數(shù)據(jù)獲取
public List<MatMaterialsResp> listLocalCache(ListQO qo) {
    List<MatMaterialsResp> resps = cache.getCachedList("testList", (s) -> {
	  // 緩存數(shù)據(jù)查詢
    });
    return resps;
}

注意:Caffeine 實現(xiàn)的緩存占用 JVM 內(nèi)存,小心 OutOfMemoryError

解決場景:

  • 1.本地緩存適用不限制緩存大小,導(dǎo)致OOM,適合緩存小對象
  • 2.本地緩存長時間存在,未及時清除無效緩存,導(dǎo)致內(nèi)存占用資源浪費(fèi)
  • 3.防止人員api濫用, 未統(tǒng)一管理隨意使用,導(dǎo)致維護(hù)性差等等

總結(jié)

從前的無腦經(jīng)驗,db查詢慢,redis緩存起來,redis真不一定快!

一個簡單性能測試:(測試響應(yīng)時間均為二次查詢的大概時間)

1.前置條件: 一條數(shù)據(jù)轉(zhuǎn)換需要200ms,共5條數(shù)據(jù),5個字段項,數(shù)據(jù)量大小463 B

db > 1s
redis > 468ms
local > 131ms

2.去除轉(zhuǎn)換時間,直接響應(yīng)

db > 208ms
redis > 428ms
local > 96ms

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 深入了解Redis的看門狗機(jī)制

    深入了解Redis的看門狗機(jī)制

    Redis鎖的延期機(jī)制,通常被稱為看門狗機(jī)制,本文就拉介紹一下Redis的看門狗機(jī)制,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-12-12
  • 淺談Redis存儲數(shù)據(jù)類型及存取值方法

    淺談Redis存儲數(shù)據(jù)類型及存取值方法

    這篇文章主要介紹了淺談Redis存儲數(shù)據(jù)類型及存取值方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • Redis GEO實現(xiàn)搜索附近用戶的項目實踐

    Redis GEO實現(xiàn)搜索附近用戶的項目實踐

    RedisGEO主要用于存儲地理位置信息,并對存儲的信息進(jìn)行操作,本文主要介紹了Redis GEO實現(xiàn)搜索附近用戶的項目實踐,具有一定的參考價值,感興趣的可以了解一下
    2024-05-05
  • Redis高效安全的遍歷所有key的幾種方法

    Redis高效安全的遍歷所有key的幾種方法

    在 Redis 中,遍歷所有的 key 是一個相對昂貴的操作,特別是當(dāng)你有大量的數(shù)據(jù)時,直接使用 KEYS 命令會導(dǎo)致阻塞,這對于大規(guī)模的 Redis 實例來說是非常不安全的,所以本文給大家介紹了幾種Redis高效安全的遍歷所有key的方法,需要的朋友可以參考下
    2025-08-08
  • Redis高性能的原因及說明

    Redis高性能的原因及說明

    這篇文章主要介紹了Redis高性能的原因及說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • Redis KEYS查詢大批量數(shù)據(jù)替代方案

    Redis KEYS查詢大批量數(shù)據(jù)替代方案

    在使用 Redis 時,KEYS 命令雖然簡單直接,但其全表掃描的特性在處理大規(guī)模數(shù)據(jù)時會導(dǎo)致性能問題,甚至可能阻塞 Redis 服務(wù),本文將介紹SCAN命令、有序集合、哈希表和RediSearch模塊四種替代 KEYS 的高效方案,需要的朋友可以參考下
    2024-12-12
  • Redis教程(一):Redis簡介

    Redis教程(一):Redis簡介

    這篇文章主要介紹了Redis教程(一):Redis簡介,本文是系列文章的第一篇,歡迎大家跟隨本教程學(xué)習(xí)Redis數(shù)據(jù)庫,需要的朋友可以參考下
    2015-04-04
  • 詳解Redis瘦身指南

    詳解Redis瘦身指南

    Redis應(yīng)該是開發(fā)者最常用的緩存服務(wù)器了,它豐富的數(shù)據(jù)結(jié)構(gòu),快速高效的內(nèi)存操作能幫助開發(fā)者迅速完成復(fù)雜功能的設(shè)計,作為一個內(nèi)存型數(shù)據(jù)庫,Redis經(jīng)常會遇到內(nèi)存問題,今天我們來談一下Redis常見的內(nèi)存滿的問題,介紹一下給 Redis “瘦身”的通用方式。
    2021-05-05
  • 配置Redis序列化方式不生效問題及解決

    配置Redis序列化方式不生效問題及解決

    這篇文章主要介紹了配置Redis序列化方式不生效問題及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • Redis分布式鎖方案設(shè)計之防止訂單重復(fù)提交或支付

    Redis分布式鎖方案設(shè)計之防止訂單重復(fù)提交或支付

    這篇文章主要為大家介紹了Redis分布式鎖之防止訂單重復(fù)提交或支付方案設(shè)計示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09

最新評論

武胜县| 长乐市| 方城县| 大渡口区| 青冈县| 神木县| 林口县| 株洲市| 客服| 巴南区| 额尔古纳市| 凤阳县| 永兴县| 佛教| 凤阳县| 平陆县| 读书| 永丰县| 巴林左旗| 明光市| 神池县| 健康| 广西| 庆云县| 治多县| 宜兰市| 拉孜县| 武强县| 马关县| 昌乐县| 体育| 简阳市| 鹰潭市| 峨边| 通道| 楚雄市| 大理市| 芜湖县| 宣威市| 西充县| 河北区|