進修spring事務與新聞隊列。本站提示廣大學習愛好者:(進修spring事務與新聞隊列)文章只能為提供參考,不一定能成為您想要的結果。以下是進修spring事務與新聞隊列正文
在開辟進程中,碰到一個bug,發生bug的緣由是spring事務提交晚於新聞隊列的臨盆新聞,招致新聞隊列花費新聞時獲得到的數據不准確。這篇文章引見成績的發生和一步步的處理進程。
一.成績的發生:
場景復原:接口中的一個辦法,起首修正定單狀況,然後向新聞隊列中臨盆新聞,新聞隊列的花費者獲得到新聞檢測定單狀況,發明定單狀況未更改。
代碼:
@Service(orderApi) public class OrderApiImpl implements OrderApi { @Resource MqService mqService; @OrderDao orderDao; public void push(String orderId) { // 更新定單狀況,之前的狀況是1 updateStatus(orderId, 3); // 發生新聞 mqService.produce(orderId); } public viod updateStatus(String orderId, Integer status) { orderDao.updateStatus(orderId, status); } }
成績發生緣由:orderApi中的一切辦法都有事務,事務類型PROPAGATION_REQUIRED,所以push辦法對數據的操作會在push代碼全體履行以後提交,而在事務提交之前新聞隊列的新聞曾經發生所以新聞隊列中花費到的定單從數據庫查詢出的狀況能夠還為1。為了讓bug景象更顯著,可以在push辦法最初添加:
try { Thread.sleep(10000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); }
如許就會發明花費新聞時,定單狀況必定是未修正的。
二.成績的處理:
處理計劃:在更新數據時,新建一個事物,包管更新代碼履行完成後,更新數據庫的事務已被提交。(確保新聞發生前數據庫操作已提交)
依照上述計劃,我起首想到的是直接修正updateStatus辦法的事務類型;我將此辦法的事務類型改成PROPAGATION_REQUIRES_NEW(新建事務,假如以後存在事務,把以後事務掛起)。
然則這麼做有兩點不適合:
1.強迫修正了updateStaus的事務類型,能夠影響其他流程。
2.未起到感化,updateStaus辦法中沒有新建事務。
關於第二點的說明:spring添加事務是經由過程BeanNameAutoProxyCreator完成的靜態署理,只是給bean對象添加了事務,如今在類外部挪用辦法,是不會觸發新事物的創立的。
所以在經由以上測驗考試後,我創立了一個新的類:
@Service("orderExtApi") public class OrderExtApiImpl { @Resource OrderApi orderApi; public void updateStatusNewPropagation(String orderId) { orderApi.updateStatus(orderId); } }
並為updateStatusNewPropagation辦法添加事務PROPAGATION_REQUIRES_NEW
這個類就只是為了給orderApi中的updateStaus辦法新起一個事務。
ok,到此為止bug曾經處理了。
然則代碼中照樣存在成績:對數據庫的操作曾經提交,假如臨盆新聞湧現異常對營業邏輯來講照樣毛病的。所以須要檢測新聞的發生能否完成。
終究orderApi中的代碼以下:
@Service(orderApi) public class OrderApiImpl implements OrderApi { @Resource MqService mqService; @Resource OrderDao orderDao; @Resource OrderExtApiImpl orderExtApi; public void push(String orderId) { // 更新定單狀況,之前的狀況是1 orderExtApi.updateStatusNewPropagation(orderId, 3); // 發生新聞--produce會檢測能否湧現異常 當前往1時表現臨盆新聞勝利 Response response = mqService.produce(orderId); if (response.getCode() != 1) { log.info("新聞隊列臨盆新聞異常:" + response.getErrorMsg()) // 臨盆新聞異常,重置狀況 期待下次從新履行 orderExtApi.updateStatusNewPropagation(orderId, 1); } } public viod updateStatus(String orderId, Integer status) { orderDao.updateStatus(orderId, status); } }
以上就是本文的全體內容,願望對年夜家的進修有所贊助,也願望年夜家多多支撐。