Laravel模型访问器从缓存中获取-性能增强 [英] Laravel model accessor fetching from cache - performance enhancements

查看:244
本文介绍了Laravel模型访问器从缓存中获取-性能增强的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a list of items in database and each item has option to be voted down or up. Those votes are stored in MySql along with other item fields. For example someting like this:

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).

User can vote down/up every day. When user decides to vote I store his decision to memcached for one day and increase one of the fields (up_votes or down_votes) accordingly.

$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));
}

下一步,我想获得有关某些用户投票方式的信息.我在模型中创建了访问器:

Next I want to have information about how certain user voted. I created accessor in model:

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的连接.我该如何改善呢?还是我不应该担心这个问题,因为缓存服务器可以毫无问题地处理这种数量的连接.

Is this smart to do or could there be some performance issues with long lists? If 100 items are returned, there are 100 connections to memcached per user. How can I improve this or is this something I should not much worry about because cache server can handle this amount of connections with no problem.

推荐答案

缓存的当前使用情况&数据库

  1. 您正在使用 IP地址来识别用户,而这些用户的身份很简单,例如 user_id .这是故意的吗?如果同一用户再次从另一个IP登录,您想显示一个不同的数字吗?
  2. 在数据库中,每个item存储# up-votes & down-votes,但在缓存中,通过itemtype of vote(上投票/下投票) >.另外,缓存会在24小时后过期.

  1. You're using IP address to identify users v/s something as simple as user_id. Is this intentional? If the same user logs in again from another IP, would you want to show a different number?
  2. In the DB, you're storing # up-votes & down-votes per item but in the cache you're storing type of vote (up-vote/down-vote) by combination of item and IP address (or user id). Also, the cache expires after 24 hours.

因此,当您说Cache::get($voteKey)时,它将返回上投票或下投票,但前提是用户在最近24小时内对此项目进行了投票(否则返回null).这是故意的吗?

So, when you say Cache::get($voteKey) it will return either up-vote or down-vote but only if the user voted on this item in the last 24 hours (otherwise returns null). Is that intended?

何时使用Cache v/s DB

通常,您将对频繁查询使用高速缓存(当您需要频繁执行特定的读取操作,但不那么频繁地执行写入操作时).如果不是这种情况,通常会退回到数据库.

Typically you would use cache for frequent queries (when you need to perform a particular read op frequently but write not as frequently). If this isn't the case, you would generally fallback to DB.

现在,假设您实际上想同时存储# up-votes/down-votes by itemtype of vote by combination of user and item.想一想,哪个查询会更频繁?根据用户和用户的组合,对每个项目或投票类型进行#次上/下投票物品?当然,这将是第一种情况(如果有的话).但是,您所做的恰恰相反.

Now let's say you actually wanted to store both # up-votes/down-votes by item and type of vote by combination of user and item. Think about it for a second, which query would be more frequent? # up-votes / down-votes per item or type of vote by combination of user & item? Of course, it would be the first scenario (if at all). However, you're doing quite the reverse.

您正在数据库中存储访问频率较高的查询,而在数据库中存储的查询较少 缓存中经常访问的查询

You're storing the more frequently accessed query in DB and the less frequently accessed query in cache

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

This will actually reduce the overall performance of your app!

什么是正确的方法?

嗯,这取决于用例.例如,假设您要同时存储用户ID和按项目ID进行的投票类型(典型的用例,因为您不希望在重投投票的每个项目中对任何用户的投票进行一次以上的计数).然后,我将把它存储在数据库中,并按高速缓存将每个项目的#个上/下投票总数存储(仅在频繁访问的情况下-例如,您可以选择不存储所有项目的#票)但仅适用于观看次数至少为X的较热门商品)

Well, that depends on the use case. For instance, let's say you want to store both the user id and type of vote by item id (typical use case because you wouldn't want any user's vote to be counted more than once per item on a vote recast). Then, I would go about storing this in the DB and storing the total # up-votes/down-votes by item in the cache (only if frequently accessed - so for instance, you may choose not to store the # votes for all items but only for the more popular items with at least X number of views)

对于上述用例,我建议如下:

For the above use case, I would suggest something like this:

数据库架构

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对 Memcached .因此,如果同一请求获取100个不同的缓存项,则不会启动100个连接-它将在单个缓存连接中完成工作

As to your original question, Laravel uses a single connection instance for cache queries for both Redis and Memcached. So, if the same request fetches 100 different cache items, it would not initiate 100 connections - it would do the job in a single cache connection

这篇关于Laravel模型访问器从缓存中获取-性能增强的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆