2012-06-16 15 views
15

मैं एक ब्लॉग/समाचार साइट के लिए एक कोड लिखता हूं। मुख्य पृष्ठ में 10 सबसे हाल के लेख हैं और साथ ही एक संग्रह अनुभाग भी है जिसमें संशोधित समय अवरुद्ध किए गए सभी लेख शामिल हैं। संग्रह अनुभाग में मैं कर्सर के आधार पर पेजिनेशन का उपयोग करता हूं और मैं दूसरे पृष्ठ से शुरू होने वाले परिणाम कैश करता हूं क्योंकि पृष्ठ केवल तभी बदलते हैं जब नया आलेख प्रकाशित होता है या किसी कारण से ड्राफ्ट में जाता है। प्रत्येक पृष्ठ में 10 लेख हैं। तो जब कोई उपयोगकर्ता कुछ पेज के साथ एक संग्रह पृष्ठ हिट करता है (पहले नहीं) तो पहले उस पृष्ठ संख्या परिणामों के लिए memcache की जांच की जाती है। पेज वहाँ, मेम्कैश उस पृष्ठ के लिए कर्सर के लिए चेक न किया जाए और फिर परिणाम है कि कर्सर का उपयोग डेटास्टोर से लाई जाती हैं:डालने के बाद ऐप इंजन डेटास्टोर में देरी पढ़ें()

class archivePage: 
    def GET(self, page): 
     if not page: 
      articles = memcache.get('archivePage') 
      if not articles: 
       articles = fetchArticles() 
       memcache.set('archivePage', articles) 
     else: 
      if int(page) == 0 or int(page) == 1: 
       raise web.seeother('/archive') 
      articles = memcache.get('archivePage'+page) 
      if not articles: 
       pageCursor = memcache.get('ArchivePageMapping'+page) 
       if not pageCursor: 
        pageMapping = ArchivePageMapping.query(ArchivePageMapping.page == int(page)).get() 
        pageCursor = pageMapping.cursor 
        memcache.set('ArchivePageMapping'+page, pageCursor) 
       articles = fetchArticles(cursor=Cursor(urlsafe=pageCursor)) 
       memcache.set('archivePage'+page, articles) 

हर बार एक नया अनुच्छेद बनाई गई है या एक मौजूदा लेख की स्थिति बदल रहा है (ड्राफ्ट/प्रकाशित) मैं संग्रह पृष्ठों के परिणामों और कर्सर के लिए कैश रीफ्रेश करता हूं। मैं डेटासंग्रह को एक लेख सहेजने के बाद यह कार्य करें:

class addArticlePage:  
    def POST(self): 
     formData = web.input() 
     if formData.title and formData.content: 
      article = Article(title=formData.title, 
           content=formData.content, 
           status=int(formData.status)) 
      key = article.put() 
      if int(formData.status) == 1: 
       cacheArchivePages() 
      raise web.seeother('/article/%s' % key.id()) 

def cacheArchivePages(): 
    articles, cursor, moreArticles = fetchArticlesPage() 
    memcache.set('archivePage', articles) 
    pageNumber=2 
    while moreArticles: 
     pageMapping = ArchivePageMapping.query(ArchivePageMapping.page == pageNumber).get() 
     if pageMapping: 
      pageMapping.cursor = cursor.urlsafe() 
     else: 
      pageMapping = ArchivePageMapping(page=pageNumber, 
              cursor=cursor.urlsafe()) 
     pageMapping.put() 
     memcache.set('ArchivePageMapping'+str(pageNumber), cursor.urlsafe()) 
     articles, cursor, moreArticles = fetchArticlesPage(cursor=cursor) 
     memcache.set('archivePage'+str(pageNumber), articles) 
     pageNumber+=1 

और यहाँ समस्या आती है। कभी-कभी (कोई कानून नहीं है, यह यादृच्छिक रूप से होता है) कैश को रीफ्रेश करने के बाद मुझे रीफ्रेश से पहले संग्रह पृष्ठों के लिए एक ही परिणाम और कर्सर मिलते हैं। उदाहरण के लिए मैं एक नया लेख जोड़ता हूं। यह डेटास्टोर में सहेजा जाता है और यह सामने वाले पृष्ठ पर और संग्रह में पहले पृष्ठ पर दिखाई देता है (संग्रह का पहला पृष्ठ कैश नहीं किया जाता है)। लेकिन अन्य संग्रह पेज अपडेट नहीं किए गए हैं। मैंने अपने कैश आर्चिव पेज() फ़ंक्शन का परीक्षण किया है और यह अपेक्षा के अनुसार काम करता है। क्या ऐसा हो सकता है कि मैंने डेटास्टोर को अद्यतन() को अद्यतन करने के बाद बहुत कम समय बीत चुका है और इससे पहले कि मैं cacheArchivePages() फ़ंक्शन में ArticlePage() लाता हूं? शायद लेखन लेनदेन अभी तक खत्म नहीं हुआ है और इसलिए मुझे पुराने परिणाम मिलते हैं? मैंने time.sleep() का उपयोग करने की कोशिश की और cacheArchivePages() को कॉल करने से पहले कुछ सेकंड प्रतीक्षा करें और उस स्थिति में मैं उस व्यवहार को पुन: उत्पन्न करने में सक्षम नहीं था, लेकिन ऐसा लगता है कि time.sleep() एक अच्छा विचार नहीं है। वैसे भी मुझे उस व्यवहार के लिए सही कारण जानने और इसके साथ कैसे निपटने की आवश्यकता है।

उत्तर

22

आपको "अंततः लगातार पूछताछ" द्वारा मारा जा रहा है। एचआर डेटास्टोर का उपयोग करते समय, प्रश्न थोड़ा पुराने डेटा का उपयोग कर सकते हैं, और क्वेरी() द्वारा प्रश्नों के लिए दृश्यमान होने के लिए कुछ समय लगता है (कुंजी या आईडी द्वारा प्राप्त() के लिए कोई देरी नहीं है)। विलंब आमतौर पर सेकंड में मापा जाता है लेकिन मुझे नहीं लगता कि हम ऊपरी बाउंड की गारंटी देते हैं - यदि आप दुर्भाग्यपूर्ण नेटवर्क विभाजन से प्रभावित होते हैं तो यह घंटों का समय हो सकता है, मुझे कल्पना है।

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

शुभकामनाएं!

+0

धन्यवाद Guido! मुझे डेटा स्थिरता पर अधिक ध्यान देना चाहिए और एचआर डेटास्टोर की विशेषताओं को ध्यान में रखना चाहिए। इस विशेष मामले में मेरे लिए पुराने परिणामों और नए लोगों की तुलना करना आसान है और यदि वे क्वेरी को पुनरारंभ करने के लिए समान हैं। – wombatonfire

+0

मैंने अपरिवर्तित किया क्योंकि "पूर्वजों के प्रश्नों का उपयोग करें" वास्तव में मेरे ऐप में देरी के मुद्दे को हल करने के लिए, आपको Guido धन्यवाद। – Deleplace

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