日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

電商真實對賬系統是如何設計并優化的

來源: 責編: 時間:2024-04-19 09:26:31 217觀看
導讀前言往期文章在熱點數據如何更新的一篇文章中有提到對賬系統。其實我在實際業務場景中是有遇到過類似對賬的優化問題的。說優化之前要掌握一點就是一定要掌握Java并發包的相關特性。本章節對此有很大依賴。熱點數據高

前言

往期文章在熱點數據如何更新的一篇文章中有提到對賬系統。其實我在實際業務場景中是有遇到過類似對賬的優化問題的。說優化之前要掌握一點就是一定要掌握Java并發包的相關特性。本章節對此有很大依賴。bqF28資訊網——每日最新資訊28at.com

  • 熱點數據高效更新文章:

inventory hint,解決熱點數據如何高效更新bqF28資訊網——每日最新資訊28at.com

Java并發包簡說

CountDownLatch和CyclicBarrier

區別

CountDownLatch:bqF28資訊網——每日最新資訊28at.com

  • 不可以重復使用,計數器無法被重置

經典案例比如門衛休息休要等所有人下班才可以關門休息 CyclicBarrier:bqF28資訊網——每日最新資訊28at.com

  • 可以重復使用,是一個同步輔助類,允許一組線程相互等待,直到到達某個公共屏障點(common barrier point)。假設設計一組固定大小的線程的程序中,這些線程必須不是的互相等待,此時就可以使用CyclicBarrier。因為該barrier在釋放等待線程后可以重用,從而稱之為循環的barrier。

經典案例:比如運動員跑步,需要所有人準備好之后裁判才可以發令讓大家在同一時刻去跑。有依賴關系bqF28資訊網——每日最新資訊28at.com

案例

有一天,老大匆忙趕來,提到對賬系統最近變得越來越緩慢,希望能迅速進行優化。經過了解對賬系統的業務流程,發現其實相當簡單:用戶通過在線商城下單會生成電子訂單并存儲在訂單數據庫中;隨后物流會生成派送單用于發貨,派送單則保存在派送單庫中。為了避免漏發或重復派送,對賬系統每天會核查是否存在異常訂單。bqF28資訊網——每日最新資訊28at.com

目前對賬系統的處理邏輯很簡單:首先查詢訂單,然后查詢派送單,接著比對訂單和派送單,將差異記錄寫入差異庫。對賬系統的核心代碼經過抽象后,也并不復雜,主要是在單線程中循環執行訂單和派送單的查詢,進行對賬操作,最后將結果寫入差異庫。bqF28資訊網——每日最新資訊28at.com

偽代碼

while(存在未對賬訂單){  // 查詢未對賬訂單  pos = getPOrders();  // 查詢派送單  dos = getDOrders();  // 執行對賬操作  diff = check(pos, dos);  // 差異寫入差異庫  save(diff);}

利用Java并行優化對賬系統

首先要找出對賬系統的瓶頸所在。目前,由于訂單量和派送單量龐大,導致查詢未對賬訂單 getPOrders() 和查詢派送單 getDOrders() 的速度較慢。是否有一種快速優化的方法呢?目前對賬系統是單線程執行的。對于這樣的串行系統,優化性能的第一個想法是能否利用多線程并行處理。bqF28資訊網——每日最新資訊28at.com

因此,我們可以看出對賬系統的瓶頸在哪里:查詢未對賬訂單 getPOrders() 和查詢派送單 getDOrders() 是否能夠并行處理呢?很顯然,這兩個操作之間并沒有依賴關系。將這兩個耗時操作并行化后,與單線程執行相比,您會發現在相同時間段內,并行執行的吞吐量接近單線程的兩倍,優化效果頗為明顯。bqF28資訊網——每日最新資訊28at.com

有了這個思路,接下來我們看看如何用代碼實現。在下面的代碼中,我們創建了兩個線程 T1 和 T2,分別并行執行查詢未對賬訂單 getPOrders() 和查詢派送單 getDOrders() 的操作。主線程則負責執行對賬操作 check()和將差異寫入 save() 的操作。值得注意的是:主線程需要等待線程 T1 和 T2 執行完畢后才能執行 check() 和 save() 這兩個操作。為此,我們通過調用 T1.join() 和 T2.join() 實現等待,當線程 T1 和 T2 結束時,調用了 T1.join() 和 T2.join() 的主線程將從阻塞狀態中解除,隨后執行后續的 check() 和 save() 操作。bqF28資訊網——每日最新資訊28at.com

偽代碼

while(存在未對賬訂單){  // 查詢未對賬訂單  Thread T1 = new Thread(()->{    pos = getPOrders();  });  T1.start();  // 查詢派送單  Thread T2 = new Thread(()->{    dos = getDOrders();  });  T2.start();  // 等待 T1、T2 結束  T1.join();  T2.join();  // 執行對賬操作  diff = check(pos, dos);  // 差異寫入差異庫  save(diff);}

用 CountDownLatch 實現線程等待

經過上述優化,基本上可以向老板報告工作完成了,但仍有一些遺憾之處。我相信您也已經注意到了,在 while 循環中每次都會創建新的線程,而創建線程是一個耗時的操作。因此,最好能夠重復利用已創建的線程。您想到了線程池,確實,線程池能夠解決這個問題。bqF28資訊網——每日最新資訊28at.com

通過線程池進行優化后:我們首先創建了一個固定大小為2的線程池,并在 while 循環中重復利用這些線程。一切看起來都進行得很順利,但似乎有一個問題無法解決,即主線程如何知道 getPOrders() 和 getDOrders() 這兩個操作何時執行完成。在前面的方案中,主線程通過調用線程 T1 和 T2 的 join() 方法來等待它們退出,但是在線程池方案中,線程根本就不會退出,因此 join() 方法失效了。bqF28資訊網——每日最新資訊28at.com

那么,如何解決這個問題呢?您可以想出許多方法,其中最直接的方法是使用一個計數器。將其初始值設為2,執行完 pos = getPOrders(); 后減 1,執行完 dos = getDOrders(); 后也減 1。主線程在這之后等待計數器等于0;當計數器等于0時,說明這兩個查詢操作已執行完畢。等待計數器為0實際上是一種條件變量,使用管程實現起來也并不復雜。bqF28資訊網——每日最新資訊28at.com

然而,我并不建議在實際項目中實施上述方案,因為Java并發包中已經提供了類似功能的工具類:CountDownLatch,我們直接使用即可。在下面的代碼示例中,我們在 while 循環中首先創建了一個CountDownLatch,計數器的初始值為2。在 pos = getPOrders(); 和 dos = getDOrders(); 兩個語句后,通過調用 latch.countDown(); 實現對計數器的減1操作。在主線程中,通過調用 latch.await(); 實現對計數器等于0的等待。bqF28資訊網——每日最新資訊28at.com

偽代碼

// 創建 2 個線程的線程池Executor executor =   Executors.newFixedThreadPool(2);while(存在未對賬訂單){  // 計數器初始化為 2  CountDownLatch latch =     new CountDownLatch(2);  // 查詢未對賬訂單  executor.execute(()-> {    pos = getPOrders();    latch.countDown();  });  // 查詢派送單  executor.execute(()-> {    dos = getDOrders();    latch.countDown();  });    // 等待兩個查詢操作結束  latch.await();    // 執行對賬操作  diff = check(pos, dos);  // 差異寫入差異庫  save(diff);}

進一步優化性能

經過以上一系列的優化,終于可以松一口氣,準備交付項目。然而,在交付之前,再次審視一番是值得的,或許還存在優化的空間。bqF28資訊網——每日最新資訊28at.com

前面我們已經實現了將 getPOrders() 和 getDOrders() 這兩個查詢操作并行化,但是這兩個查詢操作與對賬操作 check() 和 save() 之間仍然是串行執行的。很顯然,這兩個查詢操作與對賬操作也可以并行執行,即在執行對賬操作的同時可以進行下一輪的查詢操作。bqF28資訊網——每日最新資訊28at.com

接下來,我們再思考如何實現這一優化。兩次查詢操作能夠與對賬操作并行執行,而對賬操作又依賴于查詢操作的結果,這明顯具有生產者-消費者模型的特征。兩次查詢操作充當生產者,對賬操作為消費者。為了實現這種模型,我們需要一個隊列來存儲生產者產生的數據,消費者則從隊列中取出數據執行相應操作。bqF28資訊網——每日最新資訊28at.com

針對這個對賬項目,我設計了兩個隊列,其元素之間存在對應關系。具體來說,訂單查詢操作將訂單查詢結果插入訂單隊列,派送單查詢操作將派送單插入派送單隊列,這兩個隊列的元素之間是一一對應的。使用兩個隊列的好處在于,對賬操作可以每次從訂單隊列取出一個元素和派送單隊列中取出一個元素,然后執行對賬操作,確保數據的一致性。bqF28資訊網——每日最新資訊28at.com

接下來,讓我們看看如何通過雙隊列實現完全并行化。一個直接的思路是:一個線程 T1 執行訂單查詢工作,另一個線程 T2 執行派送單查詢工作。當線程 T1 和 T2 都各自生產完一條數據時,通知線程 T3 執行對賬操作。這一想法看似簡單,實際上仍然存在一個條件:T1 和 T2 的工作節奏必須一致,保持同步,否則一個快一個慢將影響各自生產數據并通知 T3 的過程。bqF28資訊網——每日最新資訊28at.com

只有在T1和T2各自生產完一條數據時才能繼續執行,也就是說,T1和T2需要相互等待,保持步調一致。同時,當T1和T2都生產完一條數據時,還需能夠通知T3執行對賬操作。bqF28資訊網——每日最新資訊28at.com

用 CyclicBarrier 實現線程同步

接下來我們將實現上述方案中提到的方法。該方案的難點在于兩個方面:一是確保線程 T1 和 T2 的步調一致,二是能夠有效通知線程 T3。bqF28資訊網——每日最新資訊28at.com

在解決這兩個難點的過程中,仍然可以利用一個計數器。將計數器初始化為2,每當線程 T1 和 T2 生產完一條數據時,都將計數器減1。若計數器大于0,則線程 T1 或 T2需要等待。當計數器等于0時,通知線程 T3,喚醒等待的線程 T1 或 T2,并將計數器重置為2。如此,線程 T1 和 T2 在生產下一條數據時,可以繼續使用這個計數器。bqF28資訊網——每日最新資訊28at.com

建議不要在實際項目中直接實現這一邏輯,因為Java并發包中已經提供了相關的工具類:CyclicBarrier。在下面的代碼中,我們首先創建了一個初始值為2的CyclicBarrier計數器。需要注意的是,在創建CyclicBarrier時,傳入了一個回調函數。當計數器減至0時,該回調函數會被調用。bqF28資訊網——每日最新資訊28at.com

線程 T1 負責查詢訂單,每查到一條數據,調用barrier.await()將計數器減1,并等待計數器變為0。線程 T2  負責查詢派送單,處理方式與線程 T1 類似。當 T1 和 T2 都調用barrier.await()時,計數器會減至0,此時 T1 和 T2可以繼續執行下一步操作,并調用barrier的回調函數執行對賬操作。bqF28資訊網——每日最新資訊28at.com

值得一提的是,CyclicBarrier的計數器具有自動重置功能。當計數器減至0時,會自動重新設定為您設置的初始值。這一特性確實方便實用。bqF28資訊網——每日最新資訊28at.com

偽代碼

// 訂單隊列Vector<P> pos;// 派送單隊列Vector<D> dos;// 執行回調的線程池 Executor executor =   Executors.newFixedThreadPool(1);final CyclicBarrier barrier =  new CyclicBarrier(2, ()->{    executor.execute(()->check());  });  void check(){  P p = pos.remove(0);  D d = dos.remove(0);  // 執行對賬操作  diff = check(p, d);  // 差異寫入差異庫  save(diff);}  void checkAll(){  // 循環查詢訂單庫  Thread T1 = new Thread(()->{    while(存在未對賬訂單){      // 查詢訂單庫      pos.add(getPOrders());      // 等待      barrier.await();    }  });  T1.start();    // 循環查詢運單庫  Thread T2 = new Thread(()->{    while(存在未對賬訂單){      // 查詢運單庫      dos.add(getDOrders());      // 等待      barrier.await();    }  });  T2.start();}

CountDownLatch 和 CyclicBarrier 是Java并發包提供的兩個非常便捷的線程同步工具類。在這里,有必要再次強調它們之間的區別:CountDownLatch 主要用于解決一個線程等待多個線程的情況,可以類比于旅游團團長必須等待所有游客齊集后才能繼續前行;而CyclicBarrier 則是一組線程相互等待,有點像幾個驢友之間的互助合作。此外,CountDownLatch 的計數器不支持重復利用,即一旦計數器降至0,后續調用await()的線程將直接通過。相比之下,CyclicBarrier 的計數器可以循環利用,同時具有自動重置功能,一旦計數器減至0,將會自動重置為設定的初始值。此外,CyclicBarrier 還支持設置回調函數,功能更加豐富。bqF28資訊網——每日最新資訊28at.com

本文鏈接:http://m.www897cc.com/showinfo-26-84007-0.html電商真實對賬系統是如何設計并優化的

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: CompletableFuture:Java 8 中的異步編程利器

下一篇: Electron 30 正式發布,新特性詳解

標簽:
  • 熱門焦點
Top 日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不
国产女主播一区二区三区| 欧美日韩精品一二三区| 亚洲午夜三级在线| 国产欧美日本在线| 美日韩精品视频免费看| 一区二区三区视频在线| 国产日韩一区二区三区在线| 亚洲国产成人av| 欧美另类综合| 亚洲一区综合| 国产免费成人| 男女激情久久| 欧美一区1区三区3区公司| 国产一区视频观看| 国产主播一区| 国产又爽又黄的激情精品视频| 99精品视频一区二区三区| 国产精品xvideos88| 亚洲黄色在线观看| 欧美日韩国内自拍| 国产一区深夜福利| 欧美日韩国产一中文字不卡 | 亚洲啪啪91| 久久偷看各类wc女厕嘘嘘偷窃| 欧美日韩视频一区二区| 影音先锋日韩资源| 在线播放日韩专区| 尤物99国产成人精品视频| 欧美激情综合亚洲一二区 | 亚洲午夜影视影院在线观看| 亚洲精品影视| 日韩网站在线| 一区二区三区偷拍| 久久人人看视频| 久久久久久久久久久久久久一区| 久久成人久久爱| 欧美中文字幕第一页| 欧美精品一线| 欧美日韩国产精品一区| 欧美日韩一区二区欧美激情| 欧美三区在线观看| 在线日韩日本国产亚洲| 亚洲在线成人| 午夜精彩国产免费不卡不顿大片| 亚洲女人av| 欧美电影在线播放| 欧美日韩一级视频| 欧美亚一区二区| 国产精品久久| 国产精品网站在线观看| 国产精品亚洲а∨天堂免在线| 国产日韩欧美视频| 在线成人中文字幕| 亚洲欧美精品| 久久精品国产精品亚洲综合| 欧美在线免费看| 模特精品在线| 欧美日韩免费看| 亚洲国产欧美一区二区三区丁香婷| 香蕉精品999视频一区二区 | 亚洲欧美日韩国产一区二区三区| 先锋资源久久| 欧美先锋影音| 国内精品免费午夜毛片| 在线观看亚洲a| 久久精品国语| 欧美人与禽猛交乱配| 欧美色欧美亚洲另类七区| 国产日韩欧美另类| 午夜激情一区| 欧美 日韩 国产 一区| 国内精品伊人久久久久av影院| 亚洲欧美激情一区二区| 国产精品v欧美精品v日韩精品| 韩国免费一区| 欧美与欧洲交xxxx免费观看| 美乳少妇欧美精品| 国产精品草莓在线免费观看| 日韩午夜在线视频| 国产欧美一区二区三区沐欲 | 日韩亚洲一区在线播放| 欧美激情一区二区三级高清视频| 欧美日韩中文字幕精品| 亚洲人成毛片在线播放女女| 亚洲女优在线| 国产精品美女久久久免费| 亚洲韩国日本中文字幕| 亚洲在线成人精品| 国产精品美女主播在线观看纯欲| 国产亚洲观看| 先锋a资源在线看亚洲| 国产美女扒开尿口久久久| 性色一区二区| 欧美日韩一区二区三| 99国内精品| 久久精品五月| 国产精品乱人伦一区二区| 亚洲视频在线观看网站| 免费久久99精品国产自| 亚洲高清资源| 欧美在线资源| 国内精品久久久久影院色 | 久久成人久久爱| 国产精品国产三级国产普通话99 | 午夜精彩视频在线观看不卡| 国产性天天综合网| 久久综合网hezyo| 国产欧美日韩一级| 久久久久久久综合日本| 国产精品一区2区| 久久本道综合色狠狠五月| 精品88久久久久88久久久| 欧美资源在线观看| 好看的av在线不卡观看| 欧美成人a视频| 在线播放日韩| 欧美激情一区二区三区高清视频| 国内精品美女在线观看| 久热爱精品视频线路一| 国产在线观看精品一区二区三区| 久久亚洲春色中文字幕| 国产亚洲精品7777| 午夜精品理论片| 免费在线国产精品| 一个人看的www久久| 欧美日韩1区2区| 亚洲欧美精品suv| 永久免费毛片在线播放不卡| 欧美日韩国产色综合一二三四| 亚洲欧美精品伊人久久| **欧美日韩vr在线| 欧美日韩一区国产| 久久九九电影| 日韩一级黄色片| 国产综合视频| 欧美日本三区| 欧美中文在线观看| 亚洲精品日韩在线| 国产欧美精品一区二区三区介绍| 老巨人导航500精品| 亚洲福利视频二区| 国产精品高潮呻吟久久| 亚洲一区二区三区四区五区黄 | 国产精品视频免费| 亚洲高清不卡在线| 国产精品久久久一区二区| 久久手机免费观看| 亚洲视频在线观看三级| 在线看片日韩| 国产精品一区二区a| 欧美精品成人一区二区在线观看| 欧美一级理论片| av成人激情| 欧美日韩一区在线观看| 久久精品亚洲乱码伦伦中文| 日韩一区二区精品在线观看| 国内精品伊人久久久久av影院| 欧美私人啪啪vps| 免费亚洲婷婷| 欧美影片第一页| 红桃视频一区| 欧美aⅴ一区二区三区视频| 亚洲欧美激情一区二区| 最新日韩中文字幕| 狠狠88综合久久久久综合网| 国产精品久久久久久妇女6080 | 国产女优一区| 欧美三级在线视频| 欧美精品国产| 久久综合九色综合欧美狠狠| 午夜免费日韩视频| 在线播放豆国产99亚洲| 国产精品视频1区| 久久久久久穴| 亚洲专区一二三| 日韩一级大片| 91久久久久久国产精品| 黑人一区二区| 国产亚洲成年网址在线观看| 国产精品久久久对白| 欧美日韩另类一区| 欧美激情国产日韩精品一区18| 久久影视精品| 久久久青草婷婷精品综合日韩| 欧美一区二区视频在线| 亚洲免费在线观看| 亚洲视频在线播放| 亚洲视频一区二区| 一区二区三区四区五区精品视频| 国产精品一二一区| 欧美午夜不卡影院在线观看完整版免费| 免费成人黄色| 亚洲一区一卡| 亚洲视频中文| 亚洲手机在线| 亚洲影院免费观看| 亚洲一区影院| 亚洲电影天堂av| 黄色成人精品网站| 欧美粗暴jizz性欧美20| 亚洲欧美区自拍先锋| 亚洲香蕉网站| 亚洲视频自拍偷拍| 亚洲高清毛片|