千家信息网

Redis怎么批量设置过期时间

发表于:2025-01-18 作者:千家信息网编辑
千家信息网最后更新 2025年01月18日,这篇文章将为大家详细讲解有关Redis怎么批量设置过期时间,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。Redis如何批量设置过期时间呢?不要说在foreach中通
千家信息网最后更新 2025年01月18日Redis怎么批量设置过期时间

这篇文章将为大家详细讲解有关Redis怎么批量设置过期时间,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

Redis如何批量设置过期时间呢?

不要说在foreach中通过set()函数批量设置过期时间

我们引入redis的PIPLINE,来解决批量设置过期时间的问题。

PIPLINE的原理是什么?

未使用pipline执行N条命令

使用pipline执行N条命令

通过图例可以很明显的看出来PIPLINE的原理:

客户端通过PIPLINE拼接子命令,只需要发送一次请求,在redis收到PIPLINE命令后,处理PIPLINE组成的命令块,减少了网络请求响应次数。

网络延迟越大PIPLINE的优势越能体现出来

拼接的子命令条数越多使用PIPLINE的优势越能体现出来

注意:并不是拼接的子命令越多越好,N值也有是上限的,当拼接命令过长时会导致客户端等待很长时间,造成网络堵塞;我们可以根据实际情况,把大批量命令拆分成几个PIPLINE执行。

代码封装

//批量设置过期时间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();}

项目实战

需求描述

  • 打开APP,给喜欢我的人发送我的上线通知(为了避免打扰,8小时内重复登录不触发通知)

  • 每个人每半小时只会收到一次这类上线通知(即半小时内就算我喜欢的1万人都上线了,我也只收到一次喜欢的人上线通知)

要点分析

  • 合理使用缓存,减少DB读写次数

  • 不仅要减少DB读写次数,也要减少Redis的读写次数,使用PIPLINE

代码实现解析

  • canRecall() 写的比较优雅,先判断是否已发送的标记,再判断HouseOpen::getCurrentOpen(),因为HouseOpen::getCurrentOpen()是要查询DB计算的,这种代码要尽可能少的被执行到,减少DB查询。

  • array_diff() 取差集的思路,获得需要推送的人

封装工具类

_userid = $userid;        //登录后给喜欢我的人推送校验:同一场次重复登录不重复发送        $this->_recallFlagKey = CacheKey::getCacheKey(CacheKey::TYPE_HOUSE_LIKE_RECALL_FLAG, $this->_userid);    }    //设置当前用户推送标示    public function setRecalled()    {        Cache::put($this->_recallFlagKey, 1, self::TYPE_TTL_HOUSE_LIKE_RECALL_FLAG);    }    //获取当前用户是否触发推送    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缓存标记        foreach ($recentLikeMeUser as $userid) {            $batchKey[] = CacheKey::getCacheKey(CacheKey::TYPE_HOUSE_LIKE_RECALL, $userid);        }        //获得最近喜欢我的且已经推送过的用户        $cacheData = [];        if (!empty($batchKey)) {            $cacheData = Redis::connection('cache')->mget($batchKey);        }        //计算最近喜欢我的用户 和 已经推送过的用户 的差集:就是需要推送的用户        $this->_availableUser = array_diff($recentLikeMeUser, $cacheData);        return $this->_availableUser;    }    //更新已经推送的用户    public function updateRecalledUser()    {        //批量更新差集用户        $recalledUser = [];        foreach ($this->_availableUser as $userid) {            $cacheKey = CacheKey::getCacheKey(CacheKey::TYPE_HOUSE_LIKE_RECALL, $userid);            $recalledUser[$cacheKey] = $userid;        }        //批量更新 设置过期时间        self::myPut($recalledUser, self::TYPE_TTL_HOUSE_LIKE_RECALL);    }    //批量设置过期时间    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();    }}

调用工具类

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

关于"Redis怎么批量设置过期时间"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

0