话说大家都是怎么维护查询缓存的

$data[‘top_project’] = Cache::remember(md5($request->route()->getName().’_top_project’),config(‘app.debug’) == true ? 100 : 864000,function(){
return Project::query()
->from(‘project as p’)
->where(‘p.is_del’,0)
->where(‘p.project_status’,2)
->orderBy(‘views’,’desc’)
->select([‘id’,’project_title’,’budget_upper_limit’])
->limit(10)
->get();
});
如上所示,对查询结果进行了缓存,大家都是怎么维护这个缓存的,我目前采用的方案是当数据有新增的时候删除这个缓存 key

《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
讨论数量: 9
sanders

为啥要给缓存键做哈希哪?虽然16的32次方概率很低但哈希还是会碰撞的。

2个月前 评论
yyy123456 2个月前
PHP布道者 (楼主) 2个月前

就是数据同步的问题嘛,无论是先更新数据库再更新缓存,或者先更新缓存再更新数据库都不可能保证100%的准确性,不过一般正常使用,不涉及到太多的数据量,基本都够了。

但是上述可能会存在问题,假如当你删除缓存数据的同时,用户刚好访问到了缓存数据,如果没做处理,那么就会报错。如果做了处理,没有就去数据库里拿并缓存起来,当大量请求的时候,所有的请求都会落到数据库,所以这里需要思考一下怎么处理。

还有,如同上一楼的朋友所说的,为啥缓存的键还要做哈希的问题。

2个月前 评论
PHP布道者 (楼主) 2个月前

laravel-model-caching

2个月前 评论
PHP布道者 (楼主) 2个月前

越多越难维护, 我是这么觉得,反正我没维护的多好

2个月前 评论

刚好前段时间从Google找到一个比较合适的缓存维护方案,根据我自身使用情况结合了一下,代码排版凑合看看吧

<?php

declare(strict_types=1);

namespace App\Support\Cache\V1;

use Illuminate\Support\Facades\Cache;
use Psr\SimpleCache\InvalidArgumentException;

abstract class CacheBuilder
{
    private string $key;
    private \Closure $data;
    protected int $ttl;
    private array $tags;

    public function __construct(string $key)
    {
        $this->key = $key;
    }

    public static function __callStatic($property, $arguments): self
    {
        $constant = self::getConstant($property);

        if (!$constant) {
            throw new \BadMethodCallException("Property {$property} not supported.");
        }
//        if ($constant instanceof \Closure) {
//            $key = $constant(...$arguments);
//        } else {
        $key = vsprintf($constant, $arguments);
//        }
        return new static($key);

    }

    private static function getConstant(string $property): ?string
    {
        $reflection = new \ReflectionClass(static::class);
        $constants = $reflection->getConstants();

        $matchedConstant = array_filter($constants, function ($constant, $name) use ($property) {
            $propertyName = mb_strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $property));
            return mb_strtolower($name) === $propertyName;
        }, ARRAY_FILTER_USE_BOTH);

        return current($matchedConstant);
    }

    public function getKey(): string
    {
        return $this->key;
    }

    public function setData($data): self
    {
        $this->data = $data;
        return $this;
    }

    public function getData(): \Closure
    {
        return $this->data;
    }

    public function setTtl(int $ttl): self
    {
        $this->ttl = $ttl;
        return $this;
    }

    public function setTags($tags): self
    {
        $this->tags = $tags;
        return $this;
    }

    /**
     * @throws InvalidArgumentException
     */
    public function get()
    {
        return Cache::store('redis')->get($this->key);
    }

    public function forget(): bool
    {
        return Cache::store('redis')->forget($this->key);
    }

    public function forever(): bool
    {
        return $this->performCacheOperation('forever');
    }

    public function remember()
    {
        return $this->performCacheOperation('remember', [$this->ttl, $this->data]);
    }

    public function put(): bool
    {
        return $this->performCacheOperation('put', [$this->ttl]);
    }

    /**
     * @return bool
     */
    public function flush(): bool
    {
        $cache = Cache::store('redis');
        if (empty($this->tags) || !$cache->supportsTags()) {
            throw new \BadMethodCallException("method: tags() not supported or tags cant be null");
        }
        return $cache->tags($this->tags)->flush();
    }

    protected function performCacheOperation(string $method, array $additionalArgs = [])
    {
        $cache = Cache::store('redis');

        if ($cache->supportsTags() && !empty($this->tags)) {
            $cache = $cache->tags($this->tags);
        }

        return $cache->$method($this->key, ...$additionalArgs);
    }
}

每一个缓存类继承CacheBuilder

<?php

declare(strict_types=1);

namespace App\Support\Cache\V1;

/**
 * @method static Domains()
 * @method static SiteCache Domain(string $domain)
 * @method static SiteCache Attributes(string $site_id, string $attribute_name)
 * @method static SiteCache ViewPage(string $site_machine_name, string $slug, string $language)
 */
class SiteCache extends CacheBuilder
{
    protected int $ttl = 60;


    public const DOMAINS = 'site_domains';
    public const DOMAIN = 'site_domain:%s';
    public const ATTRIBUTES = 'site:%s_%s';
    public const VIEW_PAGE = "view_page:%s:%s:%s";
}
<?php

declare(strict_types=1);

namespace App\Support\Cache\V1;

/**
 * @method static SiteCache allSuppliers(string $companyId)
 */
class SupplierCache extends CacheBuilder
{
    protected int $ttl = 60 * 10 * 60;

    public const ALL_SUPPLIERS = 'all_suppliers:%s';

    public const TAG = [
        'all_supplier'
    ];




}

试用

        $companyId = '1';
        $value = SupplierCache::allSuppliers($companyId)
            ->setData(function (){
                return [
                  'name'=>'tom'  
                ];
            })->remember();
2个月前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!