2012-06-16 31 views
15

Tôi viết mã cho trang blog/tin tức. Trang chính có 10 bài viết gần đây nhất và cũng có một phần lưu trữ với tất cả các bài báo được sắp xếp theo thời gian sửa đổi giảm dần. Trong phần lưu trữ, tôi sử dụng phân trang dựa trên con trỏ và kết quả bộ nhớ cache của tôi bắt đầu từ trang thứ hai vì các trang được thay đổi chỉ khi bài viết mới được xuất bản hoặc hiện tại đi vào bản nháp vì lý do nào đó. Mỗi trang có 10 bài viết. Vì vậy, khi người dùng truy cập một trang lưu trữ với một số số (không phải là trang đầu tiên), memcache sẽ được kiểm tra cho kết quả số trang đó trước tiên. Nếu trang không có, memcache được kiểm tra cho con trỏ cho trang đó và sau đó kết quả được lấy từ kho dữ liệu sử dụng mà con trỏ:Đọc trễ trong App Engine Datastore sau khi đặt()

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) 

Mỗi lần một bài viết mới được tạo ra hoặc tình trạng của một bài báo hiện đang thay đổi (dự thảo/xuất bản) Tôi làm mới bộ nhớ cache cho các kết quả trang lưu trữ và con trỏ. Tôi làm điều đó sau khi tiết kiệm một bài báo để các kho dữ liệu:

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 

Và ở đây có vấn đề. Đôi khi (không có luật, nó xảy ra ngẫu nhiên) sau khi làm mới bộ nhớ cache tôi nhận được kết quả tương tự và con trỏ cho các trang lưu trữ như trước khi làm mới. Ví dụ tôi thêm một bài viết mới. Nó được lưu trong kho dữ liệu và nó xuất hiện trên trang đầu và trên trang đầu tiên trong kho lưu trữ (trang đầu tiên của kho lưu trữ không được lưu trữ). Nhưng các trang lưu trữ khác không được cập nhật. Tôi đã thử nghiệm hàm cacheArchivePages() của mình và nó hoạt động như mong đợi. Nó có thể được như vậy mà quá ít thời gian đã trôi qua sau khi tôi đặt() một bản cập nhật cho kho dữ liệu và trước khi tôi fetchArticlesPage() trong cacheArchivePages() chức năng? Có lẽ giao dịch viết chưa kết thúc và vì vậy tôi nhận được kết quả cũ? Tôi đã cố gắng sử dụng time.sleep() và chờ một vài giây trước khi gọi cacheArchivePages() và trong trường hợp đó tôi không thể tái tạo hành vi đó, nhưng dường như với tôi rằng time.sleep() không phải là một ý tưởng hay. Dù sao thì tôi cũng cần phải biết chính xác nguyên nhân của hành vi đó và cách giải quyết nó.

Trả lời

22

Bạn có nhiều khả năng bị ảnh hưởng bởi "truy vấn cuối cùng nhất quán". Khi sử dụng kho dữ liệu HR, các truy vấn có thể sử dụng dữ liệu cũ, và phải mất một thời gian cho dữ liệu được viết bởi put() để hiển thị cho các truy vấn (không có sự chậm trễ như vậy cho get() bằng khóa hoặc id). Độ trễ thường được đo bằng giây nhưng tôi không nghĩ chúng tôi đảm bảo giới hạn trên - nếu bạn bị ảnh hưởng bởi phân vùng mạng không may, có thể là hàng giờ, tôi tưởng tượng.

Có tất cả các loại giải pháp từng phần, từ gian lận khi tác giả của bài viết gần đây nhất đang xem kết quả truy vấn để sử dụng truy vấn tổ tiên (có chia sẻ hạn chế riêng). Bạn có thể chỉ cần cung cấp cho bộ nhớ cache của bạn một thời gian giới hạn và cập nhật nó trên đọc thay vì viết.

Chúc may mắn!

+0

Cảm ơn bạn Guido! Tôi nên chú ý hơn đến tính nhất quán của dữ liệu và ghi nhớ các đặc điểm của kho dữ liệu HR. Trong trường hợp cụ thể này, tôi dễ dàng so sánh các kết quả cũ và các kết quả mới và nếu chúng giống nhau để khởi động lại truy vấn. – wombatonfire

+0

Tôi upvoted vì "sử dụng truy vấn tổ tiên" là chính xác những gì giải quyết vấn đề chậm trễ trong ứng dụng của tôi, cảm ơn bạn Guido. – Deleplace

Các vấn đề liên quan