天天看點

【原創】modb 功能設計之“多級 modb 之間的同步”

      modb 在最初設計中采用的是兩級模型,但很快就遇到了多級同步的需求。解決多級同步問題首先需要引入多級路由 key ,即将原來兩級模型中的單個 key 值擴充為 key 的 array ,具體變化如下: 

兩級使用的資料格式 

<a href="http://my.oschina.net/moooofly/blog/202726#">?</a>

1

2

3

4

5

6

7

8

<code>{</code>

<code>    </code><code>"src"</code> <code>:</code><code>"172.16.80.111"</code><code>,</code>

<code>    </code><code>"keys"</code> <code>:</code><code>"key_1"</code><code>,</code>

<code>    </code><code>"app"</code> <code>:</code><code>"a"</code><code>,</code>

<code>    </code><code>"state"</code> <code>:</code><code>"transfer"</code>

<code>    </code><code>"sql"</code> <code>:</code><code>"insert into users values(?,?,?)"</code><code>;</code>

<code>    </code><code>"sql-args"</code> <code>: [1, 2,</code><code>"abc"</code><code>]</code>

<code>}</code>

多級使用的資料格式 

<code>    </code><code>"keys"</code> <code>: [</code><code>"key_1"</code><code>,</code><code>"key_2"</code><code>]</code>

而在 modb 的業務邏輯進行中也需要增加相應的處理,具體如下: 

      假設處理的是三級資料同步情況,分别為 modb-a 、modb-b 和 modb-c 三級平台域(分别位于三級服務域中),且 a 是 b 的上級,b 是 c 的上級。a 級平台域中某業務對資料進行了變更,然後需要将此變更資訊同步到 b 和 c 級平台域。 

【原創】modb 功能設計之“多級 modb 之間的同步”

通過資料操作入口進行資料變更後,将發送如下消息給 modb-a: 

<code>    </code><code>"keys"</code> <code>: [</code><code>"key_b"</code><code>,</code><code>"key_c"</code><code>]</code>

modb-a 接收到此消息後(此時 a 級平台域的資料庫已經發生了變更),并根據配置将 

向同在 a 級的其他平台域進行消息轉發;

根據 key 值進行對下級的路由轉發;

在進行消息轉發前,modb-a 還會對消息内容做如下修改: 

<code>    </code><code>"keys"</code> <code>: [</code><code>"key_c"</code><code>]</code>

即從 keys 數組中移除 key_b 。 

      modb-b 在接收到上述消息後,将從中提取出 sql 内容進行執行,并對 keys 數組内容進行檢查,看是否還有其他 key 的存在,若有,則表明需要繼續進行向下級的路由轉發。         

      modb-b 重新擷取到該消息後(此時 b 級平台域的資料庫已經得到了更新),首先檢測 keys 數組中是否還有其他 key 存在,若有,則在進行轉發前會對消息内容做如下修改: 

      (這裡 modb-b 先後兩次作為 consumer 收到 rabbitmq 消息是因為分别訂閱了遠端和本地的 queue 所緻,好處是處理起來模型統一   ) 

<code>    </code><code>"keys"</code> <code>: []</code>

即從 keys 數組中移除 key_c 。 

      modb-c 接收到上述消息後,将從中提取 sql 内容進行執行,并對 keys 數組内容進行檢查,看是否還有其他 key 的存在,若沒有,則表明已不再需要繼續進行路由。 

      modb-c 重新擷取到該消息後(此時 c 級平台域的資料庫已經得到了更新),首先檢測 keys 數組中是否還有其他 key 存在,若沒有,則隻需要對相同服務域中的平台域進行廣播,而無需進行下一級轉發。 

      上述模型的優點是簡單,僅通過配置就可以完成多級關系的資料同步功能;缺點是存在單點,不具有動态變更上下級關系的能力,需要通過其他方式進行後續配置。 

可能遇到的異常情況: 

rabbitmq 伺服器異常 -- 業務更新本地資料庫成功後,将發送通知消息到 rabbitmq 伺服器,需要業務端能夠判斷出“伺服器不可用”狀态,并觸發重傳等操作;

modb 程序異常 -- 業務更新本地資料庫成功後,發送通知消息到 rabbitmq 伺服器,若要求在 modb 程序異常的情況下消息不丢失,則需要 rabbitmq 啟用對消息的持久化功能,并且最好取消掉 exclusive 和 auto_delete 等相關屬性的設定,可能還需要處理當 queue 不存在時消息被 blackholed 的情況;

atlas 異常 -- 若在業務尚未成功更新本地資料庫前發生 atlas 異常,則要求業務能夠告之目前情況下“無法建立資料庫連接配接”;若在業務成功更新本地資料庫後發生 atlas 異常,此時向外部 modb 同步目前更新沒有問題,但無法同步外部 modb 對本地資料庫的更新。(可能的一種解決辦法:令 modb 支援緩存功能,當發現 atlas 異常時則将更新消息放入緩存隊列,并在每次接收到新的更新消息時觸發一次針對 atlas 是否恢複的檢測。若 atlas 已經恢複,則将緩存隊列中的内容順序執行)

      上述問題并未針對“異常情況下對 資料庫進行操作時可能遇到的問題” 進行深入的說明,具體問題一定會更加複雜。一點體會:若想真正的把資料庫同步功能做好,最起碼需要深入了解資料一緻性的相關理論,若有一個成熟的架構可以使用就更加完美了。