2017-03-09 18 views
7

मेरे पास डेटाबेस में आइटम की एक सूची है और प्रत्येक आइटम के पास मतदान या नीचे जाने का विकल्प होता है। उन वोटों को अन्य आइटम फ़ील्ड के साथ 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 आइटम लौटाए जाते हैं, तो प्रति उपयोगकर्ता memcached के लिए 100 कनेक्शन हैं। मैं इसे कैसे सुधार सकता हूं या ऐसा कुछ है जिसके बारे में मुझे चिंता नहीं करना चाहिए क्योंकि कैश सर्वर इस समस्या के कनेक्शन को बिना किसी समस्या के संभाल सकता है।

उत्तर

6

कैश & डीबी के वर्तमान का उपयोग

  1. आप आईपी पते का उपयोग कर रहे user_id के रूप में सरल v/s कुछ उपयोगकर्ताओं की पहचान करने के लिए। क्या यह जानबूझकर है? यदि एक ही उपयोगकर्ता दूसरे आईपी से फिर से लॉग इन करता है, तो क्या आप एक अलग नंबर दिखाना चाहते हैं?
  2. डीबी में, आप item प्रति # up-votes & down-votes भंडारण कर रहे हैं लेकिन कैश में आप type of vote (ऊपर वोट/नीचे वोट) भंडारण कर रहे हैं item और IP address (or user id) के संयोजन से। इसके अलावा, कैश 24 घंटों के बाद समाप्त हो जाता है।

    तो, जब आप Cache::get($voteKey) कहते हैं तो यह या तो ऊपर वोट या डाउन-वोट लौटाएगा, लेकिन केवल तभी जब उपयोगकर्ता ने पिछले 24 घंटों में इस आइटम पर मतदान किया था (अन्यथा शून्य वापस आता है)। क्या इसका इरादा है?

जब कैश v/s डीबी

उपयोग करने के लिए आमतौर पर आप लगातार प्रश्नों के लिए कैश का प्रयोग करेंगे (जब आप अक्सर एक विशेष पढ़ने सेशन प्रदर्शन लेकिन जैसा कि अक्सर नहीं लिखने की ज़रूरत)। यदि यह मामला नहीं है, तो आप आम तौर पर डीबी में फॉलबैक करेंगे।

अब मान लें कि आप वास्तव में # up-votes/down-votes by item और type of vote by combination of user and item दोनों को स्टोर करना चाहते थे। इसके बारे में एक सेकंड के लिए सोचें, कौन सी क्वेरी अधिक बार होगी? उपयोगकर्ता & आइटम के संयोजन द्वारा प्रति आइटम या वोट के प्रकार के ऊपर # वोट-वोट/डाउन-वोट? बेशक, यह पहला परिदृश्य होगा (अगर बिल्कुल)। हालांकि, आप काफी विपरीत कर रहे हैं।

आप कैश

इस में डीबी में अधिक बार पहुँचा क्वेरी और कम अक्सर पहुँचा क्वेरी भंडारण कर रहे हैं वास्तव में अपने अनुप्रयोग के समग्र प्रदर्शन कम हो जाएगा!

सही तरीका क्या होगा?

अच्छा, यह उपयोग के मामले पर निर्भर करता है। उदाहरण के लिए, मान लीजिए कि आप उपयोगकर्ता आईडी और आइटम आईडी द्वारा सामान्य प्रकार के वोट को स्टोर करना चाहते हैं (सामान्य उपयोग केस क्योंकि आप नहीं चाहते हैं कि किसी भी उपयोगकर्ता के वोट को वोट रिकॉस्ट पर प्रति आइटम एक से अधिक बार गिना जाए)। फिर, मैं इसे डीबी में संग्रहीत करने और कैश में आइटम द्वारा कुल # अप-वोट/डाउन-वोट संग्रहीत करने के बारे में जाऊंगा (केवल अगर अक्सर एक्सेस किया जाता है - तो उदाहरण के लिए, आप सभी वस्तुओं के लिए # वोट स्टोर नहीं करना चुन सकते हैं

डीबी स्कीमा

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 कनेक्शन शुरू नहीं करेगा - यह एक कैश कनेक्शन में काम करेगा

संबंधित मुद्दे