天天看點

多核計算與并發程式設計(四) 緩存資料同步的設計

   這次講一個完整的例子,我們就做一個打折加油站資訊一覽,功能是浏覽油價打折的加油站,以及目前的汽油價格。

   我們這個網站的通路量非常大,一台伺服器是不夠的(否則我們就不需要在多台伺服器間同步資料了不是嗎),甚至于給我們提供加油站資訊的人也非常多,錄入資料也需要多台伺服器,于是我們有了下面的伺服器的架構

<a href="http://blog.51cto.com/attachment/201312/213034761.jpg"></a>

   我們有一台資料庫伺服器,也許将來是多台,但是不在本文的讨論範圍。

   我們有兩台用于資料維護(錄入、修改)的伺服器,我們稱之為“寫服務”。我們有三台緩存伺服器,把資料庫裡面的資料全部加載到記憶體中,提高服務響應的速度,給網站和手機端使用,我這裡稱為“讀服務”。

我們思考以下問題:

   1.“寫服務”使用中,如果使用者錄入資料時連接配接到不同的伺服器(A和B),行為和結果會不同嗎?

   2.“寫服務”引起的資料改變,怎麼通知到“讀服務”去更新緩存中的資料?

   3.“讀服務”使用中,如果使用者錄入資料時連接配接到不同的伺服器(C、D、E),行為和結果會不同嗎?

現在回答上面的問題

   1.“寫服務”沒有資料緩存,使用者所有的操作都是直接和資料庫打交道,是以,所有伺服器的行為都是一緻的,使用者連接配接到伺服器A或者B,沒有任何差别。

   2.這裡我使用一個簡單的方法來實作,到“寫服務”引起資料變化後,把資料變化的條目id,追加到一個記錄資料變化的隊列中。“讀服務”的伺服器各自定時查詢資料變化的隊列,從資料庫讀取對應的記錄來更新自身的緩存。

   3.“讀服務”的伺服器C、D、E各自定期更新緩存,會有資料不一緻的情況,取決于“定期”更新的間隔,使用者連接配接上不同的伺服器,可能會查詢到不同的資料,在大多數應用中,這是可以容忍的。

現在講一講資料同步的具體實作

1.消息約定

   在我們的應用中,隻有一種消息,就是“資料變化”,參數是資料庫中變化資料的id,“寫服務”在任何操作後,都發送“資料變化”消息。

   “讀服務”收到消息後,去資料庫查詢對應的記錄,有三種情況。

   a.資料庫查到記錄,緩存中沒有,可能是“寫服務”進行了添加操作。“讀服務”把記錄添加到緩存中

   b.資料庫查到記錄,緩存中也有,可能是“寫服務”進行了更新操作。“讀服務”更新緩存中的記錄

   c.資料庫沒有,緩存中存在,可能是“寫服務”進行了删除操作。“讀服務”删除緩存中的記錄

這一消息約定的優點是,即是消息重複執行,也不會造成資料錯誤

2.消息隊列

   我使用資料庫的一個表,來作為消息隊列,每個消息有自動增加的id,和建立時間。自動增加id是給消費者(“讀服務”)避免重複消費已經消費過的消息。建立時間用于定時批量删除過期的消息

3.消費消息

   “讀服務”定時查詢消息表,消費消息(更新緩存)之後,記錄最後的id,避免下次重複擷取

4.“讀服務”重新開機

   當服務重新開機的時候,所有的資料都是從資料庫讀取的最新資料,但也有可能在加載資料的過程中,有新的資料變化。解決辦法是,

   在啟動的最初,記錄消息隊列最大的消息id,在啟動完成後,已剛才擷取的最大id,作為首次擷取消息的起始值(但不包括那個最大id),如果在啟動過程中,消息隊列有了新id,将不會錯過。

總結一下,這個方案

   優點:實作簡單,讀伺服器之間不需要有資料交換,所有的服務都各自通路消息隊列。

   缺點:使用消息輪詢,資料加載會有延後,延後的時間取決于輪詢的間隔。

本文轉自 ponpon_ 51CTO部落格,原文連結:http://blog.51cto.com/liuxp0827/1344918,如需轉載請自行聯系原作者