2013-12-13 51 views
3

我想以優雅的方式緩存來自外部服務的數據:儘管舊數據已過期,但要等到工作人員成功獲取新數據時纔會提供。數據不是時間關鍵的,但缺乏數據(外部服務關閉)會阻止服務運行,因此使用持久性緩存。使用Python和Redis進行優雅緩存

目前

  • 我存儲在一個單獨的Redis的關鍵

  • 獲取時間戳我緩存無限期的數據,直到工人獲取新的(我不設置過期時間)

問題

  • 這是使用Redis進行優雅緩存的正確方法嗎?

  • 可我本身得到Redis的關鍵更新的時間戳,所以我並不需要存儲這些信息自己

這是代碼:

def set_data(self, data): 
    self.redis.set("bitcoinaverage", pickle.dumps(data)) 
    self.redis.set("bitcoinaverage_updated", calendar.timegm(datetime.datetime.utcnow().utctimetuple())) 

def get_data(self): 
    return pickle.loads(self.redis.get("bitcoinaverage")) 

def is_up_to_date(self): 

    last_updated = datetime.utcfromtimestamp(self.redis.get("bitcoinaverage_updated")) 

    if not last_updated: 
     return False 

    return datetime.datetime.utcnow() < last_updated + self.refresh_delay 

def tick(self): 
    """ Run a periodical worker task to see if we need to update. 
    """ 
    if not self.is_up_to_date(): 
     self.update() 

回答

2

你有什麼可以工作,但取決於你期望你的數據集有多大。如果我理解正確,你當前的實現將要求你運行一個工作者用tick()來檢測每個密鑰。在當前的實現中,這對於網絡來回會非常非常昂貴,因爲您必須通過網絡,查詢Redis,並將結果發送回每個密鑰(如果需要,可能需要兩個查詢更新)。如果只是你提到的兩個鍵,那很好。如果是更多,pipelines are your friend

如果您想要更優雅,更健壯,您可以在密鑰過期時使用notifications。這裏的範例是,對於每個值,您可以設置兩個鍵:kk_updatedk將保存該密鑰的實際值,並且k_updated將僅僅是當您想要更新k時設置了TTL的啞鍵。當k_updated過期時,您將收到通知,並且您可以讓偵聽程序立即處理此請求,作爲新作業的更新請求k並設置新的k_updated。這將使用pubsub模型,並且您可以擁有多個訂閱者並使用隊列來管理新作業,如果您想對此保持強大的話。這個系統的好處:

  1. 時,他們沒有需要不斷地對它們進行查詢,看他們是否需要更新到期鍵將會立即更新。

  2. 您可以擁有多個獨立工作人員訂閱並偵聽更新任務,並在他們進入時管理新的更新作業,這樣,如果一個更新工作人員出現故障,您不會丟失更新,直到您將該備份恢復爲止。

後者的系統可能是矯枉過正的情況下,如果你不具備極高的速度或耐用性的需求,但如果這樣做或計劃,這是值得考慮的。

+1

Wooaaah。我不知道Redis能做到這一切。幸運的是,我只有一個流程工作者,但是當我構建一些複雜的工作時,我會牢記這一點。 –

1

你在做什麼肯定會工作。

沒有辦法本機獲取密鑰插入/更新的時間戳,因此您必須按照當前的方式存儲它,或者作爲替代方案,您可以更改存儲在位串數據鍵中的內容以包含時間戳(例如,使用一些JSON來保存時間戳和醃製數據,並存儲JSON),但這會使get_data()和is_up_to_date()更加複雜。

如果您沒有爲該密鑰存儲任何內容,get_data()和is_up_to_date()會發生什麼?你有沒有測試過這種情況?

+0

謝謝!目前缺少數據/時間戳的初始條件被處理,但是也會添加它。 –

相關問題