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

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

麻了,這讓人絕望的大事務提交

來源: 責編: 時間:2024-01-15 09:20:19 230觀看
導讀一、背景繼上次的if else優化也有段時間了,最近小貓又又又著道了,接手的那個項目又遇到了坑爹的地方,經常性的報死鎖異常,經常性的主從延遲......通過報錯信息按圖索驥,發現代碼是這樣的。這是一段商品發布的邏輯,我們可以

一、背景

繼上次的if else優化也有段時間了,最近小貓又又又著道了,接手的那個項目又遇到了坑爹的地方,經常性的報死鎖異常,經常性的主從延遲......通過報錯信息按圖索驥,發現代碼是這樣的。nJs28資訊網——每日最新資訊28at.com

nJs28資訊網——每日最新資訊28at.com

nJs28資訊網——每日最新資訊28at.com

這是一段商品發布的邏輯,我們可以看到參數校驗、查詢、最終的insert以及update全部揉在一個事務中。遇到批量發布商品的時候就經常出現問題了,數據庫主從延遲是肯定少不了的。nJs28資訊網——每日最新資訊28at.com

二、開啟優化

其實像上述小貓遇到的這種狀況我們就稱其為大事務,那么我們就大概有這么一個定義。我們將執行時間長,并且操作數據比較多的事務叫做大事務。nJs28資訊網——每日最新資訊28at.com

1.大事務產生的原因

在我們日常開發過程中,其實經常會遇到大事務,老貓總結了一下,往往原因其實總結下來有這么幾點(當然存在紕漏的地方,也歡迎大家評論區留言補充):nJs28資訊網——每日最新資訊28at.com

  • 一次性操作的數據量確實多,大量的鎖競爭,比如批量操作這種行為。
  • 事務粒度過大,代碼中的 @Transactional使用不當,其他非DB操作比較多,耗時久。比如調用RPC接口,在例如上述小貓遇到的check邏輯甚至都揉在一起等等。

2.造成的影響

那么大事務造成的影響又是什么呢?nJs28資訊網——每日最新資訊28at.com

從開發者的角度來看的話,部分大事務必定對應的復雜的業務邏輯,代碼封裝事務拆解不合理,研發側維護困難,維護成本高。nJs28資訊網——每日最新資訊28at.com

從最終系統以及運維角度來看:nJs28資訊網——每日最新資訊28at.com

  • 出現了死鎖。
  • 造成了主從延遲。
  • 大事務消耗更多的磁盤空間,回滾成本高。
  • 大事務發生的過程中,由于連接池持續被打開,很容易造成數據庫連接池被沾滿。
  • 接口響應慢導致接口超時,甚至導致服務不可用等等 (歡迎大家補充)

3.優化方案

大事務既然有這么多坑,那么我們來看一下我們日常開發過程中,應該如何做到盡量規避呢?老貓整理了以下幾種優化方法。nJs28資訊網——每日最新資訊28at.com

a.降低事務顆粒度,大事務拆解小事務:nJs28資訊網——每日最新資訊28at.com

  • 編程式事務代替@Transactional。
  • 非update以及insert動作外移。

b.大數據量一次性提交盡可能拆解分批處理。nJs28資訊網——每日最新資訊28at.com

c.拆解原始事務,異步化處理。nJs28資訊網——每日最新資訊28at.com

(1) 降低事務顆粒度

1、我們對@Transactional的事務粒度把控不好,有時候如果使用不當的話事務功能可能會失效,如果經驗不足,很難排查,那么我們不如直接使用粗細粒度更好把控的編程式事務。TransactionTemplate。這樣的話咱們的優化代碼就可以寫好才能如下方式。nJs28資訊網——每日最新資訊28at.com

@Autowiredprivate TransactionTemplate transactionTemplate;public boolean publishProduct(PublishProductRequest request) {        externalSellerAuthorizeService.checkAuthorizeValid(request.getSellerId(),request.getThirdCategoryId(),request.getBrandId());        ......        transactionTemplate.execute((status) -> {            try{                //執行insert                productDao.insert(productDO);                productDescDao.insert(productDescDO);                ....                //其他insert以及update操作            }catch (Exception e) {                //回滾                status.setRollbackOnly();                return true;            }            return false;        });        return true;    }

非update以及insert動作外移。nJs28資訊網——每日最新資訊28at.com

原始代碼:nJs28資訊網——每日最新資訊28at.com

@Transactional(rollbackFor=Exception.class)   public void save(Req req) {         checkParam(req);         saveData1(req);         updateData2(req);   }   private void checkParam(Req req){       Data1 data = selectData1();       Data2 data2 = selectData2();       if(data.getSomeThing() != STATUS_YES){          throw new BusinessTimeException(.....);       }   }

然后部分小伙伴就覺得外移么,如果不用@Transactional的情況,那直接這樣不就行了么。nJs28資訊網——每日最新資訊28at.com

錯誤改造案例:nJs28資訊網——每日最新資訊28at.com

class ServiceAImpl implements ServiceA {  @Transactional(rollbackFor=Exception.class)   public void save(Req req) {         saveData1(req);         updateData2(req);   }   private void checkParam(Req req){       Data1 data = selectData1();       Data2 data2 = selectData2();       if(data.getSomeThing() != STATUS_YES){          throw new BusinessTimeException(.....);       }   } public void save(Req req){    checkParam(req);    doSave(req); }}

這個例子是非常經典的錯誤,這種直接方法調用的做法事務不會生效,老貓以前也踩過這樣的坑。因為 @Transactional 注解的聲明式事務是通過 spring aop 起作用的, 而 spring aop 需要生成代理對象,直接方法調用使用的還是原始對象,所以事務不會生效。那么我們應該如何改造呢?我們看下正確的改造。nJs28資訊網——每日最新資訊28at.com

正確改造方案1,當然還是利用上面的TransactionTemplate:nJs28資訊網——每日最新資訊28at.com

  @Autowired  private TransactionTemplate transactionTemplate;   public void save(Req req) {         checkParam(req);         transactionTemplate.execute((status) -> {            try{                saveData1(req);                updateData2(req);                ....                //其他insert以及update操作            }catch (Exception e) {                //回滾                status.setRollbackOnly();                return true;            }            return false;        });   }   private void checkParam(Req req){       Data1 data = selectData1();       Data2 data2 = selectData2();       if(data.getSomeThing() != STATUS_YES){          throw new BusinessTimeException(.....);       }   }

正確改造方案2,把 @Transactional 注解加到新Service方法上,把需要事務執行的代碼移到新方法中。nJs28資訊網——每日最新資訊28at.com

  @Servcie  public class ServiceA {     @Autowired     private ServiceB serviceB;     private void checkParam(Req req){       Data1 data = selectData1();       Data2 data2 = selectData2();       if(data.getSomeThing() != STATUS_YES){          throw new BusinessTimeException(.....);       }   }    public void save(Req req) {          checkParam(req);          serviceB.save(req);    }  }   @Servcie   public class ServiceB {      @Transactional(rollbackFor=Exception.class)      public void save(Req req) {         saveData1(req);         updateData2(req);      }   }

正確改造方案3:將ServiceA 再次注入到自身(老貓覺得這種方式不優雅,不太推薦,這里就不寫了)nJs28資訊網——每日最新資訊28at.com

(2) 大數據量一次性提交盡可能拆解分批處理

我們再來看大數量批量請求的場景,咱們具體來分析一下,假設上游系統存在一個批量導入2w的數據操作。如果我們讀取到上游導入的數據,并且直接執行DB一次性執行肯定是不合適的。這種情況就需要我們對其請求的數據量做一個拆解。我們可以采用Lists.partition等等方式將數據拆成多個小的批量然后再進行入庫操作處理。nJs28資訊網——每日最新資訊28at.com

@Servciepublic class ServiceA {  @Autowired  private ServiceB serviceB;  private void batchAdd(List<Long> inventorySkuIdList){      List<List<Long>> partition = Lists.partition(inventorySkuIdList, 1000);        for (List<Long> idList : partition) {            List<InventorySkuDO> inventorySkuDOList = inventorySkuDao.selectByIdList(idList, null);            if (CollectionUtils.isNotEmpty(inventorySkuDOList)) {               serviceB.doInsertUpdate(inventorySkuDOList);            }        }  }}@Servciepublic class ServiceB {  @Transactional(rollbackFor=Exception.class)  private void doInsertUpdate(List<InventorySkuDO> inventorySkuDOList){        for (InventorySkuDO inventorySkuDO : inventorySkuDOList) {           doInsert(inventorySkuDO);           doUpdate(inventorySkuDO)        }  }}

(3) 拆解原始事務,異步化處理

這種異步化處理的方案其實有兩種方式進行異步化操作。尤其是涉及到第三方RPC調用或者HTTP調用的時候,這種方案就更加適合。nJs28資訊網——每日最新資訊28at.com

方案一,采用CompletableFuture異步編排特性,當業務流程比較長的時候,我們可以將一個大業務拆解成多個小的任務進行異步化執行。比如咱們有個批量支付的業務邏輯,因為整個流程是同步的,所以大概有了下面這樣的流程。(關于CompletableFeature老貓覺得挺有意思的,后續老貓會出專門的文章來理透該特性,歡迎大家持續關注)。nJs28資訊網——每日最新資訊28at.com

nJs28資訊網——每日最新資訊28at.com

completeFeaturenJs28資訊網——每日最新資訊28at.com

對應轉換成代碼邏輯的話,大概是這樣的:nJs28資訊網——每日最新資訊28at.com

void doBatchPay() {        CompletableFuture<Object> task1 = CompletableFuture.supplyAsync(() -> {            return "訂單信息";        });        CompletableFuture<Object> task2 = CompletableFuture.supplyAsync(() -> {            try {               return doPay();            } catch (InterruptedException e) {                //log add            }        });        //task1、task2 執行完執行task3 ,需要感知task1和task2的執行結果        CompletableFuture<Object> future = task1.thenCombineAsync(task2, (t1, t2) -> {            return "郵件發送成功";        });    }

方案二,Mq異步化處理,還是針對上述業務邏輯,我們是否可以將最終的發送郵件的動作剝離出來,最終再去統一執行發送郵件。nJs28資訊網——每日最新資訊28at.com

nJs28資訊網——每日最新資訊28at.com

關于偽代碼這里不展開了,有興趣的小伙伴可以自行實現一下。nJs28資訊網——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-60936-0.html麻了,這讓人絕望的大事務提交

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

上一篇: 我們優雅判斷 interface 是否為 nil

下一篇: 為啥我放棄用 Pinia 和 Vuex 去做字典狀態管理呢?

標簽:
  • 熱門焦點
  • 摸魚心法第一章——和配置文件說拜拜

    為了能摸魚我們團隊做了容器化,但是帶來的問題是服務配置文件很麻煩,然后大家在群里進行了“親切友好”的溝通圖片圖片圖片圖片對比就對比,簡單對比下獨立配置中心和k8s作為配
  • Automa-通過連接塊來自動化你的瀏覽器

    1、前言通過瀏覽器插件可實現自動化腳本的錄制與編寫,具有代表性的工具就是:Selenium IDE、Katalon Recorder,對于簡單的業務來說可快速實現自動化的上手工作。Selenium IDEKat
  • Golang 中的 io 包詳解:組合接口

    io.ReadWriter// ReadWriter is the interface that groups the basic Read and Write methods.type ReadWriter interface { Reader Writer}是對Reader和Writer接口的組合,
  • 破圈是B站頭上的緊箍咒

    來源 | 光子星球撰文 | 吳坤諺編輯 | 吳先之每年的暑期檔都少不了瞄準追劇女孩們的古偶劇集,2021年有優酷的《山河令》,2022年有愛奇藝的《蒼蘭訣》,今年卻輪到小破站抓住了追
  • 得物寵物生意「狂飆」,發力“它經濟”

    作者|花花小萌主近日,得物宣布正式上線寵物鑒別,通過得物App內的&ldquo;在線鑒別&rdquo;,可找到鑒別寵物的選項。通過上傳自家寵物的部位細節,就能收獲擁有專業資質認證的得物鑒
  • 大廠卷向扁平化

    來源:新熵作者丨南枝 編輯丨月見大廠職級不香了。俗話說,兵無常勢,水無常形,互聯網企業調整職級體系并不稀奇。7月13日,淘寶天貓集團啟動了近年來最大的人力制度改革,目前已形成一
  • 滴滴違法違規被罰80.26億 共存在16項違法事實

    滴滴違法違規被罰80.26億 存在16項違法事實開始于2121年7月,歷經一年時間,網絡安全審查辦公室對“滴滴出行”網絡安全審查終于有了一個暫時的結束。據“網信
  • 英特爾Xe-HP項目終止,將專注Xe-HPC/HPG系列顯卡

    據10 月 31 日消息報道,英特爾高級副總裁兼加速計算系統和圖形事業部總經理 表示,Xe-HP“ Arctic Sound” 系列服務器 GPU 已經應用于 oneAPI devcloud 云服
  • Meta盲目擴張致超萬人被裁,重金押注元宇宙而前景未明

    圖片來源:圖蟲創意日前,Meta創始人兼CEO 馬克&middot;扎克伯發布公開信,宣布Meta計劃裁員超11000人,占其員工總數13%。他公開承認了自己的預判失誤:&ldquo;不僅
Top 主站蜘蛛池模板: 叶城县| 健康| 高碑店市| 太白县| 庆安县| 昌乐县| 蒙城县| 枞阳县| 格尔木市| 共和县| 萝北县| 曲麻莱县| 内黄县| 大邑县| 宁河县| 黑龙江省| 盐亭县| 乐至县| 正蓝旗| 开原市| 泰州市| 建平县| 措美县| 从江县| 建始县| 五常市| 伊金霍洛旗| 普宁市| 沂水县| 鄂托克旗| 九寨沟县| 江永县| 右玉县| 弥勒县| 大连市| 鹤峰县| 山阳县| 错那县| 舟曲县| 长宁区| 武汉市|