我有一个数据库中的项目列表,每个项目都有选项可以向下或向上投票。这些投票与其他项目字段一起存储在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();
});
用户可以每天投票/投票。当用户决定投票时,我将他的决定存储到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));
}
接下来,我想了解某些用户如何投票的信息。我在模型中创建了访问器:
public function getVoteAttribute($value)
{
$voteKey = sprintf('%s-%s', Request::ip(), $this->id);
return $this->attributes['vote'] = Cache::get($voteKey);
}
protected $appends = ['vote'];
这样做是否明智?或者长列表是否会出现性能问题?如果返回100个项目,则每个用户有100个与memcached的连接。如何改进这个或者这是我不应该担心的事情,因为缓存服务器可以毫无问题地处理这么多连接。
答案 0 :(得分:6)
当前使用缓存& DB 强>
在数据库中,您按# up-votes & down-votes
存储item
,但在缓存中,您需要存储type of vote
(向上/向下投票) )item
和IP address (or user id)
的组合。此外,缓存将在24小时后过期。
因此,当您说Cache::get($voteKey)
时,它将返回向上投票或向下投票,但前提是用户在过去24小时内对此项目进行了投票(否则返回null)。这是打算吗?
何时使用缓存v / s DB
通常,您会使用缓存进行频繁查询(当您需要经常执行特定的读取操作但不经常写入时)。如果不是这种情况,您通常会回退到DB。
现在让我们说你实际上想要同时存储# up-votes/down-votes by item
和type of vote by combination of user and item
。想想它一秒钟,哪个查询会更频繁? #up-votes / down-votes每个项目或投票类型的组合用户和&项目?当然,这将是第一个场景(如果有的话)。但是,你正在做相反的事情。
您将更频繁访问的查询存储在数据库中并且更少 经常访问缓存中的查询
这实际上会降低应用的整体性能!
什么是正确的方法?
嗯,这取决于用例。例如,我们假设您要按项目ID存储用户ID和投票类型(典型用例,因为您不希望任何用户的投票计数超过一次投票重铸的项目)。然后,我将把它存储在数据库中,并在缓存中按项目存储总的#up-votes / down-votes(仅当经常访问时 - 例如,您可以选择不存储所有项目的#potes)但仅限于具有至少X个视图的更受欢迎的项目)
对于上述用例,我建议这样的事情:
数据库架构
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();
});
投票控制器逻辑
$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);
原始问题
对于您的原始问题,Laravel使用单个连接实例进行Redis和Memcached的缓存查询。因此,如果同一请求获取100个不同的缓存项,则它不会启动100个连接 - 它将在单个缓存连接中完成工作