posts - 12, comments - 8, trackbacks - 0, articles - 5
            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          一. 應(yīng)用場景

          在大型分布式應(yīng)用中,我們經(jīng)常碰到在多數(shù)據(jù)庫之間的數(shù)據(jù)同步問題,比如說一款游戲,在玩家注冊后,可以馬上登陸進(jìn)入服務(wù)器,數(shù)據(jù)在一個IDC更新,其它IDC立即可見。為了簡化思路,我們這里稱玩家注冊的數(shù)據(jù)庫(數(shù)據(jù)來源庫)為中心庫,同步目的地的數(shù)據(jù)庫為分站庫。

          在分布式領(lǐng)域有個CAP理論,是說Consistency(一致性), Availability(可用性), Partition tolerance(分區(qū)和容錯) 三部分在系統(tǒng)實現(xiàn)只可同時滿足二點,法三者兼顧。

          能做的

          · 數(shù)據(jù)快速搬運(yùn)到指定的IDC節(jié)點

          · 數(shù)據(jù)傳遞過程中失敗時,重新傳遞

          · 監(jiān)控數(shù)據(jù)傳遞流程

          · 故障轉(zhuǎn)移

          · 數(shù)據(jù)版本控制

          · 分配全局唯一的ID

          不能做的

          · 不參與業(yè)務(wù)行為,業(yè)務(wù)操作只能通過注冊的方式集成

          · 不保存業(yè)務(wù)數(shù)據(jù),不提供傳遞的業(yè)務(wù)的查詢

          二.系統(tǒng)要求

          1.數(shù)據(jù)快速同步:除去網(wǎng)絡(luò)原因,正常情況下從來源庫同步到接收庫的時間不超過300m2.高并發(fā):單個應(yīng)用每秒同步2000條記錄
          3.可伸縮性,在資源達(dá)到上限時能通過增加應(yīng)用分散處理后期增長的壓力
          4.數(shù)據(jù)完整性要求,在數(shù)據(jù)同步過程中保證數(shù)據(jù)不丟失和數(shù)據(jù)安全
          5.故障轉(zhuǎn)移和數(shù)據(jù)恢復(fù)功能

          三.設(shè)計思路

          系統(tǒng)優(yōu)化,最常用的就是進(jìn)行業(yè)務(wù)切割,將總?cè)蝿?wù)切割為許多子任務(wù),分區(qū)塊分析系統(tǒng)中可能存在的性能瓶頸并有針對性地進(jìn)行優(yōu)化,在本系統(tǒng)中,主要業(yè)務(wù)包含以下內(nèi)容:
          1.Syncer:外部接口,接收同步數(shù)據(jù)請求,初始化同步系統(tǒng)的一些必要數(shù)據(jù)
          2.Delivery:將同步數(shù)據(jù)按照業(yè)務(wù)或優(yōu)先級進(jìn)行分發(fā),并記錄分發(fā)結(jié)果
          3.Batch:分站庫收到同步數(shù)據(jù)后,根據(jù)不同的業(yè)務(wù)類型調(diào)用相應(yīng)的業(yè)務(wù)邏輯處理數(shù)據(jù)
          基于以上三塊業(yè)務(wù)功能,我們可以把整個數(shù)據(jù)同步流程切割為3個應(yīng)用,具體如下圖顯示。在Syncer端應(yīng)用中,我們需要將原始同步數(shù)據(jù)和分發(fā)的分站進(jìn)行存儲,以備失敗恢復(fù),此時如果采用數(shù)據(jù)庫進(jìn)行存儲,勢必會受限于數(shù)據(jù)庫性能影響,因此我們采用了高效的key-value風(fēng)格存儲的redis服務(wù)來記錄數(shù)據(jù),同時在不同應(yīng)用之間采用隊列(Httpsqs服務(wù))的方式來進(jìn)行通訊,同時也保證的數(shù)據(jù)通訊的順序性,為之后的順序同步做好基礎(chǔ)。
          Httpsqs提供了http風(fēng)格的數(shù)據(jù)操作模式,業(yè)務(wù)編碼非常簡單,同時也提供了web形式的隊列處理情況查詢,這是選擇它做隊列服務(wù)很大一部分原因:方便業(yè)務(wù)操作和性能監(jiān)控。

          四.數(shù)據(jù)流轉(zhuǎn) 

          綠色-正常流程、紅色-異常流程

          隊列處理

          根據(jù)業(yè)務(wù)劃分隊列名稱,每個隊列再劃分為三個關(guān)聯(lián)隊列:正常隊列(Normal)、重試隊列(Retry)、死亡隊列(Death),處理流程為:

          【進(jìn)程A】把數(shù)據(jù)先放入正常隊列,如果放置失敗寫恢復(fù)日志

          【進(jìn)程B】監(jiān)聽正常隊列,獲取隊列數(shù)據(jù)并進(jìn)行業(yè)務(wù)處理,處理失敗放入重試隊列

          【進(jìn)程C】監(jiān)聽重試隊列,過幾秒獲取隊列數(shù)據(jù)并重新進(jìn)行業(yè)務(wù)處理,處理失敗放入死亡隊列

          【進(jìn)程D】監(jiān)聽死亡隊列,獲取隊列數(shù)據(jù)并重新進(jìn)行業(yè)務(wù)處理,處理失敗重新放入死亡隊列尾部,等待下一次輪回

          業(yè)務(wù)處理失敗如果無法再次放入隊列,記錄恢復(fù)日志

          數(shù)據(jù)同步流程

          1發(fā)送數(shù)據(jù),支持Http POST:curl -d "經(jīng)過URL編碼的文本消息",如"http://host:port/sync_all/register"
          或者Http GET:curl "http://host:port/sync_all/register?data=經(jīng)過URL編碼的文本消息"

          sync-syncer接收到同步數(shù)據(jù)請求,創(chuàng)建sid并分解出需要同步的節(jié)點個數(shù),把原始數(shù)據(jù)和子任務(wù)寫入redis中,sid寫入httpsqs中

          sync-delivery監(jiān)聽中心httpsqs隊列,根據(jù)sid從redis獲取到原始數(shù)據(jù)和需要同步的節(jié)點地址,往其他節(jié)點發(fā)送數(shù)據(jù),流程如按"隊列處理流程"進(jìn)行

          sync-batch監(jiān)聽分節(jié)點的httpsqs隊列,調(diào)用已經(jīng)注冊的處理器處理隊列數(shù)據(jù),流程如按"隊列處理流程"進(jìn)行

          三. 恢復(fù)和監(jiān)控

          恢復(fù)數(shù)據(jù)源

          · httpsqs中的死亡隊列 - 業(yè)務(wù)處理暫時處理不了的數(shù)據(jù)

          · recovery日志文件 - 其它異常情況下的數(shù)據(jù),例如網(wǎng)絡(luò)無法連接、內(nèi)部服務(wù)不可用

          數(shù)據(jù)恢復(fù)

          獨(dú)立的應(yīng)用來處理正常流程中沒有完成的任務(wù),主要功能有:

          · 監(jiān)聽死亡隊列,進(jìn)行業(yè)務(wù)重做,再次執(zhí)行失敗時將執(zhí)行次數(shù)+1,最大執(zhí)行次數(shù)為5(默認(rèn)),超出上限則記錄到恢復(fù)日志中

          · 讀取恢復(fù)日志,重新放入死亡隊列

          應(yīng)用監(jiān)控

          · 使用scribe日志框架服務(wù)業(yè)務(wù)日志的采集和監(jiān)控

          · 收集重要的業(yè)務(wù)操作日志

          · 動態(tài)的開啟/關(guān)閉某類業(yè)務(wù)日志

          · 對redis進(jìn)行監(jiān)控

          · 對httpsps,監(jiān)控隊列個數(shù),每個隊列的狀態(tài)

          四. 數(shù)據(jù)結(jié)構(gòu)

          {"sid":111,"type":"reg","v":1,"data":"hello world","ctime":65711321800,"exec":1}

          · sid(sync id) - 全局唯一id

          · v(version) - 版本號

          · data - 業(yè)務(wù)數(shù)據(jù)

          · ctime(create time) - 創(chuàng)建時間(毫秒)

          · exec - 可選,執(zhí)行次數(shù)

          類別

          key格式

          value格式

          備注

          redis原始數(shù)據(jù)

          sync:<業(yè)務(wù)類型>:<sid>

          {"ctime":65711321800,"v":1,"data":"hello world"}

          分站沒有此項

          redis業(yè)務(wù)附加任務(wù)

          sync:<業(yè)務(wù)類型>:<sid>:sub

          set類型,保存需要同步的節(jié)點id,例如[1,3,5]

          分發(fā)確認(rèn)Set數(shù)據(jù)結(jié)構(gòu) 

          httpsqs隊列

          sync:<業(yè)務(wù)類型> 
          sync:<業(yè)務(wù)類型>:retry 
          sync:<業(yè)務(wù)類型>:death

          {"sid":111,"type":"pp_register","exec":1} 

          中心隊列內(nèi)容,key中<業(yè)務(wù)類型>是可選項 

          httpsqs隊列

          sync:<業(yè)務(wù)類型> 
          sync:<業(yè)務(wù)類型>:retry 
          sync:<業(yè)務(wù)類型>:death

          {"sid":111,"v":1,"data":"hello world","ctime":65711321800,"exec":1} 

          分站隊列內(nèi)容,包含業(yè)務(wù)數(shù)據(jù) 

          所有的key都小寫,以 ':' 作為分隔符

          五.編碼及測試結(jié)果

          經(jīng)過編碼和測試,在內(nèi)網(wǎng)環(huán)境下,在無數(shù)據(jù)庫限制的情況下,單應(yīng)用可以傳遞1500條/秒,基本滿足業(yè)務(wù)需求。如果需進(jìn)一步擴(kuò)展,采用集群式布署可使得吞吐量成倍的增長。


          評論

          # re: 數(shù)據(jù)同步系統(tǒng)設(shè)計  回復(fù)  更多評論   

          2013-07-29 16:02 by adf
          asdfasdfadsf

          # re: 數(shù)據(jù)同步系統(tǒng)設(shè)計[未登錄]  回復(fù)  更多評論   

          2013-11-06 17:23 by 魚中魚
          要是有個示例就好了。

          # re: 數(shù)據(jù)同步系統(tǒng)設(shè)計  回復(fù)  更多評論   

          2013-12-26 16:41 by bolo
          太慢了吧,才2000條/s,我做的可以7000條/s

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
          博客園   IT新聞   Chat2DB   C++博客   博問  
           
          主站蜘蛛池模板: 河南省| 木里| 荔波县| 厦门市| 烟台市| 永州市| 天津市| 湘乡市| 原平市| 盐源县| 郑州市| 陆丰市| 武强县| 漳浦县| 云浮市| 公安县| 民县| 永川市| 鹿泉市| 镇沅| 贺兰县| 灵台县| 精河县| 上蔡县| 岱山县| 兰溪市| 台安县| 沙湾县| 镇平县| 鄂伦春自治旗| 茂名市| 丹巴县| 贵港市| 怀来县| 贵州省| 方山县| 青神县| 二连浩特市| 华亭县| 铜山县| 拜泉县|