分布式腕巡、服務化的ERP系統(tǒng)架構設計

ERP之痛

? ? ? ?曾幾何時玄坦,我混跡于電商、珠寶行業(yè)4年多绘沉,為這兩個行業(yè)開發(fā)過兩套大型業(yè)務系統(tǒng)(ERP)煎楣。作為一個ERP系統(tǒng),系統(tǒng)主要功能模塊無非是訂單管理车伞、商品管理择懂、生產(chǎn)采購、倉庫管理另玖、物流管理困曙、財務管理等等。作為一個管理系統(tǒng)谦去,大家的一般開發(fā)習慣就是使用.Net或Java技術慷丽,建立一個單塊(單進程)架構的應用,只有一個SQLServer或MySql數(shù)據(jù)庫鳄哭。然后在項目文件中分一下各個模塊要糊,三層結構方式組織代碼編寫開發(fā)。最后測試妆丘,交付上線锄俄。

? ? ? ? 起初,因為數(shù)據(jù)量不大勺拣,系統(tǒng)性能還不錯奶赠,各種列表查詢,報表查詢药有,Excel數(shù)據(jù)導出功能等用的都很流暢车柠。但是隨著公司業(yè)務發(fā)展,訂單量日積月累,后期各種業(yè)務部門的報表查詢竹祷、數(shù)據(jù)導出需求不斷增多谈跛,我們漸漸就感覺系統(tǒng)運行越來越慢。于是我們可能最先想到的解決方案就是塑陵,優(yōu)化系統(tǒng)瓶頸數(shù)據(jù)庫這個大頭感憾。我們可能的一種嘗試就是將數(shù)據(jù)庫單獨放置到一個服務器,實現(xiàn)數(shù)據(jù)庫和應用程序分離令花,或者是建立各種數(shù)據(jù)庫表索引阻桅,優(yōu)化程序代碼等方法。經(jīng)過這樣一番研究優(yōu)化兼都,系統(tǒng)某些功能可能性能的確大大提高嫂沉,但是我們還是發(fā)現(xiàn)某些功能列表的數(shù)據(jù)查詢導出依然很慢,或者隨著數(shù)據(jù)量繼續(xù)積累扮碧,原來較快的列表導出功能趟章,也愈來愈變得緩慢了。我們用盡各種辦法慎王,最后也達不到理想的系統(tǒng)性能速度蚓土。

? ? ? ? 為了提高系統(tǒng)性能,我們也許會主動學習一些互聯(lián)網(wǎng)公司的技術經(jīng)驗赖淤,什么高并發(fā)蜀漆、高性能、大數(shù)據(jù)咱旱、讀寫分離等方案确丢,發(fā)現(xiàn)自己根本無從下手。我們會覺得因為系統(tǒng)業(yè)務特點不一樣吐限。ERP系統(tǒng)并發(fā)量不高鲜侥,主要是業(yè)務復雜,各種業(yè)務耦合度遠高于那些互聯(lián)網(wǎng)應用毯盈,不好做拆分剃毒,數(shù)據(jù)查詢邏輯要遠比互聯(lián)網(wǎng)系統(tǒng)復雜病袄,一個列表頁查詢出來的數(shù)據(jù)搂赋,往往需要關聯(lián)4、5張表才能得到結果益缠。有些報表類的甚至更多脑奠。加上各種業(yè)務操作事務性、數(shù)據(jù)一致性要求很高幅慌,很多時候?qū)е挛覀兇氩患笆炙纹郏瑹o法進一步優(yōu)化系統(tǒng)。

? ? ? ? 曾幾何時,我也被這樣或那樣的理由所挫敗齿诞,認為ERP系統(tǒng)非常特殊酸休,無藥可救,可是后來祷杈。斑司。。

? ? ? ? 我現(xiàn)在已經(jīng)不這么認為了但汞,似乎有了新的解決方案O(∩_∩)O哈哈~

曙光乍現(xiàn)

? ? ? ?在敘述具體方案前宿刮,先說下自己的想法。我首先覺得我們做ERP系統(tǒng)前私蕾,就得有當今互聯(lián)網(wǎng)思維僵缺。我們不要再去做一個大一統(tǒng)的系統(tǒng)了。我們要分拆一個大系統(tǒng)踩叭,做成一個個小系統(tǒng)磕潮。然后通過系統(tǒng)接口讓這些小系統(tǒng)相互通信。這樣來組成一個大系統(tǒng)懊纳,具體來說就是“分布式”揉抵、“服務化”的互聯(lián)網(wǎng)思維。讓系統(tǒng)在架構設計上就是一個先天支持高度可擴展的系統(tǒng)嗤疯。

? ? ? ?怎么做呢冤今?具體來說就是要將訂單管理、商品管理茂缚、生產(chǎn)采購戏罢、倉庫管理、物流管理脚囊、財務管理拆分成一個個子系統(tǒng)龟糕。這些子系統(tǒng)可以單獨設計開發(fā),對外暴露出各種其他子系統(tǒng)需求的數(shù)據(jù)接口即可悔耘。每個子系統(tǒng)都有單獨的數(shù)據(jù)庫讲岁。甚至這些子系統(tǒng)可以交由不同的團隊去開發(fā)和維護,使用不同的技術體系衬以,使用不同的數(shù)據(jù)庫缓艳。而不是再像以前那樣,都集成在同一個大而全的系統(tǒng)中看峻,一個大而全的數(shù)據(jù)庫阶淘。

? ? ? ?對于新架構的系統(tǒng)他有什么優(yōu)點呢?

? ? ? ?首先互妓,也是最重要的就是解決系統(tǒng)的性能問題溪窒。以往數(shù)據(jù)庫實例只有一個坤塞,沒法擴展出多個實例,以便在性能受限的情況下依靠增加數(shù)據(jù)庫實例來達到負載均衡澈蚌。也許有人會說可以使用讀寫分離方案摹芙,但是因為ERP系統(tǒng)的特點,這個方案很多時候不現(xiàn)實宛瞄。比如說操作庫存的時候瘫辩,你不能從讀庫里讀庫存,然后在寫庫里寫入庫存坛悉。因為主從復制會有時效性伐厌,寫入的庫存并不能馬上寫入從庫。這樣的場景在ERP中也有多處裸影。何況寫庫不能擴展挣轨,只能有一個。而新設計方案是寫庫是分離的轩猩,每個子系統(tǒng)有自己的數(shù)據(jù)庫卷扮。

? ? ? ?其次,就是更新非常方便均践,各個子系統(tǒng)以后臺微服務的方式存在晤锹。前臺一個單獨的web項目,這個web項目調(diào)用后臺這些子系統(tǒng)的服務接口彤委。這樣的設計鞭铆,在某個業(yè)務子系統(tǒng)需要更新的時候,可以單獨更新焦影。不用像以前那種單進程架構時车遂,一個小更新需要整個系統(tǒng)重啟,導致用戶會話也丟失斯辰,用戶需要新登錄舶担。而現(xiàn)在的這種設計就不會有這個問題。

系統(tǒng)整體設計

? ? ? 系統(tǒng)物理部署視圖

詳細設計

? ?拆分應用層

? ? ? ? 拆分應用層彬呻,是踐行“微服務”架構的理念衣陶。將原來大而全的單進程架構按照業(yè)務模塊拆分成可獨立部署的應用程序,以此來達到平滑系統(tǒng)更新闸氮、升級剪况、方便負載擴展的目的。具體來說湖苞,技術上可以使用restfull風格的接口拯欧,也可以使用像java中dubbo框架方式來簡化開發(fā)復雜度详囤。ERPWeb端或其他移動端也是一個單獨的應用充當表現(xiàn)層财骨。非常薄镐作,只是簡單的接受參數(shù),調(diào)取后臺其他各種微服務程序的接口獲取所需展示的數(shù)據(jù)隆箩。微服務充當業(yè)務邏輯層该贾,每個微服務都是可獨立部署上線的程序,對外提供數(shù)據(jù)訪問接口捌臊。

? ? ? ? 微服務可以使用流行的各種RPC框架杨蛋,比如dubbo,可以支持多種調(diào)用協(xié)議Http理澎、TCP等逞力,這些框架使得編碼比較容易,框架封裝底層數(shù)據(jù)通信細節(jié)糠爬,使得客戶端執(zhí)行遠程方法如同執(zhí)行本地方法一樣簡單寇荧。

? ? ? ? dubbo微服務架構,還支持服務治理执隧,負載均衡等功能揩抡。這樣不僅可以提高系統(tǒng)的可用性,還能動態(tài)提升系統(tǒng)應用層的性能镀琉。比如倉庫管理中入庫業(yè)務非常繁忙峦嗤,占用非常多的CPU和內(nèi)存資源,我們可以另外加一臺機器屋摔,單獨再部署一個倉庫管理服務上去烁设。這樣使得整個系統(tǒng),有兩個倉庫管理服務在同時工作钓试,平衡負載署尤。而這一切都是在服務注冊中心,比如Zookeeper下自動完成的亚侠。

? ? ? ? 微服務結構曹体,天生很好的支持系統(tǒng)更新升級操作。比如財務模塊有個新需求需要上線硝烂,我們只需要替換財務模塊的服務重啟即可箕别。這對已經(jīng)登錄系統(tǒng)的用戶來說,沒有多少影響滞谢,不用重新登陸系統(tǒng)串稀,其他模塊服務使用也不受影響。

在此我向大家推薦一個架構學習交流群狮杨。交流學習群號:478030634 ?里面會分享一些資深架構師錄制的視頻錄像:有Spring母截,MyBatis,Netty源碼分析橄教,高并發(fā)清寇、高性能喘漏、分布式、微服務架構的原理华烟,JVM性能優(yōu)化翩迈、分布式架構等這些成為架構師必備的知識體系。還能領取免費的學習資源盔夜,目前受益良多

? ? 拆分數(shù)據(jù)層

? ? ? ? 數(shù)據(jù)庫瓶頸是ERP系統(tǒng)的永久原文之傷负饲。大量復雜的數(shù)據(jù)查詢表連接邏輯充斥著整個系統(tǒng)。數(shù)據(jù)庫垂直拆分成功的關鍵就是如何重新設計系統(tǒng)數(shù)據(jù)層各個模塊相互耦合的問題喂链。能解決這個問題返十,永久之傷便可以解決了。

我們先來看一個典型數(shù)據(jù)層模塊耦合問題椭微。需求是展示物料庫存吧慢,列表字段:物料編號、物料名稱赏表、品類检诗、倉庫、數(shù)量

物料表:

庫存表:


品類和倉庫表省略瓢剿。逢慌。。

? ? ? ? 很顯然间狂,傳統(tǒng)一個數(shù)據(jù)庫中攻泼,我們只需要簡單的join操作,即可關聯(lián)這兩張表鉴象,外加關聯(lián)品類和倉庫表即可查詢出我們所要的數(shù)據(jù)忙菠。但是現(xiàn)在我們的架構中,物料表和商品表不在同一個數(shù)據(jù)庫實例中纺弊,我們不能使用join操作了牛欢,那我們該怎么實現(xiàn)需求呢?

? ? ? ? 新的架構淆游,只允許我們通過對方的服務接口來獲取數(shù)據(jù)傍睹,不能直接關聯(lián)對方服務的私有數(shù)據(jù)庫。至少從架構上犹菱,服務化角度來說不能直接訪問對方服務的數(shù)據(jù)庫拾稳。這種情況下,假設web模塊子系統(tǒng)調(diào)用倉庫子系統(tǒng)來獲取數(shù)據(jù)腊脱,則我們需要在倉庫模塊中創(chuàng)建一個service方法來裝配這些數(shù)據(jù)访得。然后返回給web子系統(tǒng)。如下圖所示陕凹,倉庫管理方法首先獲取本地庫存表的物料編碼悍抑、和倉庫表的倉庫名稱字段信息鳄炉,并且分頁完后最終準備返回20條數(shù)據(jù)到Web模塊前,將這20條數(shù)據(jù)中的物料ID作為參數(shù)請求商品模塊子系統(tǒng)传趾,商品子系統(tǒng)返回這20個物料ID相關的商品信息給到倉庫管理模塊,然后倉庫管理模塊重新組裝上列表所需的物料名稱和品類兩個字段數(shù)據(jù)泥技,實現(xiàn)最終要返回給Web子系統(tǒng)的數(shù)據(jù)浆兰。

? ? ? ? 也許你會說,這太麻煩了珊豹,這種方法的性能肯定沒有直接join來的高簸呈,解決不了性能問題。咋看起來好像是這么回事店茶,但是仔細考慮看看蜕便,在系統(tǒng)并發(fā)量低、數(shù)據(jù)量小贩幻、業(yè)務不算繁忙的環(huán)境下轿腺,的確性能還不如傳統(tǒng)一個數(shù)據(jù)中join方式來的快速。但我們想想以后吧丛楚!我們現(xiàn)在的架構設計是將一個數(shù)據(jù)庫拆成多個數(shù)據(jù)庫族壳,每個數(shù)據(jù)庫可以運行在單獨的服務器上去,這樣以后就能負載數(shù)據(jù)庫的壓力了趣些。整體來說這樣才能不會讓數(shù)據(jù)庫成為未來業(yè)務繁忙時候的性能瓶頸了仿荆。想想都覺得讓人興奮不已,是不是坏平?

? ? ? ?這時候有人又會問拢操,那以后系統(tǒng)數(shù)據(jù)量、業(yè)務更大了舶替,連你這個拆分成幾個數(shù)據(jù)庫還不夠用怎么辦呢令境?我的方法是,可以基于拆分的數(shù)據(jù)庫顾瞪,單獨每個庫可以做讀寫分離展父、使用緩存等。甚至可以繼續(xù)拆分下去玲昧,將子系統(tǒng)再次拆分成多個孫子系統(tǒng)栖茉。視業(yè)務模塊繁忙程度而定。

報表系統(tǒng)

? ? ? ? 有人又會問孵延,有些列表查詢邏輯非常復雜吕漂,關聯(lián)十多張表,如果按上述方法拆分數(shù)據(jù)尘应,那簡直是災難盎棠吼虎!是的,你說的沒有錯苍鲜。這種情況下我的方案是將這種更加復雜的報表級別的數(shù)據(jù)查詢展示需求思灰,可以單獨做個報表系統(tǒng)。報表數(shù)據(jù)庫設計采用數(shù)據(jù)倉庫方式混滔。為了更高的讀取性能洒疚,我們可以將數(shù)據(jù)庫表設計成很多冗余字段方式也就是反范式設計,以及建立非常多的組合索引坯屿。

? ? ? ?這種系統(tǒng)成功的關鍵就是數(shù)據(jù)和主ERP系統(tǒng)業(yè)務庫的同步問題了油湖。一般可以寫一個定時同步程序,將ERP主業(yè)務系統(tǒng)的數(shù)據(jù)經(jīng)過帥選领跛、轉化等方式直接生成報表視圖所需的最終或中間數(shù)據(jù)乏德,簡化關聯(lián)查詢。報表系統(tǒng)也可以采用微服務架構設計吠昭。如下圖所示:

? ? ? ? 如果報表所需的數(shù)據(jù)要求實時的喊括,我們可以讓ERP系統(tǒng)業(yè)務操作時,觸發(fā)同步數(shù)據(jù)的請求矢棚,實時同步至報表庫瘾晃。

分布式事務

? ? ? ?也許有人又又問了,ERP系統(tǒng)很多操作都要求事務性幻妓,你拆分系統(tǒng)后怎么實現(xiàn)事務性蹦误,保障數(shù)據(jù)一致性呢?

這個問題很好肉津,也是我決定寫這篇文章前思考的最后一個問題强胰。在微服務架構中,實現(xiàn)夸服務的事務并不容易妹沙,至少不像本地應用使用本地數(shù)據(jù)庫事務那樣方便偶洋,性能高效,數(shù)據(jù)一致性好距糖。

? ? ? ? 也許你聽過分布式事務這個概念玄窝。有兩種情景,一種是一個應用中使用多個數(shù)據(jù)庫悍引,為保障數(shù)據(jù)一致性恩脂,需要使用分布式事務。還有一種情況就是針對我們這個架構而言的趣斤。微服務環(huán)境下的分布式事務俩块,具體來說打個比方。采購入庫這個操作設計在倉庫管理服務中。入庫后玉凯,需要更新采購子系統(tǒng)中的采購單中的入庫數(shù)量势腮。這個過程要求數(shù)據(jù)一致性,也就是采購單入庫成功后寫入了庫存表中的數(shù)量漫仆,同時要更新采購單表中的入庫數(shù)量捎拯。我們不能直接在倉庫服務中去訪問采購服務中的數(shù)據(jù)庫,必須通過采購服務提供的服務接口才行盲厌。如果這樣署照,我們怎么能保證數(shù)據(jù)一致性呢?因為很有可能庫存表寫入成功狸眼,但調(diào)取采購服務寫入采購單數(shù)據(jù)時失敗了藤树≡〉危可能是網(wǎng)絡問題原因?qū)е碌耐孛龋@樣數(shù)據(jù)就不一致了。

? ? ? ?在分布式事務技術中升略,有實現(xiàn)最終一致性這么一說微王,意思就是只要我能保證兩邊數(shù)據(jù)最終實現(xiàn)了一致性就行,不一定要使用事務品嚣。這樣說來就有方案了炕倘。如倉庫子系統(tǒng)在處理采購入庫時需要增加入庫單數(shù)據(jù)和更新庫存數(shù)據(jù)等多個表。這多個表都在倉庫子系統(tǒng)中翰撑,我們可以使用一個本地事務來保證倉庫子系統(tǒng)中的表數(shù)據(jù)一致性罩旋。然后調(diào)用采購子系統(tǒng)更新采購單里的入庫數(shù)量。為了防止這個過程突然中斷導致調(diào)用失敗眶诈,我們考慮增加一個消息隊列中間件如ActiveMQ涨醋。如果接口返回失敗我們就往MQ里寫入這個處理請求,等到采購子系統(tǒng)恢復正常后逝撬,MQ通知采購子系統(tǒng)處理這個更新操作浴骂。由于消息消費掉以后不會再有通知了,采購子系統(tǒng)處理過程中發(fā)生異常導致更新失敗宪潮,需要將問題寫入本地的日志庫溯警,以便通知管理員做后續(xù)補償處理。就這樣通過各種辦法來達到數(shù)據(jù)的最終一致性即可狡相。雖然聽上去有點坑梯轻,但這就是解決方案。沒有其他更好的了尽棕¢萘埽或者更新失敗后重新調(diào)用倉庫子系統(tǒng)回滾入庫單和庫存數(shù)據(jù),達到最終一致性!如圖所示:

? ? ? ?非常有幸能和大家一起分享知識和經(jīng)驗蟀悦,正是由于大家的無私分享媚朦,才讓我們得以成長和進步,我最近幾年來都很少分享東西日戈,有時候是因為工作很忙沒有時間寫點東西询张,有時候也是因為自己懶或是沒有什么新東西可以分享給大家的。最后也希望大家對我的分享不足之處給予批評指正浙炼,一起進步份氧!

在此我向大家推薦一個架構學習交流群。交流學習群號:478030634 ?里面會分享一些資深架構師錄制的視頻錄像:有Spring弯屈,MyBatis蜗帜,Netty源碼分析,高并發(fā)资厉、高性能厅缺、分布式、微服務架構的原理宴偿,JVM性能優(yōu)化湘捎、分布式架構等這些成為架構師必備的知識體系。還能領取免費的學習資源窄刘,目前受益良多

大家覺得文章對你還是有一點點幫助的窥妇,大家可以點擊下方二維碼進行關注∶浼《Java爛豬皮》公眾號聊的不僅僅是Java技術知識活翩,還有面試等干貨,后期還有大量架構干貨翻伺。大家一起關注吧材泄!關注爛豬皮,你會了解的更多..............


原文連接:https://www.cnblogs.com/liuche/p/7955462.html

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末穆趴,一起剝皮案震驚了整個濱河市脸爱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌未妹,老刑警劉巖簿废,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異络它,居然都是意外死亡族檬,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門化戳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來单料,“玉大人埋凯,你說我怎么就攤上這事∩猓” “怎么了白对?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長换怖。 經(jīng)常有香客問我甩恼,道長,這世上最難降的妖魔是什么沉颂? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任条摸,我火速辦了婚禮,結果婚禮上铸屉,老公的妹妹穿的比我還像新娘钉蒲。我一直安慰自己,他們只是感情好彻坛,可當我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布顷啼。 她就那樣靜靜地躺著,像睡著了一般小压。 火紅的嫁衣襯著肌膚如雪线梗。 梳的紋絲不亂的頭發(fā)上椰于,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天,我揣著相機與錄音,去河邊找鬼嫩码。 笑死向拆,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的偏陪。 我是一名探鬼主播抢呆,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼笛谦!你這毒婦竟也來了抱虐?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤饥脑,失蹤者是張志新(化名)和其女友劉穎恳邀,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體灶轰,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡谣沸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了笋颤。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片乳附。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出赋除,到底是詐尸還是另有隱情阱缓,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布举农,位于F島的核電站茬祷,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏并蝗。R本人自食惡果不足惜祭犯,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望滚停。 院中可真熱鬧沃粗,春花似錦、人聲如沸键畴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽起惕。三九已至涡贱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間惹想,已是汗流浹背问词。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留嘀粱,地道東北人激挪。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像锋叨,于是被迫代替她去往敵國和親垄分。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,843評論 2 354

推薦閱讀更多精彩內(nèi)容