2009-06-23 8 views
10

मान लें कि आपके पास पृष्ठ का एक टुकड़ा है जो सबसे हालिया पोस्ट प्रदर्शित करता है, और आप इसे 30 मिनट में समाप्त कर देते हैं। मैं यहाँ रेल का उपयोग कर रहा हूँ।memcached और Rails के लिए खंड और ऑब्जेक्ट कैशिंग को गठबंधन करने का सबसे अच्छा तरीका

<% cache("recent_posts", :expires_in => 30.minutes) do %> 
    ... 
<% end %> 

जाहिर है आप अगर टुकड़ा मौजूद सबसे हाल की पोस्ट प्राप्त करने के लिए डेटाबेस देखने क्या करने की जरूरत नहीं है, इसलिए तुम भी है कि भूमि के ऊपर से बचने के लिए सक्षम होना चाहिए।

नियंत्रक में कुछ इस तरह जो काम करने के लिए लगता है क्या मैं अब कर रहा हूँ है:

unless Rails.cache.exist? "views/recent_posts" 
    @posts = Post.find(:all, :limit=>20, :order=>"updated_at DESC") 
end 

यह सबसे अच्छा तरीका है? क्या ये सुरक्षित है?

एक बात मुझे समझ नहीं आता क्यों कुंजी "recent_posts" टुकड़ा के लिए है और "views/recent_posts" जब बाद में जाँच, लेकिन मैं memcached -vv देख यह क्या उपयोग कर रहा था देखने के लिए करने के बाद इस के साथ आया है। साथ ही, मुझे मैन्युअल रूप से "recent_posts" दर्ज करने के डुप्लिकेशंस को पसंद नहीं है, यह एक ही स्थान पर रखना बेहतर होगा।

विचार?

उत्तर

12

इवान वीवर के Interlock Plugin इस समस्या का हल।

यदि आप अलग-अलग व्यवहार की आवश्यकता है, जैसे कि अधिक बढ़िया अनाज नियंत्रण की आवश्यकता है तो आप इसे आसानी से कुछ भी कार्यान्वित कर सकते हैं। मूल विचार का मानना ​​है कि डेटा की आवश्यकता है एक ब्लॉक है कि केवल वास्तव में मार डाला में अपने नियंत्रक कोड रैप करने के लिए है:

# in FooController#show 
@foo_finder = lambda{ Foo.find_slow_stuff } 

# in foo/show.html.erb 
cache 'foo_slow_stuff' do 
    @foo_finder.call.each do 
    ... 
    end 
end 

आप माणिक मेटा प्रोग्रामिंग की मूल बातें यह काफी आसान इस लपेट के लिए है के साथ परिचित हैं, तो अपने स्वाद के एक क्लीनर एपीआई में।

यह ध्यान में रखते हुए सीधे खोजक कोड डालने से बेहतर है:

  • खोजक कोड जहां डेवलपर्स सम्मेलन
  • से यह उम्मीद रहती है दृश्य मॉडल का नाम/विधि से अनभिज्ञ है, और अधिक देखने के लिए अनुमति देता रहता है पुन: उपयोग

मुझे लगता है कि cache_fu में इसके किसी संस्करण/कांटे में समान कार्यक्षमता हो सकती है, लेकिन विशेष रूप से याद नहीं किया जा सकता है।

मेमकैड से प्राप्त लाभ सीधे आपके कैश हिट दर से संबंधित है। सावधानी बरतें कि आपकी कैश क्षमता बर्बाद न करें और एक ही सामग्री को कई बार कैश करके अनावश्यक यादें करें।उदाहरण के लिए, रिकॉर्ड ऑब्जेक्ट्स के साथ-साथ उनके HTML खंड को एक ही समय में कैश न करें। आम तौर पर खंड कैशिंग सर्वश्रेष्ठ प्रदर्शन प्रदान करेगी, लेकिन यह वास्तव में आपके आवेदन के विनिर्देशों पर निर्भर करती है। हालांकि मैं अभी भी सूखी के मुद्दे स्वीकार

<% cache("recent_posts", :expires_in => 30.minutes) do %> 
    ... 
<% end %> 

नियंत्रक

unless fragment_exist?("recent_posts") 
    @posts = Post.find(:all, :limit=>20, :order=>"updated_at DESC") 
end 

:

+0

जबकि मुझे लगता है कि लैर का उत्तर थोड़ा और स्पष्ट हो सकता है, और मेटा प्रोग्रामिंग का उपयोग करने से बचाता है, तो आपका जवाब बेहतर है कि विज्ञापन एमवीसी के लिए अधिक बारीकी से सुनता है। मैंने दोनों को वैध के रूप में उखाड़ फेंक दिया है, लेकिन यह निर्णय लेने के लिए समुदाय को छोड़ देगा (स्वीकार्य के रूप में एक नहीं उठाएगा :) धन्यवाद! –

+0

मैं सहमत हूं, और यह भी एक अच्छा समाधान खोजने के लिए। दृश्य का पुन: उपयोग करने के लिए, सामान्य रूप से हाँ यह एक अच्छा सिद्धांत है। आपको नियंत्रक को कैश कुंजी की आपूर्ति करने की आवश्यकता होगी, हालांकि इसके लिए यहां काम करना है। बीटीडब्ल्यू, मज़ेदार रूप से पर्याप्त, खंड कैशिंग पर एपीआई दस्तावेज पहले उदाहरण में एमवीसी सिद्धांत का उल्लंघन करता है: http://api.rubyonrails.org/classes/ActionController/Caching/Fragments.html –

3

क्या होता है यदि कैश नियंत्रक में उस समय के बीच कैश की अवधि समाप्त हो जाती है और जब दृश्य दृश्य में जांच की जा रही है?

मैं मॉडल में एक नई विधि बनाने चाहते हैं:

class Post 
    def self.recent(count) 
     find(:all, :limit=> count, :order=>"updated_at DESC") 
    end 
    end 

तो का उपयोग उस दृश्य में:

<% cache("recent_posts", :expires_in => 30.minutes) do %> 
    <% Post.recent(20).each do |post| %> 
    ... 
    <% end %> 
<% end %> 

स्पष्टता के लिए, आप भी एक हाल ही में पोस्ट के प्रतिपादन ले जाने पर विचार कर सकता है में अपने स्वयं के आंशिक:

<% cache("recent_posts", :expires_in => 30.minutes) do %> 
    <%= render :partial => "recent_post", :collection => Post.recent(20) %> 
<% end %> 
+0

महान बिंदु लार्स में किसी भी कार्रवाई उपयोग

def index when_fragment_expired "cache_key", 5.minutes @object = YourObject.expensive_operations end end 

में

def when_fragment_expired(name, time_options = nil) # idea of avoiding race conditions # downside: needs 2 cache lookups # in view we actually cache indefinetely # but we expire with a 2nd fragment in the controller which is expired time based return if ActionController::Base.cache_store.exist?('fragments/' + name) && ActionController::Base.cache_store.exist?(fragment_cache_key(name)) # the time_fraqgment_cache uses different time options time_options = time_options - Time.now if time_options.is_a?(Time) # set an artificial fragment which expires after given time ActionController::Base.cache_store.write("fragments/" + name, 1, :expires_in => time_options) ActionController::Base.cache_store.delete("views/"+name) yield end 

तो निर्धारित करें! बहुत अच्छी चीजें –

+0

मुझे लगता है कि अब तक आपका सबसे अच्छा समाधान है, हालांकि तकनीकी रूप से यह एमवीसी का उल्लंघन कर सकता है, यह काफी स्पष्ट है। जेसन वाटकिन का जवाब एक वैध विकल्प है। –

1

तुम भी

Fragment Cache Docs

जो तुम ऐसा करने की अनुमति की जांच के लिए चाहते हो सकता है अपने सिर को दो स्थानों में कुंजी के नाम की आवश्यकता होती है। मैं आम तौर पर लार्स के सुझाव के समान करता हूं लेकिन यह वास्तव में स्वाद पर निर्भर करता है। अन्य डेवलपर्स मुझे पता है कि टुकड़े की जांच के साथ छड़ी मौजूद है।

अद्यतन:

आप टुकड़ा डॉक्स को देखें, तो आप देख सकते हैं कि यह दृश्य उपसर्ग की आवश्यकता होगी, से छुटकारा मिलता है:

# File vendor/rails/actionpack/lib/action_controller/caching/fragments.rb, line 33 
def fragment_cache_key(key) 
    ActiveSupport::Cache.expand_cache_key(key.is_a?(Hash) ? url_for(key).split("://").last : key, :views) 
end 
+0

आह, समझ में आता है। Fragment_exist? विधि शायद cache_key पर "दृश्य /" उपसर्ग की आवश्यकता से छुटकारा पाती है? –

1

लार्स वहाँ एक मामूली मौका होने के बारे में एक बहुत अच्छी बिंदु बनाता है विफलता का उपयोग:

unless fragment_exist?("recent_posts") 

क्योंकि जब आप कैश की जांच करते हैं और जब आप कैश का उपयोग करते हैं तो बीच एक अंतर होता है।

जेसन का उल्लेख है कि प्लगइन (इंटरलॉक) यह मानकर यह बहुत ही सुन्दर तरीके से संभालता है कि यदि आप टुकड़े के अस्तित्व की जांच कर रहे हैं, तो आप शायद टुकड़े का उपयोग भी करेंगे और इस प्रकार स्थानीय रूप से सामग्री को कैश करेंगे। मैं इन कारणों से इंटरलॉक का उपयोग करता हूं।

1

बस सोचा था की एक टुकड़े के रूप में:

आवेदन नियंत्रक में दृश्य

cache "cache_key" do 
view_code 
end 
संबंधित मुद्दे