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() 取差集的思路,获得需要推送的人
封装工具类
<?phpnamespace App\Model\House;...class HouseLikeRecallUser{ protected $_userid = ''; protected $_availableUser = []; protected $_recallFlagKey = ''; const TYPE_TTL_HOUSE_LIKE_RECALL = 60 * 30; //半小时后可以再次接收到喜欢的xxx进入通知 const TYPE_TTL_HOUSE_LIKE_RECALL_FLAG = 60 * 60 * 8; //8小时重复登录不触发 //初始化 传入setRecalled 的过期时间 public function __construct($userid) { $this->_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怎么批量设置过期时间”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341