国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Redis數(shù)據(jù)緩存

這篇具有很好參考價值的文章主要介紹了Redis數(shù)據(jù)緩存。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

緩存

一 緩存基礎(chǔ)

1 緩存的概念和作用

緩存就是數(shù)據(jù)交換的緩沖區(qū)(稱作Cache),是存貯數(shù)據(jù)的臨時地方,一般讀寫性能較高

Redis數(shù)據(jù)緩存,緩存,redis,數(shù)據(jù)庫

2 緩存的使用

之前沒有使用緩存是的模型

Redis數(shù)據(jù)緩存,緩存,redis,數(shù)據(jù)庫

3 項目說明

Redis數(shù)據(jù)緩存,緩存,redis,數(shù)據(jù)庫

當我們查詢商家信息的時候,直接從mysql中獲取的。現(xiàn)在我們將原來的項目改造。改造地方在ShopController,我們按照流程圖去做,添加redis緩存,業(yè)務(wù)都是在service中實現(xiàn)的。

# 具體實現(xiàn)流程
1 redis中查詢商戶緩存
2 判斷是否存在
3 存在直接返回
4 不存在根據(jù)id去數(shù)據(jù)庫查詢
5 數(shù)據(jù)庫也不存在,返回錯誤
6 存在則寫入redis中
7 返回
<dependency>
 ? ?<groupId>com.alibaba</groupId>
 ? ?<artifactId>fastjson</artifactId>
 ? ?<version>1.2.47</version>
</dependency>
1 修改controller
/**
 ? ?* 根據(jù)id查詢商鋪信息
 ? ? * @param id 商鋪id
 ? ? * @return 商鋪詳情數(shù)據(jù)
*/
@GetMapping("/{id}")
public Result queryShopById(@PathVariable("id") Long id) {
 ? ?return shopService.queryById(id);
 ? ?// ? ? ?  return Result.ok(shopService.getById(id));
}
2 修改service
@Resource
private RedisTemplate<String,Object> redisTemplate;
?
@Override
public Result queryById(Long id) {
 ? ?//1 redis中查詢商戶緩存
 ? ?String shopJson = (String)redisTemplate.opsForValue().get("cache.shop:" + id);
 ? ?//2 判斷是否存在
 ? ?if(StrUtil.isNotBlank(shopJson)){
 ? ? ? ?//3存在直接返回
 ? ? ? ?Shop shop = JSONUtil.toBean(shopJson, Shop.class);
 ? ? ? ?return Result.ok(shop);
 ?  }
 ? ?//4 不存在根據(jù)id去數(shù)據(jù)庫查詢
 ? ?Shop shop = this.getById(id);
 ? ?//5 數(shù)據(jù)庫也不存在,返回錯誤
 ? ?if(shop==null){
 ? ? ? ?return Result.fail("店鋪不存在");
 ?  }
 ? ?//6 存在則寫入redis中
 ? ?redisTemplate.opsForValue().set("cache.shop:" + id,JSONUtil.toJsonStr(shop));
 ? ?//7 返回
 ? ?return Result.ok(shop);
}
3 改造首頁

Redis數(shù)據(jù)緩存,緩存,redis,數(shù)據(jù)庫

@Autowired
private RedisTemplate<String, Object> redisTemplate;
?
@Override
public Result queryTypeList() {
?
 ? ?List<Object> list = redisTemplate.opsForList().range("cache.list",0,-1);
 ? ?if(list!=null && list.size()!=0){
 ? ? ? ?return Result.ok(list);
 ?  }
 ? ?List<ShopType> sort = this.query().orderByAsc("sort").list();
 ? ?if(sort==null||sort.size()==0){
 ? ? ? ?return Result.fail("列表不存在");
 ?  }
 ? ?sort.forEach(s->redisTemplate.opsForList().rightPush("cache.list",s));
 ? ?return Result.ok(sort);
}

二 數(shù)據(jù)一致性

1 思路

  • 查詢數(shù)據(jù)的時候,如果緩存未命中,則查詢數(shù)據(jù)庫,將數(shù)據(jù)寫入緩存設(shè)置超時時間

  • 修改數(shù)據(jù)時,先修改數(shù)據(jù)庫,在刪除緩存。

  • 延時雙刪策略

2 代碼實現(xiàn)

  • 修改更新方法,添加超時時間

 @Override
    public Result queryById(Long id) {
        //1 redis中查詢商戶緩存
        String shopJson = (String)redisTemplate.opsForValue().get("cache.shop:" + id);
        //2 判斷是否存在
        if(StrUtil.isNotBlank(shopJson)){
            //3存在直接返回
            Shop shop = JSONUtil.toBean(shopJson, Shop.class);
            return Result.ok(shop);
        }
        //4 不存在根據(jù)id去數(shù)據(jù)庫查詢
        Shop shop = this.getById(id);
        //5 數(shù)據(jù)庫也不存在,返回錯誤
        if(shop==null){
            return Result.fail("店鋪不存在");
        }
        //6 存在則寫入redis中
       redisTemplate.opsForValue().set("cache.shop:" + id,JSONUtil.toJsonStr(shop),30, TimeUnit.MINUTES);
        //7 返回
        return Result.ok(shop);
    }
  • 修改ShopController

 ?
@PutMapping
 ? ?public Result updateShop(@RequestBody Shop shop) {
 ? ? ? ?// 寫入數(shù)據(jù)庫
?
 ? ? ? ?//shopService.updateById(shop);
 ? ? ? ?//return Result.ok();
 ? ? ? ?return ?shopService.update(shop);
 ?  }
  • 修改service代碼 延時雙刪策略

?@Override
 ? ?public Result update(Shop shop) {
?
 ? ? ? ?Long id = shop.getId();
 ? ? ? ?if(id==null){
 ? ? ? ? ? ?return Result.fail("店鋪id不存在");
 ? ? ?  }
 ? ? ? ? // 刪除緩存
 ? ? ? ?redisTemplate.delete("cache.shop:" + id);
 ? ? ? ?// 更新數(shù)據(jù)庫
 ? ? ? ?updateById(shop);
 ? ? ? ?Thread.sleep(800);
 ? ? ? ?// 刪除緩存
 ? ? ? ?redisTemplate.delete("cache.shop:" + id);
 ? ? ? ?return Result.ok();
 ?  }

3 修改完代碼以后,將所有的緩存刪除,執(zhí)行查詢操作,多了超時

Redis數(shù)據(jù)緩存,緩存,redis,數(shù)據(jù)庫

4 用postman執(zhí)行修改方法: localhost:8081/shop

{
  "area":"大關(guān)",
  "sold":3035,
  "address":"金華路錦昌文華苑29號",
  "name":"102茶餐廳",
  "x":120.149192,
  "y":30.316078,
  "typeId":1,
  "id":1
}

Redis數(shù)據(jù)緩存,緩存,redis,數(shù)據(jù)庫

執(zhí)行完成以后,數(shù)據(jù)庫的數(shù)據(jù)發(fā)生改變,查看redis的數(shù)據(jù)已經(jīng)刪除了。

三 緩存常見問題

1 緩存穿透:

客戶端請求的數(shù)據(jù),在數(shù)據(jù)庫和redis中都不存在,這樣緩存永遠都不會生效,請求最終都到了數(shù)據(jù)庫上。

解決方案:

  • 當在數(shù)據(jù)庫查詢的結(jié)果也不存在的時候,可以返回null值給redis,并且設(shè)置TTL

Redis數(shù)據(jù)緩存,緩存,redis,數(shù)據(jù)庫

  • 布隆過濾器

    Redis數(shù)據(jù)緩存,緩存,redis,數(shù)據(jù)庫

布隆過濾器是一種數(shù)據(jù)結(jié)構(gòu),底層是位數(shù)組,通過將集合中的元素多次hash得到的結(jié)果保存到布隆過濾器中。主要作用就是可以快速判斷一個元素是否在集合里面,但是因為算法的原因,也有一定概率的錯誤。

開發(fā)的時候我們一般選擇空值值方式。

  • 代碼方式實現(xiàn)

    Redis數(shù)據(jù)緩存,緩存,redis,數(shù)據(jù)庫

根據(jù)id查詢的時候,如果信息不存在,則要將空值寫入redis,并設(shè)置空值過期時間

@Override
    public Result queryById(Long id) {
        //1 redis中查詢商戶緩存
        String shopJson = (String)redisTemplate.opsForValue().get("cache.shop:" + id);
        //2 判斷是否存在
        if(StrUtil.isNotBlank(shopJson)){
            //3存在直接返回
            Shop shop = JSONUtil.toBean(shopJson, Shop.class);
            return Result.ok(shop);
        }
        if(shopJson!=null){
            return Result.fail("店鋪不存在");
        }
        //4 不存在根據(jù)id去數(shù)據(jù)庫查詢
        Shop shop = this.getById(id);
        //5 數(shù)據(jù)庫也不存在,返回錯誤
        if(shop==null){
            // 空值寫入redis中
            redisTemplate.opsForValue().set("cache.shop:" + id,"",3, TimeUnit.MINUTES);
            return Result.fail("店鋪不存在");
        }
        //6 存在則寫入redis中
       redisTemplate.opsForValue().set("cache.shop:" + id,JSONUtil.toJsonStr(shop),30, TimeUnit.MINUTES);
        //7 返回
        return Result.ok(shop);
    }

2 緩存擊穿:

也叫熱點key問題,一個被高并發(fā)訪問且業(yè)務(wù)復(fù)雜的key突然失效了,無數(shù)的請求瞬間給數(shù)據(jù)庫帶來的巨大沖擊

Redis數(shù)據(jù)緩存,緩存,redis,數(shù)據(jù)庫

解決方案: 互斥鎖 邏輯過期

Redis數(shù)據(jù)緩存,緩存,redis,數(shù)據(jù)庫

互斥鎖思路:

Redis數(shù)據(jù)緩存,緩存,redis,數(shù)據(jù)庫

查詢緩存的時候,未命中需要獲取鎖 代碼ShopServiceImpl

@Override
public Result queryById(Long id) {
    //1 redis中查詢商戶緩存
    String shopJson = (String)redisTemplate.opsForValue().get("cache.shop:" + id);
    //2 判斷是否存在
    if(StrUtil.isNotBlank(shopJson)){
        //3存在直接返回
        Shop shop = JSONUtil.toBean(shopJson, Shop.class);
        return Result.ok(shop);
    }
    if(shopJson!=null){
        return Result.fail("店鋪不存在");
    }
    Shop shop = null;
    String lockKey = "lock.id:" + id;
    try {
        //代碼到這里說明沒有命中緩存,那么就可以獲取鎖了
        boolean isLock = tryLock(lockKey);
        // 如果沒有拿到鎖,則等待一會,遞歸執(zhí)行代碼
        if(!isLock){
            Thread.sleep(100);
            queryById(id);
        }
        //獲取鎖成功
        //4 不存在根據(jù)id去數(shù)據(jù)庫查詢
        shop = this.getById(id);
        //5 數(shù)據(jù)庫也不存在,返回錯誤
        if(shop==null){
            // 空值寫入redis中
            redisTemplate.opsForValue().set("cache.shop:" + id,"",3, TimeUnit.MINUTES);
            return Result.fail("店鋪不存在");
        }
        //6 存在則寫入redis中
        redisTemplate.opsForValue().set("cache.shop:" + id,JSONUtil.toJsonStr(shop),30, TimeUnit.MINUTES);
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        unlock(lockKey);
    }
    //7 返回
    return Result.ok(shop);
}

    // 獲取鎖
private boolean tryLock(String key){
    Boolean flag = redisTemplate.opsForValue().setIfAbsent(key, "1", 10, TimeUnit.SECONDS);
    return BooleanUtil.isTrue(flag);
}
//釋放鎖
private void unlock(String key){
    redisTemplate.delete(key);
}

3 緩存雪崩

同一時間段內(nèi),大量的緩存key失效或者redis宕機,到時大量的請求到達數(shù)據(jù)庫,帶來巨大的壓力。

Redis數(shù)據(jù)緩存,緩存,redis,數(shù)據(jù)庫

解決方案

  • 給key設(shè)置隨機的TTL

  • 集群方案防止宕機不可用文章來源地址http://www.zghlxwxcb.cn/news/detail-796281.html

到了這里,關(guān)于Redis數(shù)據(jù)緩存的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Redis如何保證緩存和數(shù)據(jù)庫一致性?

    現(xiàn)在我們在面向增刪改查開發(fā)時,數(shù)據(jù)庫數(shù)據(jù)量大時或者對響應(yīng)要求較快,我們就需要用到Redis來拿取數(shù)據(jù)。 Redis:是一種高性能的內(nèi)存數(shù)據(jù)庫,它將數(shù)據(jù)以鍵值對的形式存儲在內(nèi)存中,具有讀寫速度快、支持多種數(shù)據(jù)類型、原子性操作、豐富的特性等優(yōu)勢。 優(yōu)勢: 性能極高

    2024年01月16日
    瀏覽(41)
  • Redis---數(shù)據(jù)庫和緩存如何保證一致性?

    用「讀 + 寫」請求的并發(fā)的場景來分析: 假如某個用戶數(shù)據(jù)在緩存中不存在,請求 A 讀取數(shù)據(jù)時從數(shù)據(jù)庫中查詢到年齡為 20,在未寫入緩存中時另一個請求 B 更新數(shù)據(jù)。它更新數(shù)據(jù)庫中的年齡為 21,并且清空緩存。這時請求 A 把從數(shù)據(jù)庫中讀到的年齡為 20 的數(shù)據(jù)寫入到緩存

    2024年01月24日
    瀏覽(27)
  • Redis如何保障緩存與數(shù)據(jù)庫的數(shù)據(jù)一致性問題?

    Redis如何保障緩存與數(shù)據(jù)庫的數(shù)據(jù)一致性問題?

    目錄 一.最經(jīng)典的數(shù)據(jù)庫加緩存的雙寫雙刪模式 二. 高并發(fā)場景下的緩存+數(shù)據(jù)庫雙寫不一致問題分析與解決方案設(shè)計 三、上面高并發(fā)的場景下,該解決方案要注意的問題 1.1 Cache Aside Pattern概念以及讀寫邏輯 (1)讀的時候,先讀緩存,緩存沒有的話,那么就讀數(shù)據(jù)庫,然后取

    2023年04月21日
    瀏覽(29)
  • Springboot+Redis:實現(xiàn)緩存 減少對數(shù)據(jù)庫的壓力

    Springboot+Redis:實現(xiàn)緩存 減少對數(shù)據(jù)庫的壓力

    ????歡迎光臨,終于等到你啦???? ??我是蘇澤,一位對技術(shù)充滿熱情的探索者和分享者。???? ??持續(xù)更新的專欄 Redis實戰(zhàn)與進階 本專欄講解Redis從原理到實踐 這是蘇澤的個人主頁可以看到我其他的內(nèi)容哦???? 努力的蘇澤 http://suzee.blog.csdn.net/ ? 目錄 緩存如何實現(xiàn)?

    2024年03月24日
    瀏覽(19)
  • 數(shù)據(jù)庫緩存服務(wù)——NoSQL之Redis配置與優(yōu)化

    數(shù)據(jù)庫緩存服務(wù)——NoSQL之Redis配置與優(yōu)化

    目錄 一、緩存概念 1.1 系統(tǒng)緩存 1.2 緩存保存位置及分層結(jié)構(gòu) 1.2.1 DNS緩存 1.2.2 應(yīng)用層緩存 1.2.3 數(shù)據(jù)層緩存 1.2.4 硬件緩存 二、關(guān)系型數(shù)據(jù)庫與非關(guān)系型數(shù)據(jù)庫 2.1 關(guān)系型數(shù)據(jù)庫 2.2 非關(guān)系型數(shù)據(jù)庫 2.3 關(guān)系型數(shù)據(jù)庫和非關(guān)系型數(shù)據(jù)庫區(qū)別: 2.4 非關(guān)系型數(shù)據(jù)庫產(chǎn)生背景 2.5 總結(jié)

    2024年02月15日
    瀏覽(24)
  • Redis數(shù)據(jù)庫 | 發(fā)布訂閱、主從復(fù)制、哨兵模式、緩存雪崩

    Redis數(shù)據(jù)庫 | 發(fā)布訂閱、主從復(fù)制、哨兵模式、緩存雪崩

    ??wei_shuo的個人主頁 ??wei_shuo的學習社區(qū) ??Hello World ! Redis 發(fā)布訂閱 (pub/sub) 是一種消息通信模式:發(fā)送者 (pub) 發(fā)送消息,訂閱者 (sub) 接收消息 Redis 客戶端可以訂閱任意數(shù)量的頻道 Redis主從復(fù)制是指在Redis中設(shè)置一個主節(jié)點(Master)和一個或多個從節(jié)點(Slave),

    2024年02月15日
    瀏覽(25)
  • Redis緩存MySQL數(shù)據(jù)庫存儲二者如何保證數(shù)據(jù)一致性

    在大型互聯(lián)網(wǎng)應(yīng)用中,由于數(shù)據(jù)庫讀寫頻繁、壓力大等原因,我們通常會使用緩存來減少數(shù)據(jù)庫的訪問次數(shù),提高系統(tǒng)的性能。而Redis作為一個高性能的內(nèi)存數(shù)據(jù)庫,成為了緩存的首選方案之一。但是,緩存和數(shù)據(jù)庫之間存在數(shù)據(jù)一致性的問題,如何解決這個問題呢?本文將

    2023年04月19日
    瀏覽(27)
  • redis面試題目-如何保證數(shù)據(jù)庫與緩存的數(shù)據(jù)一致性

    原視頻:https://www.bilibili.com/video/BV1Km4y1r75f?p=62vd_source=fa75329ae3880aa55609265a0e9f5d34 由于緩存和數(shù)據(jù)庫是分開的,無法做到原子性的同時進行數(shù)據(jù)修改,可能出現(xiàn)緩存更新失敗,或者數(shù)據(jù)庫更新失敗的情況,這時候會出現(xiàn)數(shù)據(jù)不一致,影響前端業(yè)務(wù) 先更新數(shù)據(jù)庫,再更新緩存。緩

    2024年02月05日
    瀏覽(27)
  • Redis 緩存與數(shù)據(jù)庫雙寫不一致如何解決

    Redis緩存與數(shù)據(jù)庫雙寫不一致是一個常見的挑戰(zhàn),但可以通過一些方法來解決或減輕這種不一致性。以下是一些可能的解決方案: 事務(wù)處理: 在進行緩存和數(shù)據(jù)庫雙寫時,確保它們被包含在同一事務(wù)中。這可以通過使用支持事務(wù)的數(shù)據(jù)庫和Redis事務(wù)來實現(xiàn)。這樣,要么兩者同

    2024年01月21日
    瀏覽(24)
  • 如何保證Redis緩存和數(shù)據(jù)庫的一致性問題

    熟練掌握Redis緩存技術(shù)? 那么請問Redis緩存中有幾種讀寫策略,又是如何保證與數(shù)據(jù)庫的一致性問題 今天來聊一聊常用的三種緩存讀寫策略 首先我們來思考一個問題 寫 先更新緩存 再更新數(shù)據(jù)庫 首先如果緩存更新成功但數(shù)據(jù)庫更新失敗,會導致數(shù)據(jù)不一致的問題 其次當請求

    2024年02月14日
    瀏覽(23)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包