宅男在线永久免费观看网直播,亚洲欧洲日产国码无码久久99,野花社区在线观看视频,亚洲人交乣女bbw,一本一本久久a久久精品综合不卡

全部
常見(jiàn)問(wèn)題
產(chǎn)品動(dòng)態(tài)
精選推薦

淺談Redis緩存的穿透、擊穿和雪崩

管理 管理 編輯 刪除

Redis是一種流行的內(nèi)存緩存解決方案,但在實(shí)際使用中,會(huì)遇到一些緩存相關(guān)的問(wèn)題,其中最主要的就是緩存穿透,擊穿和雪崩問(wèn)題。

一、緩存穿透

緩存穿透是指當(dāng)查詢一個(gè)不存在的緩存時(shí),由于緩存中沒(méi)有相應(yīng)的數(shù)據(jù),而數(shù)據(jù)庫(kù)中也不存在對(duì)應(yīng)的數(shù)據(jù),導(dǎo)致每次查詢都必須訪問(wèn)數(shù)據(jù)庫(kù),這會(huì)導(dǎo)致數(shù)據(jù)庫(kù)的負(fù)載過(guò)高。攻擊者可以利用這個(gè)漏洞進(jìn)行惡意攻擊,通過(guò)不斷查詢不存在的緩存,來(lái)使緩存服務(wù)器或者數(shù)據(jù)庫(kù)癱瘓。

關(guān)于緩存穿透常用的的有兩種解決辦法:

第一種,緩存空數(shù)據(jù),當(dāng)查詢一個(gè)不存在的數(shù)據(jù)時(shí),可以將這個(gè)查詢結(jié)果緩存起來(lái),以空對(duì)象的形式存儲(chǔ)在緩存中。這樣,在下一次查詢時(shí),如果緩存中存在這個(gè)空對(duì)象,就可以直接返回,而不會(huì)再次查詢數(shù)據(jù)庫(kù)或接口。

第二種,使用布隆過(guò)濾器

<?php

/**
 * 布隆過(guò)濾器類
 */
class BloomFilter {
    private $redis; // Redis對(duì)象
    private $bitmapSize; // 位圖大小
    private $hashCount; // 哈希函數(shù)數(shù)量

    /**
     * 構(gòu)造函數(shù)
     * @param int $bitmapSize 位圖大小,默認(rèn)為1024
     * @param int $hashCount 哈希函數(shù)數(shù)量,默認(rèn)為3
     */
    public function __construct($bitmapSize = 1024, $hashCount = 3) {
        // 實(shí)例化Redis對(duì)象并連接到Redis服務(wù)器
		$redis = new Redis();
		$redis->connect('127.0.0.1', 6379);
		$this->redis = $redis;
        $this->bitmapSize = $bitmapSize;
        $this->hashCount = $hashCount;
    }

    /**
     * 插入元素到布隆過(guò)濾器中
     * @param string $element 要插入的元素
     */
    public function insert($element) {
        // 對(duì)元素進(jìn)行多次哈希,并在位圖中設(shè)置相應(yīng)位置為1
        for ($i = 1; $i <= $this->hashCount; $i++) {
            $hash = md5($element . $i);
            $position = hexdec(substr($hash, 0, 6)) % $this->bitmapSize;
            $this->redis->setBit('bloom_filter', $position, 1);
        }
    }

    /**
     * 判斷元素是否存在于布隆過(guò)濾器中
     * @param string $element 要判斷的元素
     * @return bool 如果存在返回true,否則返回false
     */
    public function contains($element) {
        // 對(duì)元素進(jìn)行多次哈希,并檢查位圖相應(yīng)位置是否為1
        for ($i = 1; $i <= $this->hashCount; $i++) {
            $hash = md5($element . $i);
            $position = hexdec(substr($hash, 0, 6)) % $this->bitmapSize;
            if (!$this->redis->getBit('bloom_filter', $position)) {
                // 如果任意一個(gè)位置為0,則表示元素不存在于布隆過(guò)濾器中
                return false;
            }
        }
        // 如果所有位置都為1,則表示元素可能存在于布隆過(guò)濾器中
        return true;
    }
}

// 緩存穿透解決方案
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

// 實(shí)例化布隆過(guò)濾器對(duì)象
$bloomFilter = new BloomFilter($redis);
$cacheKey = 'product_info_123';
if ($bloomFilter->contains($cacheKey)) {
    $productInfo = $redis->get($cacheKey);
    if ($productInfo) {
        return $productInfo;
    }
} else {
    // 如果布隆過(guò)濾器中不存在該鍵,則直接返回空結(jié)果
    return null;
}

// 如果緩存中不存在該鍵,則從數(shù)據(jù)庫(kù)中查詢并存入緩存和布隆過(guò)濾器中
$productInfo = $database->queryProductInfoById(123);
if (!$productInfo) {
    // 如果數(shù)據(jù)庫(kù)中也不存在該記錄,則插入一個(gè)空記錄,防止緩存穿透攻擊
    $productInfo = '';
    $redis->set($cacheKey, 60, $productInfo);
} else {
    $redis->set($cacheKey, 60, $productInfo);
    $bloomFilter->insert($cacheKey);
}
return $productInfo;

二、緩存擊穿

緩存擊穿是指當(dāng)某個(gè)熱點(diǎn)數(shù)據(jù)失效時(shí),大量的并發(fā)請(qǐng)求訪問(wèn)這個(gè)熱點(diǎn)數(shù)據(jù),導(dǎo)致所有請(qǐng)求都訪問(wèn)數(shù)據(jù)庫(kù),從而使數(shù)據(jù)庫(kù)的負(fù)載急劇增加。為了避免這種情況發(fā)生,可以將熱點(diǎn)數(shù)據(jù)的緩存時(shí)間設(shè)置為永不過(guò)期,或者設(shè)置一個(gè)較長(zhǎng)的過(guò)期時(shí)間。

$redis->set($key, $value, -1) 和$redis->set($key, $value) 都可以用來(lái)設(shè)置緩存數(shù)據(jù),并且讓緩存永不過(guò)期。

三、緩存雪崩

緩存雪崩是指當(dāng)某一時(shí)刻緩存中的大量數(shù)據(jù)同時(shí)失效時(shí),大量的并發(fā)請(qǐng)求訪問(wèn)這些失效的數(shù)據(jù),導(dǎo)致所有請(qǐng)求都訪問(wèn)數(shù)據(jù)庫(kù),從而使數(shù)據(jù)庫(kù)的負(fù)載急劇增加。為了避免這個(gè)問(wèn)題,我們可以設(shè)置緩存的過(guò)期時(shí)間隨機(jī)化,使緩存的失效時(shí)間不同,避免大量數(shù)據(jù)同時(shí)失效。此外,我們也可以采用緩存預(yù)熱的方式,提前將熱點(diǎn)數(shù)據(jù)加載到緩存中,以減少緩存的失效率。

在實(shí)際應(yīng)用中,可以通過(guò)設(shè)置一個(gè)隨機(jī)數(shù)生成器,隨機(jī)生成一個(gè)緩存時(shí)間偏移量,然后將緩存時(shí)間加上偏移量作為實(shí)際緩存時(shí)間。例如,在一個(gè)緩存時(shí)間為60秒的基礎(chǔ)上,可以隨機(jī)生成一個(gè)0到10秒的偏移量,然后將緩存時(shí)間設(shè)置為60秒加上該偏移量,即在60到70秒之間隨機(jī)。

// 緩存時(shí)間
$cache_time = 60;

// 生成隨機(jī)偏移量
$offset = rand(0, 10);

// 設(shè)置緩存時(shí)間
$expire_time = $cache_time + $offset;

// 設(shè)置緩存
$redis->set($key, $value, $expire_time);



請(qǐng)登錄后查看

徐斗明 最后編輯于2023-09-13 14:10:07

快捷回復(fù)
回復(fù)
回復(fù)
回復(fù)({{post_count}}) {{!is_user ? '我的回復(fù)' :'全部回復(fù)'}}
排序 默認(rèn)正序 回復(fù)倒序 點(diǎn)贊倒序

{{item.user_info.nickname ? item.user_info.nickname : item.user_name}} LV.{{ item.user_info.bbs_level || item.bbs_level }}

作者 管理員 企業(yè)

{{item.floor}}# 同步到gitee 已同步到gitee {{item.is_suggest == 1? '取消推薦': '推薦'}}
{{item.is_suggest == 1? '取消推薦': '推薦'}}
沙發(fā) 板凳 地板 {{item.floor}}#
{{item.user_info.title || '暫無(wú)簡(jiǎn)介'}}
附件

{{itemf.name}}

{{item.created_at}}  {{item.ip_address}}
打賞
已打賞¥{{item.reward_price}}
{{item.like_count}}
{{item.showReply ? '取消回復(fù)' : '回復(fù)'}}
刪除
回復(fù)
回復(fù)

{{itemc.user_info.nickname}}

{{itemc.user_name}}

回復(fù) {{itemc.comment_user_info.nickname}}

附件

{{itemf.name}}

{{itemc.created_at}}
打賞
已打賞¥{{itemc.reward_price}}
{{itemc.like_count}}
{{itemc.showReply ? '取消回復(fù)' : '回復(fù)'}}
刪除
回復(fù)
回復(fù)
查看更多
打賞
已打賞¥{{reward_price}}
2416
{{like_count}}
{{collect_count}}
添加回復(fù) ({{post_count}})

相關(guān)推薦

快速安全登錄

使用微信掃碼登錄
{{item.label}} 加精
{{item.label}} {{item.label}} 板塊推薦 常見(jiàn)問(wèn)題 產(chǎn)品動(dòng)態(tài) 精選推薦 首頁(yè)頭條 首頁(yè)動(dòng)態(tài) 首頁(yè)推薦
取 消 確 定
回復(fù)
回復(fù)
問(wèn)題:
問(wèn)題自動(dòng)獲取的帖子內(nèi)容,不準(zhǔn)確時(shí)需要手動(dòng)修改. [獲取答案]
答案:
提交
bug 需求 取 消 確 定
打賞金額
當(dāng)前余額:¥{{rewardUserInfo.reward_price}}
{{item.price}}元
請(qǐng)輸入 0.1-{{reward_max_price}} 范圍內(nèi)的數(shù)值
打賞成功
¥{{price}}
完成 確認(rèn)打賞

微信登錄/注冊(cè)

切換手機(jī)號(hào)登錄

{{ bind_phone ? '綁定手機(jī)' : '手機(jī)登錄'}}

{{codeText}}
切換微信登錄/注冊(cè)
暫不綁定
CRMEB客服

CRMEB咨詢熱線 咨詢熱線

400-8888-794

微信掃碼咨詢

CRMEB開(kāi)源商城下載 源碼下載 CRMEB幫助文檔 幫助文檔
返回頂部 返回頂部
CRMEB客服