2011-10-05 18 views
2

我知道這是一個有點特定於應用程序的問題,但我想看看是否有人有我沒有想過的聰明解決方案。這是一個艱難的任務,所以任何人都可以優雅地解決這個問題的重點(和道具)。處理任務計數,同時保持性能

我有一個包含任務數全球導航on Rails應用程序紅寶石(見下圖)

Global navitation with task counts

的問題是,產生這些計數需要一些激烈的查詢。因爲它的全球性,它在每一頁。他們還需要在人們處理任務時進行更新。這使得它特別具有挑戰性。

這就是說,現在我通過memcached將導航HTML緩存10分鐘。如果有人照顧一項任務,噢。導航每10分鐘更新一次。我知道,可怕的解決方案,但這是我的停止差距措施,直到我提出一個適當的解決方案。我想避免在應用程序中添加一堆鉤子(例如:處理傳遞,會觸發一個鉤子以減少每個相關用戶的計數)。請記住,這些計數涉及系統中的許多實體,邏輯有點複雜。它涉及訪問(每個用戶根據權限系統有不同的計數),並且在某些情況下確定這些計數可能很複雜。掛鉤會很快變得雜亂,並且生成這些計數的邏輯將被複​​制。

任何幫助將不勝感激。

+0

偉大的問題。您對導航HTML所做的事情是緩存,那麼爲什麼不將相同的緩存概念應用於將值存儲在「計數」表中?畢竟,在某個時候某些鉤子減少了一個計數,所以減少了表中的計數。這也應該有一些設計模式(希望)。 – Zabba

回答

-1

更新:

簡單的解決辦法是刪除所有緩存的導航HTML的變化的所有受影響的用戶。您也可以通過ajax調用加載navHTML,以便您不必等待加載頁面才能加載(並在客戶端的localStorage中保留navHTML的緩存版本,並且只要頁面加載完成就可以然後根據需要觸發重新設置navHTML)。

一個更復雜的解決方案是:在2個層(navHTML然後個別項目/用戶/狀態項)

緩存此。您必須找到一種方法來更新範圍,以便他們知道應該觸發重置的重要因素。因此,如果更改狀態機中的傳送狀態,則應重置該傳送的所有計數器,並刪除受影響用戶的導航緩存。

我會將每個交付項目的所有密鑰以某種名稱空間方式放入緩存中,例如「delivery:234324-user:123-status」,因此無論何時使用id#234324更改,您迭代並刪除所有緩存屬於該交付的項目(可能最好保持它儘可能愚蠢)。當有人請求頁面時,您可以計算並存儲要緩存的計數,只需在實際對象更改時刪除緩存。然後,您可以完全緩存導航HTML,但是隻要有更改,其中包含用戶和ID(例如user-123),就會刪除導航緩存,並強制導入HTML重新加載。爲導航添加一些類型的緩存時間(如最大年齡1分鐘或某事)來解決錯誤。導航項目應該通過單個項目的緩存構建,而不必通過每個項目。

你可能需要添加緩存掃地機連接到您的關聯模型http://guides.rubyonrails.org/caching_with_rails.html


下面是引用計數器緩存(我想建立數據庫模型,允許使用計數器緩存是最好的方式處理它)。

http://railscasts.com/episodes/23-counter-cache-column

有可能要麼用的has_many關係自動地使用它,或者手動更新計數。我假設如果你的模型是複雜的,並且你有一個多對多的關係,你可以把計數器緩存放在一個關係對象上。

+0

謝謝你。它不像計數器緩存那麼簡單。雖然我理解它背後的概念,但確定這些計數背後的大部分邏輯都存在於各種「範圍」中。他們依靠本地和外國的多種條件。我想唯一的解決方案是弄清楚如何做到這一點,我真的想避免它,因爲它會拋出我的應用程序掛鉤等。 –

1

如果爲自動遞增/遞減計數器添加額外的代碼被排除,其中一種解決方案是使用緩存並有效使用緩存。下面的僞代碼。

class User 

    def counters 
    needs_update(user_id) 
    memcache.read(counter_user_id) 
    end 

    def needs_update(user_id) 
     some_job_queue_for_counters.insert(Job.new(User.update_counters(user_id))) 
    end 

    #executed by the job runner 
    def update_counters user_id 
    counter_hash = {:counter1 => complex_logic1, :counter2 => complex_logic2 ...} 
    memcache.write(counter_user_id, counter_hash.to_json.gzipped) 
    end 

end 

有幾點要注意。

  1. 根據執行計數器邏輯的時間,從瀏覽器進行一次AJAX調用,例如每1分鐘或更多進行一次調用。
  2. 計數器方法儘可能快,因爲 memcache.read()返回壓縮的json字符串。零處理到 生成響應。
  3. 您可以在應用程序的開始 處預熱所有用戶的內存緩存。然後,計數器更新僅發生在 稱爲couters方法的用戶,即對於保持 瀏覽器/移動應用程序打開的用戶。
  4. needs_update方法可以爲user_id執行作業合併以避免重複。