1. 程式人生 > >多個獨立進程架構下的單進程數據庫同步方案

多個獨立進程架構下的單進程數據庫同步方案

pda 倒數 tlist 服務 uniq 更新 開始 定時同步 1.2

現在有一個分布在多臺主機上,每個主機上都有多個進程的http服務,這些所有的應用都是獨立、平等的,唯一聯系是同時都連接著同一個數據庫集群。 現在有一個需求,需要從另外一個數據源( http 接口)定時同步數據到我的數據庫中。 最簡單的辦法是每個進程都設置一個定時同步任務,但是這樣的話,不論是對對方接口的請求,還是對數據庫的更新都會有很多的無效操作,如果沒有其它更好的方案的話,才會考慮使用這個方案。 之後想到了一個方案,雖然應用是多進程的,但是每個 http 請求都只有一個特定應用來處理,這樣的話,我只要開發一個接口,觸發接口之後才開始同步數據,這樣部署完應用的時候我只去觸發一次接口,就可以保證只有一個進程在定時同步數據。這種方案的問題有1.無法立即確認確實有一個進程在同步了,這個可以通過在同步時加入日誌,通過日誌來確認 2.這種模式下,每次部署完之後都要先手動調用一次這個接口,不夠自動化 3.如果執行同步任務的進程因為什麽原因掛掉了,除非經常檢查日誌,否則很難及時發現同步任務已經掛掉 4.難以確認是哪臺機器的哪個進程在做同步任務,這個同樣可以通過查看日誌來確認
然後又想到了一個通過數據庫來解決問題的方案。在進程啟動的時候首先每個進程都向數據庫寫入一個記錄,然後等待一段時間後,比如半小時或者一小時之後,檢查數據庫上的記錄中中的最後一個,把其它的記錄都刪掉,然後各個服務器上的各個進程開始和數據庫中的記錄對比,剩余的一條是哪個進程寫入的那個記錄,就使用那個進程來同步數據。但是這樣仍然不能解決執行同步任務的進程掛掉時候,不能及時發現並解決問題的缺點。 最後,在數據庫集群治理模式上找到了靈感。我完全可以模仿mongodb復制集, 把這些相互獨立的進程看作一個集群,每次同步時從中選擇一個進程作為同步進程即可,這樣只要有至少一個進程存活即可。而如果所有進程都沒有在存活了,那麽服務整體都已經不可用了,也會很容易就發現問題。最終解決方案的具體實現方法是:
首先定義一個心跳時間,例如每10s。 每隔一個心跳時間,每個進程都向數據庫更新自己的最後存活時間; 然後設定如果每個進程超過3個心跳時間沒有與數據庫做交互,就判定為該進程已掛掉; 每2個心跳時間,每個進程都去驗證自己是不是獨特進程,如果是獨特進程,就繼續執行預定的定時任務,如果已經不是(有可能由於後來突然又新增了進程導致當前獨特進程不再是獨特進程),就停止掉當前進程的定時任務。

下面是具體的步驟和示例代碼:1. 註冊應用:初始化應用啟動時間、最後存活時間id = db.model.create(createTime, time);2. 所有應用間隔每個心跳時間定時更新自己的最後存活時間setInterval( update(id, time), heartbeatTime );
3. 所有應用獲取按應用id排序倒數10個應用id(也就是最後10個啟動的應用),用最後有效存活進程作為可用進程,在所有有效存活應用中,選擇按id排序而非時間排序的最後一個進程作為獨特進程(也可以按創建時間來選擇,只要不是按照最後存活時間就行),這個步驟也是在每個心跳時間定時執行setInterval(func() {list = db.getList().sort({ id: -1 }).limit(10);list = list.filter( now - time < heartbeatTime * 3 );porcessIsUnique = ( id == list[0].id );}, heartbeatTime)4. 定時檢查當前進程是否是獨特進程4.1.當前進程是獨特進程4.1.1.定時任務還沒有開始執行,開始執行定時任務4.1.2.定時任務已經開始執行,繼續執行定時任務,不做其他操作4.2. 當前進程不是獨特進程4.2.1. 如果定時任務已經在執行,停止定時任務4.2.2. 如果沒有定時任務,不做其它操作setInterval( func() {interval = null;if(processIsUnique) {if(!interval) {// 這裏執行需要執行的定時任務interval = setInterval( syncJob, syncTime );}}else {if(interval) {clearInterval(interval);interval = null;}}}, heartbeatTime * 2)這個模式有兩大優點: 1. 完全自治,部署完即可自動運行,不再需要手動控制 2.無縫熱更新擴展,無論是擴大還是縮小集群規模,均可自動適配,不需要重新部署

多個獨立進程架構下的單進程數據庫同步方案