亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Redis 如何批量設(shè)置過期時(shí)間(PIPLINE的使用)

 更新時(shí)間:2021年11月24日 09:13:38   作者:王中陽Go  
有時(shí)候我們并不希望redis的key一直存在。例如緩存,驗(yàn)證碼等數(shù)據(jù),我們希望它們能在一定時(shí)間內(nèi)自動(dòng)的被銷毀。本文就詳細(xì)的介紹一下Redis 如何批量設(shè)置過期時(shí)間,感興趣的可以了解一下

合理的使用緩存策略對(duì)開發(fā)同學(xué)來講,就好像孫悟空習(xí)得自在極意功一般~

Redis如何批量設(shè)置過期時(shí)間呢?

不要說在foreach中通過set()函數(shù)批量設(shè)置過期時(shí)間

我們引入redis的PIPLINE,來解決批量設(shè)置過期時(shí)間的問題。

PIPLINE的原理是什么?

未使用pipline執(zhí)行N條命令

使用pipline執(zhí)行N條命令

通過圖例可以很明顯的看出來PIPLINE的原理:

客戶端通過PIPLINE拼接子命令,只需要發(fā)送一次請(qǐng)求,在redis收到PIPLINE命令后,處理PIPLINE組成的命令塊,減少了網(wǎng)絡(luò)請(qǐng)求響應(yīng)次數(shù)。

網(wǎng)絡(luò)延遲越大PIPLINE的優(yōu)勢(shì)越能體現(xiàn)出來

拼接的子命令條數(shù)越多使用PIPLINE的優(yōu)勢(shì)越能體現(xiàn)出來

注意:并不是拼接的子命令越多越好,N值也有是上限的,當(dāng)拼接命令過長(zhǎng)時(shí)會(huì)導(dǎo)致客戶端等待很長(zhǎng)時(shí)間,造成網(wǎng)絡(luò)堵塞;我們可以根據(jù)實(shí)際情況,把大批量命令拆分成幾個(gè)PIPLINE執(zhí)行。

代碼封裝

//批量設(shè)置過期時(shí)間
public static function myPut(array $data, $ttl = 0)
{
    if (empty($data)) {
        return false;
    }

    $pipeline = Redis::connection('cache')
        ->multi(\Redis::PIPELINE);
    foreach ($data as $key => $value) {
        if (empty($value)) {
            continue;
        }
        if ($ttl == 0) {
            $pipeline->set(trim($key), $value);
        } else {
            $pipeline->set(trim($key), $value, $ttl);
        }
    }
    $pipeline->exec();
}

項(xiàng)目實(shí)戰(zhàn)

需求描述

  • 打開APP,給喜歡我的人發(fā)送我的上線通知(為了避免打擾,8小時(shí)內(nèi)重復(fù)登錄不觸發(fā)通知)
  • 每個(gè)人每半小時(shí)只會(huì)收到一次這類上線通知(即半小時(shí)內(nèi)就算我喜歡的1萬人都上線了,我也只收到一次喜歡的人上線通知)

要點(diǎn)分析

  • 合理使用緩存,減少DB讀寫次數(shù)
  • 不僅要減少DB讀寫次數(shù),也要減少Redis的讀寫次數(shù),使用PIPLINE

代碼實(shí)現(xiàn)解析

  • canRecall() 寫的比較優(yōu)雅,先判斷是否已發(fā)送的標(biāo)記,再判斷HouseOpen::getCurrentOpen(),因?yàn)镠ouseOpen::getCurrentOpen()是要查詢DB計(jì)算的,這種代碼要盡可能少的被執(zhí)行到,減少DB查詢。
  • array_diff() 取差集的思路,獲得需要推送的人

封裝工具類

<?php
namespace App\Model\House;
.
.
.
class HouseLikeRecallUser
{
    protected $_userid = '';
    protected $_availableUser = [];
    protected $_recallFlagKey = '';

    const TYPE_TTL_HOUSE_LIKE_RECALL = 60 * 30; //半小時(shí)后可以再次接收到喜歡的xxx進(jìn)入通知
    const TYPE_TTL_HOUSE_LIKE_RECALL_FLAG = 60 * 60 * 8; //8小時(shí)重復(fù)登錄不觸發(fā)

    //初始化 傳入setRecalled 的過期時(shí)間
    public function __construct($userid)
    {
        $this->_userid = $userid;
        //登錄后給喜歡我的人推送校驗(yàn):同一場(chǎng)次重復(fù)登錄不重復(fù)發(fā)送
        $this->_recallFlagKey = CacheKey::getCacheKey(CacheKey::TYPE_HOUSE_LIKE_RECALL_FLAG, $this->_userid);
    }

    //設(shè)置當(dāng)前用戶推送標(biāo)示
    public function setRecalled()
    {
        Cache::put($this->_recallFlagKey, 1, self::TYPE_TTL_HOUSE_LIKE_RECALL_FLAG);
    }

    //獲取當(dāng)前用戶是否觸發(fā)推送
    public function canRecall()
    {
        $res = false;
        if (empty(Cache::get($this->_recallFlagKey))) {
            $houseOpen = HouseOpen::getCurrentOpen();
            if ($houseOpen['status'] == HouseOpen::HOUSE_STATUS_OPEN) {
                $res = true;
            }
        }
        return $res;
    }

    //獲取需要推送用戶
    public function getAvailableUser()
    {
        //獲得最近喜歡我的用戶
        $recentLikeMeUser = UserRelationSingle::getLikeMeUserIds($this->_userid, 100, Utility::getBeforeNDayTimestamp(7));

        //獲得最近喜歡我的用戶的 RECALL緩存標(biāo)記
        foreach ($recentLikeMeUser as $userid) {
            $batchKey[] = CacheKey::getCacheKey(CacheKey::TYPE_HOUSE_LIKE_RECALL, $userid);
        }

        //獲得最近喜歡我的且已經(jīng)推送過的用戶
        $cacheData = [];
        if (!empty($batchKey)) {
            $cacheData = Redis::connection('cache')->mget($batchKey);
        }

        //計(jì)算最近喜歡我的用戶 和 已經(jīng)推送過的用戶 的差集:就是需要推送的用戶
        $this->_availableUser = array_diff($recentLikeMeUser, $cacheData);
        return $this->_availableUser;
    }

    //更新已經(jīng)推送的用戶
    public function updateRecalledUser()
    {
        //批量更新差集用戶
        $recalledUser = [];
        foreach ($this->_availableUser as $userid) {
            $cacheKey = CacheKey::getCacheKey(CacheKey::TYPE_HOUSE_LIKE_RECALL, $userid);
            $recalledUser[$cacheKey] = $userid;
        }
        //批量更新 設(shè)置過期時(shí)間
        self::myPut($recalledUser, self::TYPE_TTL_HOUSE_LIKE_RECALL);
    }

    //批量設(shè)置過期時(shí)間
    public static function myPut(array $data, $ttl = 0)
    {
        if (empty($data)) {
            return false;
        }

        $pipeline = Redis::connection('cache')
            ->multi(\Redis::PIPELINE);
        foreach ($data as $key => $value) {
            if (empty($value)) {
                continue;
            }
            if ($ttl == 0) {
                $pipeline->set(trim($key), $value);
            } else {
                $pipeline->set(trim($key), $value, $ttl);
            }
        }
        $pipeline->exec();
    }
}

調(diào)用工具類

public function handle()
{
    $userid = $this->_userid;
    $houseLikeRecallUser = new HouseLikeRecallUser($userid);
    if ($houseLikeRecallUser->canRecall()) {
        $recallUserIds = $houseLikeRecallUser->getAvailableUser();
        $houseLikeRecallUser->setRecalled();
        $houseLikeRecallUser->updateRecalledUser();
        //群發(fā)推送消息
        .
        .
        .
    }
}

總結(jié)

不同量級(jí)的數(shù)據(jù)需要不同的處理辦法,減少網(wǎng)絡(luò)請(qǐng)求次數(shù),合理使用緩存,是性能優(yōu)化的必經(jīng)之路。

進(jìn)一步思考

如果我喜歡的1萬人同時(shí)上線(秒級(jí)并發(fā)),我只收到一個(gè)消息推送,要避免被通知轟炸,怎么解決這類并發(fā)問題呢?

到此這篇關(guān)于Redis 如何批量設(shè)置過期時(shí)間(PIPLINE的使用)的文章就介紹到這了,更多相關(guān)Redis 批量設(shè)置過期時(shí)間內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • RediSearch加RedisJSON大于Elasticsearch的搜索存儲(chǔ)引擎

    RediSearch加RedisJSON大于Elasticsearch的搜索存儲(chǔ)引擎

    這篇文章主要為大家介紹了RediSearch加RedisJSON大于Elasticsearch的王炸使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • RedisTemplate 實(shí)現(xiàn)基于Value 操作的簡(jiǎn)易鎖機(jī)制(示例代碼)

    RedisTemplate 實(shí)現(xiàn)基于Value 操作的簡(jiǎn)易鎖機(jī)制(示例代碼)

    本文將介紹如何使用 RedisTemplate 的 opsForValue().setIfAbsent() 方法來實(shí)現(xiàn)一種簡(jiǎn)單的鎖機(jī)制,并提供一個(gè)示例代碼,展示如何在 Java 應(yīng)用中利用這一機(jī)制來保護(hù)共享資源的訪問,感興趣的朋友跟隨小編一起看看吧
    2024-05-05
  • Linux下安裝Redis 6.0.5的實(shí)現(xiàn)

    Linux下安裝Redis 6.0.5的實(shí)現(xiàn)

    本文詳細(xì)介紹了在Linux系統(tǒng)下安裝Redis 6.0.5的步驟,包括安裝準(zhǔn)備、編譯安裝、啟動(dòng)服務(wù)、設(shè)置密碼和配置文件修改等,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-02-02
  • redis緩存的簡(jiǎn)單操作(get、put)

    redis緩存的簡(jiǎn)單操作(get、put)

    這篇文章主要介紹了redis緩存的簡(jiǎn)單操作,包括引入jedisjar包、配置redis、RedisDao需要的一些工具等,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-09-09
  • Redis中哈希分布不均勻的解決辦法

    Redis中哈希分布不均勻的解決辦法

    這篇文章主要介紹了Redis中哈希分布不均勻的解決辦法的相關(guān)資料,需要的朋友可以參考下
    2021-02-02
  • Redis報(bào)錯(cuò)UnrecognizedPropertyException: Unrecognized field問題

    Redis報(bào)錯(cuò)UnrecognizedPropertyException: Unrecognized 

    在使用SpringBoot訪問Redis時(shí),報(bào)錯(cuò)提示識(shí)別不了屬性headPart,經(jīng)過排查,發(fā)現(xiàn)并非Serializable或getset方法問題,而是存在一個(gè)方法getHeadPart,但無headPart屬性,解決方案是將getHeadPart改為makeHeadPart
    2024-10-10
  • springboot中操作redis實(shí)例分享

    springboot中操作redis實(shí)例分享

    本文介紹了如何在Spring?Boot應(yīng)用中整合Redis緩存技術(shù),包括配置Redis連接、定義Redis模板、實(shí)現(xiàn)Redis的基本操作以及使用Spring?Cache注解。這些內(nèi)容可幫助開發(fā)者快速掌握Spring?Boot與Redis的集成,并提高應(yīng)用性能。
    2023-06-06
  • Redis動(dòng)態(tài)熱點(diǎn)數(shù)據(jù)緩存策略設(shè)計(jì)

    Redis動(dòng)態(tài)熱點(diǎn)數(shù)據(jù)緩存策略設(shè)計(jì)

    本文主要介紹了Redis動(dòng)態(tài)熱點(diǎn)數(shù)據(jù)緩存策略設(shè)計(jì),包括熱點(diǎn)數(shù)據(jù)識(shí)別、動(dòng)態(tài)緩存、多級(jí)緩存、預(yù)加載機(jī)制、更新策略以及監(jiān)控告警等,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-01-01
  • 淺談Redis的事件驅(qū)動(dòng)模型

    淺談Redis的事件驅(qū)動(dòng)模型

    本文主要介紹了淺談Redis的事件驅(qū)動(dòng)模型,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • Redis關(guān)于內(nèi)存碎片的解決方法

    Redis關(guān)于內(nèi)存碎片的解決方法

    今天生產(chǎn)機(jī)報(bào)內(nèi)存爆滿異常被叫過去查看問題,通過各種排除最終定位到了Redis的內(nèi)存碎片的問題,這篇博客將詳細(xì)介紹Redis內(nèi)存碎片問題并給出最佳實(shí)踐解決此問題,需要的朋友可以參考下
    2024-07-07

最新評(píng)論