2017-03-09 18 views
7

我有一個數據庫中的項目列表,每個項目都有選項被選中。這些選票與其他項目字段一起存儲在MySql中。例如這樣的東西:從緩存中提取Laravel模型訪問器 - 性能增強

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的連接。我該如何改善這一點,或者這是我不應該擔心的事情,因爲緩存服務器可以毫無問題地處理這種連接數量。

回答

6

當前緩存& DB的使用

  1. 您使用IP地址來識別用戶V/S的東西作爲USER_ID一樣簡單。這是故意的嗎?如果同一用戶從另一個IP再次登錄,您是否想要顯示不同的號碼?
  2. 在DB,你存儲# up-votes & down-votesitem但在緩存中,你要按照itemIP address (or user id)組合,存儲type of vote(贊成票/反對票)。此外,緩存在24小時後過期。

    因此,當您說Cache::get($voteKey)時,它將返回加票或減票,但只有當用戶在過去24小時內對該項投票(否則返回空)時纔會返回。這是打算嗎?

當使用緩存V/S DB

通常你會使用緩存頻繁的查詢(當你需要頻繁執行特定讀運算,但寫不頻繁)。如果不是這種情況,你通常會回退到DB。

現在讓我們假設你實際上想存儲# up-votes/down-votes by itemtype of vote by combination of user and item。想一想,哪個查詢會更頻繁? #用戶&項目組合的每個項目或投票類型的最多/最低票數?當然,這將是第一種情況(如果有的話)。但是,你做的恰恰相反。

你存儲在數據庫和更頻繁訪問的查詢少 經常訪問的查詢緩存

這實際上減少了您的應用程序的整體性能!

什麼是正確的方法?

那麼,這取決於用例。例如,假設您希望通過商品ID存儲用戶ID和投票類型(典型用例,因爲您不希望每個用戶的投票在投票中重複計算多次)。然後,我會將這些數據存儲在數據庫中,並按緩存項的順序存儲總計#票增加/減票數(僅當頻繁訪問時 - 例如,您可以選擇不存儲所有項目的#票但只適用於更受歡迎的項目有意見至少X號)

對於上述使用的情況下,我建議是這樣的:

DB模式

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使用單一連接實例兩個RedisMemcached緩存查詢。因此,如果相同的請求獲取100個不同的緩存項目,它將不會啓動100個連接 - 它會在單個緩存連接中執行作業