Laravel模型访问器从缓存中获取 - 性能增强

izu*_*pet 6 php mysql caching laravel eloquent

我有一个数据库中的项目列表,每个项目都可以选择向下或向上投票.这些投票与其他项目字段一起存储在MySql中.例如,像这样:

Schema::create('items', function ($table) {
    $table->increments('id');
    $table->text('message');
    $table->integer('up_votes')->unsigned()->default(0);
    $table->integer('down_votes')->unsigned()->default(0);
    $table->timestamps();
});
Run Code Online (Sandbox Code Playgroud)

用户可以每天投票/投票.当用户决定投票时,我将他的决定存储到memcached一天,并相应地增加其中一个字段(up_votes或down_votes).

$voteKey = sprintf('%s-%s', $request->ip(), $item->id);

if (!Cache::has($voteKey)) {
    $vote = $request->get('vote');

    $this->item->increment($vote ? 'up_votes' : 'down_votes');
    Cache::put($voteKey, $vote, (60*24));
}
Run Code Online (Sandbox Code Playgroud)

接下来我想了解某些用户如何投票的信息.我在模型中创建了访问器:

public function getVoteAttribute($value)
{
    $voteKey = sprintf('%s-%s', Request::ip(), $this->id);

    return $this->attributes['vote'] = Cache::get($voteKey);
}

protected $appends = ['vote'];
Run Code Online (Sandbox Code Playgroud)

这样做是否明智?或者长列表会出现性能问题?如果返回100个项目,则每个用户有100个与memcached的连接.我怎样才能改进这一点,或者这是我不应该担心的事情,因为缓存服务器可以毫无问题地处理这么多连接.

Par*_*ras 6

当前使用缓存和数据库

  1. 您使用IP地址来识别用户v/s,就像user_id一样简单.这是故意的吗?如果同一用户再次从另一个IP登录,您是否要显示不同的号码?
  2. 在DB,你存储# up-votes & down-votes每个item但在高速缓存中你存储type of vote(赞成票/反对票)的组合itemIP address (or user id).此外,缓存在24小时后过期.

    所以,当你说Cache::get($voteKey)它将返回向上投票或向下投票时,但仅在用户在过去24小时内对此项目进行投票时(否则返回null).这是有意的吗?

何时使用Cache v/s DB

通常,您会使用缓存进行频繁查询(当您需要经常执行特定的读操作但不经常写时).如果不是这种情况,通常会回退到DB.

现在让我们说你真的想存储两者# up-votes/down-votes by itemtype of vote by combination of user and item.想想它一秒钟,哪个查询会更频繁?#up-votes/down-votes每个项目或投票类型的用户和项目的组合?当然,这将是第一个场景(如果有的话).但是,你正在做相反的事情.

您在DB中存储更频繁访问的查询,在缓存中存储频率较低的查询

这实际上会降低您应用的整体性能!

什么是正确的方法?

那么,这取决于用例.例如,假设您希望按项目ID存储用户ID和投票类型(典型用例,因为您不希望任何用户的投票在投票重铸时每个项目被计算多次).然后,我将把它存储在数据库中,并在缓存中按项目存储总的#up-votes/down-votes(仅当经常访问时 - 例如,您可以选择不存储所有项目的#potes)但仅限于具有至少X个视图的更受欢迎的项目)

对于上面的用例,我建议这样的事情:

DB Schema

Schema::create('item_user', function ($table) {
    $table->increments('id');
    $table->integer('user_id')->unsigned();
    $table->integer('item_id')->unsigned();
    $table->enum('vote_type', ['up_vote', 'down_vote']);
    $table->unique(['user_id', 'item_id']);
    $table->timestamps();
});
Run Code Online (Sandbox Code Playgroud)

投票控制器逻辑

$user = Auth::user();
$vote = $request->get('vote');
$voteType = $vote ? 'up_vote' : 'down_vote';
$voteKey = "{$voteType}_{$item->id}";

$item->users()->updateExistingPivot($user->id, ['vote_type' => $voteType]);
Cache::increment($voteKey);
Run Code Online (Sandbox Code Playgroud)

原始问题

至于您的原始问题,Laravel使用单个连接实例进行RedisMemcached的缓存查询.因此,如果同一请求获取100个不同的缓存项,它将不会启动100个连接 - 它将在单个缓存连接中完成工作