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

Redis緩存策略超詳細講解

 更新時間:2022年09月16日 09:00:22   作者:扎哇太棗糕  
實際開發(fā)中緩存處理是必須的,不可能我們每次客戶端去請求一次服務(wù)器,服務(wù)器每次都要去數(shù)據(jù)庫中進行查找,為什么要使用緩存?說到底是為了提高系統(tǒng)的運行速度

Redis緩存中間件

緩存是什么

  所謂緩存就是數(shù)據(jù)交換的緩沖區(qū)(稱作Cache [ kæ? ] ),是一個臨時存貯數(shù)據(jù)的地方,一般讀寫性能較高。CPU的運算速度要遠遠大于內(nèi)存的讀寫速度,這樣會使CPU花費很長時間等待數(shù)據(jù)從內(nèi)存的獲取或者寫入,因此緩存的出現(xiàn)主要就是為了解決CPU運算速度與內(nèi)存讀寫速度不匹配的矛盾

  說了半天緩存和web開發(fā)有什么必要的聯(lián)系嘛?當(dāng)然有,在整個web開發(fā)的各個階段都可以使用到不同緩存,比如瀏覽器緩存頁面等靜態(tài)資源,tomcat服務(wù)器應(yīng)用層緩存查詢過的數(shù)據(jù),數(shù)據(jù)庫緩存索引信息等

緩存的優(yōu)點

  • 降低后端負載
  • 提高讀寫效率,降低響應(yīng)時間

緩存的缺點

  • 數(shù)據(jù)更新前后緩存區(qū)中該數(shù)據(jù)的一致性難保證
  • 解決數(shù)據(jù)一致性需要復(fù)雜的業(yè)務(wù)代碼,提高后續(xù)維護成本
  • 集群模式下提高運維成本

Redis緩存已查詢數(shù)據(jù)

  在未使用緩存之前,用戶的所有請求都會直接訪問數(shù)據(jù)庫,但是使用redis作為緩存之后就不一樣了。用戶的請求會是先在redis中查找,如果查到也就是命中的話就直接返回客戶端,如果未命中的話就去數(shù)據(jù)庫中查找,查到有結(jié)果就將查詢到的結(jié)果寫入redis中,然后返回給客戶端;未查到結(jié)果就返回404狀態(tài)碼

redis緩存中間件實踐

  黑馬點評中有這么一個業(yè)務(wù):點擊商鋪圖片會通過id查詢該商鋪的相關(guān)信息,如果使用redis緩存的話,后期再訪問該商鋪的話就會直接到redis中查詢,可以大大縮短查詢所需時間

collector中定義與前端交互的方法,前端請求/shop-type/list?id=xx

@RestController
@RequestMapping("/shop")
public class ShopController {
    @Resource
    public IShopService shopService;
    /**
     * 根據(jù)id查詢商鋪信息
     * @param id 商鋪id
     * @return 商鋪詳情數(shù)據(jù)
     */
    @GetMapping("/{id}")
    public Result queryShopById(@PathVariable("id") Long id) {
        return shopService.queryById(id);
    }
}

編寫typeService里業(yè)務(wù)邏輯方法getList的接口和實現(xiàn)類,邏輯參考Redis緩存已查詢數(shù)據(jù)的相關(guān)分析

@Service
public class ShopServiceImpl extends ServiceImpl<ShopMapper, Shop> implements IShopService {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Override
    public Result queryById(Long id) {
        // 從redis查詢商鋪緩存
        String shopJson = stringRedisTemplate.opsForValue().get(RedisConstants.CACHE_SHOP_KEY + id);
        // 判斷該商鋪是否存在
        if (StrUtil.isNotBlank(shopJson)) {
            // 存在直接返回
            Shop shop = JSONUtil.toBean(shopJson, Shop.class);
            return Result.ok(shop);
        }
        // 不存在查詢數(shù)據(jù)庫
        Shop shop = getById(id);
        if (shop == null) {
            // 數(shù)據(jù)庫中不存在直接返回錯誤信息
            return Result.fail("店鋪不存在");
        }
        // 數(shù)據(jù)庫中存在寫入redis
        stringRedisTemplate.opsForValue().set(RedisConstants.CACHE_SHOP_KEY + id, JSONUtil.toJsonStr(shop));
        // 返回
        return Result.ok(shop);
    }
}

  經(jīng)實驗驗證得知,使用redis緩存未命中時查詢耗時將近200毫秒,后續(xù)查詢命中之后只需幾毫秒,可見redis作為緩存中間件對數(shù)據(jù)讀取的功效還是很高的

緩存更新

  之前介紹redis的時候介紹過redis緩存的一些缺點,比如數(shù)據(jù)庫中數(shù)據(jù)更新前后緩存區(qū)中該數(shù)據(jù)的一致性難保證,該怎么應(yīng)對redis緩存的這個缺點呢?這就引出接下來的學(xué)習(xí)內(nèi)容——緩存更新策略

緩存更新的三個策略

  內(nèi)存淘汰: redis底層的內(nèi)存淘汰機制,無需我們自己維護,當(dāng)內(nèi)存不足時自動淘汰部分數(shù)據(jù),下次查詢時更新緩存。這種機制的優(yōu)點是維護成本極低,但是缺點也很明顯,由于淘汰數(shù)據(jù)的不確定性導(dǎo)致很難保證數(shù)據(jù)的一致性

  超時剔除: 向redis中添加緩存數(shù)據(jù)的時候設(shè)置TTL時間,到期后自動刪除緩存,下次查詢時更新緩存。這種機制維護成本不是很高,但是數(shù)據(jù)一致性同樣無法做到很高的保證,因為設(shè)置之后數(shù)據(jù)的有效期就固定了,但是更新時間不固定,若是數(shù)據(jù)在超時剔除之前發(fā)生更新然后查詢,得到的仍是更新之前的數(shù)據(jù)

  主動更新: 使用代碼在修改數(shù)據(jù)庫的同時更新緩存。這種策略能夠保證很高的數(shù)據(jù)一致性,但是伴隨而來的就是更高的維護成本,要在每一個更改語句后面加上redis緩存更新

  具體使用哪種策略取決于該業(yè)務(wù)對數(shù)據(jù)一致性的需求:一致性需求不高的話,可以使用內(nèi)存淘汰策略。一致性需求較高的話,可以使用主動更新加上超時剔除策略,保證了較高的一致性

主動更新策略的三種方案

  代碼(Cache Aside Pattern):最直接的一種方案,使用代碼在修改數(shù)據(jù)庫的同時更新緩存

  服務(wù)(Read/Warite Through Pattern):將redis緩存與數(shù)據(jù)庫整合為一個服務(wù),由這個服務(wù)來維護數(shù)據(jù)的一致性,在更新數(shù)據(jù)庫時只需要調(diào)用該服務(wù)即可,無需關(guān)心服務(wù)底層的業(yè)務(wù)邏輯,類似于封裝。但是市面上沒有現(xiàn)成的服務(wù)可以使用,自己封裝這么一個服務(wù)也很復(fù)雜,所以說這種方案可用性很差

  寫回(Write Behind Caching Pattern):所有數(shù)據(jù)庫的CRUD操作都在redis緩存中完成,由另外一個獨立的線程異步的將緩存中的數(shù)據(jù)持久化到數(shù)據(jù)庫中,以此來保證數(shù)據(jù)的最終一致。這種方案有個很大的好處,那就是極大地減少了對數(shù)據(jù)庫的操作,如果主線程在另一個線程兩次持久化之間對redis中的數(shù)據(jù)操作多次,數(shù)據(jù)庫中只會執(zhí)行最后一次操作,而不是也操作多次。但是也有壞處,那就是如果還沒等到另一個線程持久化數(shù)據(jù)庫,此時redis緩存發(fā)生宕機,緩存大多數(shù)在內(nèi)存中,此時發(fā)生宕機就會導(dǎo)致緩存中的數(shù)據(jù)消失,數(shù)據(jù)庫中的數(shù)據(jù)就與宕機前redis中的數(shù)據(jù)不一致

  綜上所述,雖然Cache Aside Pattern方案是最復(fù)雜的一個,但是他也同樣是最可靠的一個,于是我們選擇它來進行接下來的代碼學(xué)習(xí)

主動更新策略注意項

  數(shù)據(jù)庫發(fā)生更新的時候直接刪除緩存中的該數(shù)據(jù),而不是跟著更新緩存,因為如果發(fā)生連續(xù)修改多次的情況,更新緩存的話更新次數(shù)等于數(shù)據(jù)庫的更新次數(shù);如果是刪除緩存數(shù)據(jù)的話就只需要刪除一次,下一次查詢直接從數(shù)據(jù)庫中查詢再寫入緩存。

  刪除緩存數(shù)據(jù)和數(shù)據(jù)庫操作應(yīng)該保證原子性,也就是說刪除緩存數(shù)據(jù)操作和數(shù)據(jù)庫操作應(yīng)該同時成功或者同時失敗,那么該如何實現(xiàn)呢?單體式系統(tǒng)中,可以通過將兩個操作放在一個事務(wù)中來完成;分布式系統(tǒng)中可以利用TCC等分布式事務(wù)方案來實現(xiàn)

  刪除緩存數(shù)據(jù)操作和數(shù)據(jù)庫操作的先后順序是什么? 應(yīng)該是先寫數(shù)據(jù)庫再刪除緩存,原因是這種方式發(fā)生線程安全性問題的可能較小

主動更新的代碼實現(xiàn)

controller層前端交互

/**
 * 更新商鋪信息
 * @param shop 商鋪數(shù)據(jù)
 * @return 無
 */
@PutMapping
public Result updateShop(@RequestBody Shop shop) {
    // 寫入數(shù)據(jù)庫
    return shopService.update(shop);
}

  需要server的update方法,創(chuàng)建接口和實現(xiàn)類完成業(yè)務(wù)邏輯代碼編寫。主動更新+超時剔除的策略就只有兩步,那就是在寫緩存的時候設(shè)置超時時間,更新數(shù)據(jù)庫之后刪除緩存

// 數(shù)據(jù)庫中存在寫入redis的時候設(shè)置超時時間
stringRedisTemplate.opsForValue().set(RedisConstants.CACHE_SHOP_KEY + id, JSONUtil.toJsonStr(shop), RedisConstants.CACHE_SHOP_TTL, TimeUnit.MINUTES);
/**
 * 更新商鋪信息
 * @param shop  商鋪信息
 * @return 前端返回數(shù)據(jù)
 */
@Override
@Transactional
public Result update(Shop shop) {
    if (shop.getId() == null) {
        return Result.fail("店鋪id不能為空");
    }
    // 更新數(shù)據(jù)庫
    updateById(shop);
    // 刪除緩存
    stringRedisTemplate.delete(RedisConstants.CACHE_SHOP_KEY + shop.getId());
    // 返回
    return Result.ok();
}

到此這篇關(guān)于Redis緩存策略超詳細講解的文章就介紹到這了,更多相關(guān)Redis緩存策略內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 分析Java中ArrayList與LinkedList列表結(jié)構(gòu)的源碼

    分析Java中ArrayList與LinkedList列表結(jié)構(gòu)的源碼

    這篇文章主要介紹了Java中ArrayList與LinkedList列表結(jié)構(gòu)的源碼,文章最后對LinkedList和ArrayList以及Vector的特性有一個對比總結(jié),需要的朋友可以參考下
    2016-05-05
  • 淺談java實現(xiàn)重載的方法

    淺談java實現(xiàn)重載的方法

    方法重載是讓類以統(tǒng)一的方式處理不同類型數(shù)據(jù)的一種手段。多個同名函數(shù)同時存在,具有不同的參數(shù)個數(shù)/類型。重載Overloading是一個類中多態(tài)性的一種表現(xiàn)。Java的方法重載,就是在類中可以創(chuàng)建多個方法,它們具有相同的名字,但具有不同的參數(shù)和不同的定義。
    2015-09-09
  • Java工廠模式的使用細則介紹

    Java工廠模式的使用細則介紹

    工廠模式,是一種實例化對象的方式,只要輸入需要實例化對象的名字,就可以通過工廠對象的相應(yīng)工廠函數(shù)來制造你需要的對象
    2023-02-02
  • java并發(fā)學(xué)習(xí)-CountDownLatch實現(xiàn)原理全面講解

    java并發(fā)學(xué)習(xí)-CountDownLatch實現(xiàn)原理全面講解

    這篇文章主要介紹了java并發(fā)學(xué)習(xí)-CountDownLatch實現(xiàn)原理全面講解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • volatile與happens-before的關(guān)系與內(nèi)存一致性錯誤

    volatile與happens-before的關(guān)系與內(nèi)存一致性錯誤

    本文講了Java并發(fā)編程中volatile變量、happens-before與內(nèi)存一致性錯誤,下面來和小編一起學(xué)習(xí)下如何解決
    2019-05-05
  • 利用Java簡單實現(xiàn)一個代碼行數(shù)統(tǒng)計器方法實例

    利用Java簡單實現(xiàn)一個代碼行數(shù)統(tǒng)計器方法實例

    這篇文章主要給大家介紹了關(guān)于如何利用Java簡單實現(xiàn)一個代碼行數(shù)統(tǒng)計器的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • 如何在32位Windows系統(tǒng)下安裝Java

    如何在32位Windows系統(tǒng)下安裝Java

    這篇文章主要介紹了如何在32位Windows系統(tǒng)下安裝Java,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • Java中打亂一個數(shù)組的2種公平算法分享

    Java中打亂一個數(shù)組的2種公平算法分享

    這篇文章主要介紹了Java中打亂一個數(shù)組的2種公平算法分享,本文講解了洗牌程序原理、生成隨機索引交換二種方法并給出示例代碼,需要的朋友可以參考下
    2015-03-03
  • Java項目常見工具類詳解

    Java項目常見工具類詳解

    這篇文章主要為大家總結(jié)了平時在Java項目中使用的工具類:JWT工具類、MD5工具類、視頻點播工具類、公共常量工具類、日期操作工具類、Http客戶端工具類和獲取IP工具類。需要的可以參考一下
    2021-12-12
  • MyBatis-Plus中使用EntityWrappe進行列表數(shù)據(jù)倒序設(shè)置方式

    MyBatis-Plus中使用EntityWrappe進行列表數(shù)據(jù)倒序設(shè)置方式

    這篇文章主要介紹了MyBatis-Plus中使用EntityWrappe進行列表數(shù)據(jù)倒序設(shè)置方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03

最新評論

信宜市| 永州市| 河池市| 大丰市| 巫山县| 盐亭县| 稻城县| 剑阁县| 茶陵县| 邯郸市| 莎车县| 甘孜县| 乐陵市| 正定县| 浦东新区| 崇文区| 新津县| 玉树县| 理塘县| 墨竹工卡县| 华容县| 石门县| 浠水县| 高州市| 偃师市| 临沂市| 广丰县| 高密市| 福州市| 双桥区| 永吉县| 南投县| 石棉县| 抚顺市| 浦城县| 册亨县| 中阳县| 瓦房店市| 工布江达县| 汉川市| 浦江县|