高并发情况下防止缓存穿透的代码实现

场景:

高并发情况下,缓存失效瞬间,大量请求落到db情况下,会造成雪崩效应,如何解决?

思路:

设置一个长时间的缓存时间,再设置一个短时间的刷新缓存时间,如果到了刷新缓存的时间,则在redis中加一个原子锁,查询db数据,设置缓存,并返回数据。

    /**
     * 防止缓存穿透解决方法
     *
     * @param string $cacheKey
     * @param int $expireTime 过期时间
     * @param int $refreshTime 刷新缓存时间
     * @param \Closure $callback 查询db回调
     * @return array|mixed
     */
    function refresh_cache(string $cacheKey, int $expireTime, int $refreshTime, \Closure $callback):array 
    {

        $lock = $cacheKey. ':lock'; //缓存锁的key
        $ttl = Reids::ttl($cacheKey); //以秒为单位返回 key 的剩余过期时间
        $swooleResponse = new Swoole\Http\Response();

        //如果存在key
        if ($ttl > 0) {

            $cacheData = Reids::get($cacheKey);
            $data = $cacheData ? json_decode($cacheData, true) : [];

            $diffTime = bcsub($expireTime, $ttl);

            /** 如果缓存过去的时间,在刷新的时间内,返回缓存数据 */
            if ($diffTime < $refreshTime) {
                $swooleResponse->header('X-Cache-Ttl', $ttl); //或 \header('X-Cache-Ttl: xx');
                return $data;
            }

            /** 设置redis原子锁, 如果100个用户同时访问,只会一个用户执行  */
            if (Redis::set($lock, 'locked', 'nx', 'ex', 3)) {
                //执行回调函数,查询db,并设置缓存
                $data = $callback();
                Redis::set($cacheKey, json_encode($data, JSON_UNESCAPED_UNICODE), $expireTime);
                $swooleResponse->header('X-Cache-Ttl', 'Void');
                return $data;
            }

            $swooleResponse->header('X-Cache-Ttl', $ttl);
            return $data;
        }

        //缓存不存在,执行回调函数,查询db,并设置缓存
        $data = $callback();
        Redis::set($cacheKey, json_encode($data, JSON_UNESCAPED_UNICODE), $expireTime);
        $swooleResponse->header('X-Cache-Ttl', 'None');
        return $data;
    }
  • 如何使用:
    //例如:获取用户列表,设置1小时缓存,如果缓存过去大于30s, 则查询一次db
    $callback = function () {
            return $db->query("SELECT * FROM `user` LIMIT 10")->get();
    };
    return refresh_cache('user:list:cache:key', 3600, 30, $callback);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容