Как лучше всего загружать и обновлять данные с помощью Redis и MySQL? - PullRequest
1 голос
/ 26 мая 2020

Я использую Redis в качестве слоя кеширования и хотел бы знать, что лучше всего использовать вместе с DB (в данном случае MySQL).

Здесь у меня есть пример функции панели управления пользователя:

public function updateDashboardUser(Request $request) {

        $user = app('redis')->hGetAll($request->userID); //Get data from cache

        if ($user) { //if there is data use this

            $id = $user['id'];
            $name = $user['name'];

        } else { //otherwise use this
            $user = User::select('id', 'name')->where('id', '=', $request->userID)->first();

            $id = $user->id;
            $name = $user->name;

        }

        return response()->json(['id' => $id, 'name' => $name], 200);

    }

Однако этот оператор else никогда не достигается, хотя $user из кеша может быть пустым. Есть ли лучший способ сделать это?

Также при обновлении ... Есть ли лучший способ автоматически обновлять оба (кеш и БД) при изменении данных в одном из них.

public function editDashboard(Request $request) {
        $user = Route::find($request->userID);

        $user->name = $request->name;
        $user->save();

        $cacheEdit = app('redis')->hSet($user->id, 'name', $request->name);

        return response()->json(['status' => '200'], 200);
    }

На данный момент я делаю это так, но иногда может быть изменен только один из них, а затем данные кеша (или, наоборот, данные БД) не синхронизируются / не обновляются.

Это мой первый опыт с Redis и кешированием в целом, поэтому приветствуется любая помощь.

1 Ответ

0 голосов
/ 26 мая 2020
  • Вместо прямого использования Redis API, вы должны использовать Laravel API кеша, он допускает некоторую абстракцию, и вам даже не нужно знать, какой из них является базовым кешем.

  • Используя Eloquent вместо построителя запросов, вы можете разблокировать некоторые очень мощные функции, такие как события модели. Например, в вашей модели User:

protected static function booted()
{
    parent::booted();

    $cache = app('cache');

    static::updated(function ($user) use ($cache) {
        $cacheKey = $user->getCacheKey();
        if ($cache->has($cacheKey) {
            $cache->put($cacheKey, $user, 30); //30 is the life duration of this value in cache, you're free to change it
        }
    });

    static::deleted(function ($user) use ($cache) {
        $cache->forget($user->getCacheKey());
    });
}

public function getCacheKey()
{
    return 'users.' . $this->getKey();
}

Эти «ловушки событий» автоматически вызываются Laravel всякий раз, когда вы обновляете или удаляете User с помощью Eloquent.

Это позволяет вам бегло делать это:

use App\User;
use Illuminate\Http\Request;
use Illuminate\Contracts\Routing\ResponseFactory;
use Illuminate\Contracts\Cache\Repository as Cache;

public function updateDashboardUser(Request $request, Cache $cache, ResponseFactory $responseFactory)
{
    $id = $request->userID;

    $user = $cache->remember('users.' . $id, 30, function () use ($id) {
        return User::findOrFail($id);
    });

    return $responseFactory->json($user->only(['id', 'name']), 200);
}

Например, как указано здесь https://laravel.com/docs/7.x/cache#retrieving -items-from-the-cache , вы можете использовать remember (или rememberForever), чтобы получить что-то из кеша и автоматически вернуться к закрытию, если не найдено. Затем findOrFail извлечет его из базы данных и в конечном итоге выдаст Illuminate\Database\Eloquent\ModelNotFoundException, потому что в этом случае нет смысла отправлять успешный ответ. Я также заменил ваших помощников, таких как response, с помощью внедрения зависимостей в контрактах (Laravel интерфейсы), что является наиболее чистой практикой.

https://laravel.com/docs/7.x/contracts

...