laravel 避免重复从缓存重新加载的最佳方法?

o3imoua4  于 2022-12-19  发布在  其他
关注(0)|答案(3)|浏览(129)

假设我们有一个Class的方法被调用了迭代n次,并且这个方法本身有一条语句从一个cache系统-- Redis中提取data
现在,如果这个方法被调用 n 次该高速缓存也会被命中 n 次,导致连续获取反序列化相同的数据 *n次 *,这在像PHP这样的解释器的情况下会消耗大量的时间和CPU。
将缓存的数据传递给这个方法也可以是no,因为我们可能示例化这个类的n个示例。
那么,如果我们可以使用Object的静态属性来保存值,是否有一种方法可以避免在类/对象的上下文中多次命中该高速缓存?

ppcbkaq5

ppcbkaq51#

首先,编写一个服务类:

  • 提供吸气剂,该吸气剂:
  • 从缓存加载所需值(基于唯一键),
  • 而且备份加载值,
  • 最后,返回backuped-value,而不是从缓存中重新加载。
  • 提供更新备份和缓存的setter。

然后简单地使用Laravel的特性来注入和/或获取所述服务类的示例。
(我写和/或说"backupped"而不是"backed up",因为字典是错的,如证明:

  • "备份蛋糕"仍然是它的意思
  • 而"备份蛋糕"则令人困惑。)

示例

<?php

namespace App\Services;

use Illuminate\Support\Facades\Cache;

class MyCacheService
{
    protected $backupMap = [];

    /**
     * Requests an instance of this-class from Laravel. 
     *
     * @return MyCacheService|null
     */
    public static function instance()
    {
        return \Illuminate\Support\Facades\App::make(MyCacheService::class);
    }

    public function get($key)
    {
        $backup = & $this->backupMap[$key];
        if ( ! isset($backup)) {
            $backup = $this->rawGet($key);
        }
        return $buckup;
    }

    public function set($key, $value)
    {
        $this->rawSet($key, $value);
        $this->backupMap[$key] = $value;
    }

    /** Loads from cache */
    private function rawGet($key)
    {
        // ... your normal loading from cache logic goes here,
        // but as sub-example:

        return Cache::get($key);
    }

    /** Saves into cache */
    private function rawSet($key, $value)
    {
        // ... your normal saving into cache logic goes here,
        // but as sub-example:
        Cache::set($key, $value);
    }
}

用法:

use App\Services\MyCacheService;
use Illuminate\Support\Facades\App;

// ...

// Get instance once, like:
$cacheService = MyCacheService::instance();

// Or like:
/** @var MyCacheService|null $cacheService */
$cacheService = App::make(MyCacheService::class);

// Finally, reuse as many times as required, like:
$myValue = $cacheService->get('my-unique-key');

$myOtherValue = $cacheService->get('my-other-key');
    • 注意**Laravel为我们存储了类的示例,否则可以使用名为$instanceprivate static属性,以及来自instance()方法的return属性。
    • 警告:**正如您可能已经知道的,可能需要替换rawGet和rawSet的逻辑。

此外,将MyCacheService.php文件(其源代码如上所示)放在app/Services文件夹中。

brccelvz

brccelvz2#

如果您认为不应该使用服务类(另一个答案对此进行了解释),
然后考虑使用PHP的$GLOBALS变量来备份加载的缓存(而不是添加另一个定制的static变量)。

示例

也许备份一次即可:

在Laravel的AppServiceProvider.php文件中,执行如下操作:

<?php

namespace App\Providers;

// ...

use Illuminate\Support\Facades\Cache;

class AppServiceProvider extends ServiceProvider
{

    // ...

    public function boot()
    {
        $keyList = [
            'my-unique-key',
            'my-other-key',
        ];

        foreach($keyList as $key) {
            $GLOBALS['cache-' . $key] = Cache::get($key);
        }
    }
}

最后,在任何需要的地方使用$GLOBALS['cache-my-unique-key']

或者,每个类的备份:

<?php

use Illuminate\Support\Facades\Cache;

class YourClass {
    private $myData;

    public function __construct()
    {
        $key = 'my-unique-key';

        $value = & $GLOBALS['cache-' . $key];
        if ( ! isset($value)) {
            $value = Cache::get($key);
        }

        $this->myData = $value;
    }

    // Finally, use `$this->myData` anywhere in this same class.
}

注意您可能已经知道,在这两种情况下,我们都使用'cache-'前缀来避免错误地覆盖任何内容。

lztngnrs

lztngnrs3#

您可以使用静态属性来存储缓存数据,并使用相同的方法访问它.

class CacheClass
{
    private static $cachedData;

    public function retrieveData()
    {
        if (!isset(self::$cachedData)) {
            // re-assign the value
            self::$cachedData = fetchDataFromCache();
        }
        
        return self::$cachedData;
    }
}

相关问题