精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

SpringBoot結合RabbitMQ實現分布式事務之最大努力通知

開發 前端
如果盡最大努力也沒有通知到接收方,或者接收方消費消息后要再次消費,此時可由接收方主動向通知方查詢消息信息來滿足需求。

環境:springboot.2.4.12 + RabbitMQ3.7.4

什么是最大努力通知

這是一個充值的案例

圖片圖片

交互流程 :

1、賬戶系統調用充值系統接口。

2、充值系統完成支付向賬戶系統發起充值結果通知 若通知失敗,則充值系統按策略進行重復通知。

3、賬戶系統接收到充值結果通知修改充值狀態。

4、賬戶系統未接收到通知會主動調用充值系統的接口查詢充值結果。通過上邊的例子我們總結最大努力通知方案的目標 :目標 :發起通知方通過一定的機制最大努力將業務處理結果通知到接收方。

具體包括 :

1、有一定的消息重復通知機制。因為接收通知方可能沒有接收到通知,此時要有一定的機制對消息重復通知。

2、消息校對機制。如果盡最大努力也沒有通知到接收方,或者接收方消費消息后要再次消費,此時可由接收方主動向通知方查詢消息信息來滿足需求。

最大努力通知與可靠消息一致性有什么不同?

1、解決方案思想不同 可靠消息一致性,發起通知方需要保證將消息發出去,并且將消息發到接收通知方,消息的可靠性關鍵由發起通知方來保證。最大努力通知,發起通知方盡最大的努力將業務處理結果通知為接收通知方,但是可能消息接收不到,此時需要接收通知方主動調用發起通知方的接口查詢業務處理結果,通知的可靠性關鍵在接收通知方。

2、兩者的業務應用場景不同 可靠消息一致性關注的是交易過程的事務一致,以異步的方式完成交易。最大努力通知關注的是交易后的通知事務,即將交易結果可靠的通知出去。

3、技術解決方向不同 可靠消息一致性要解決消息從發出到接收的一致性,即消息發出并且被接收到。最大努力通知無法保證消息從發出到接收的一致性,只提供消息接收的可靠性機制。可靠機制是,最大努力地將消息通知給接收方,當消息無法被接收方接收時,由接收方主動查詢消費。

通過RabbitMQ實現最大努力通知

關于RabbitMQ相關文章《SpringBoot RabbitMQ消息可靠發送與接收 》,《RabbitMQ消息確認機制confirm 》。

  • 項目結構

圖片圖片

兩個子模塊users-mananger(賬戶模塊),pay-manager(支付模塊)

  • 依賴
<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 <scope>runtime</scope>
</dependency>

子模塊pay-manager

  • 配置文件
server:
  port: 8080
---
spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
    virtual-host: /
    publisherConfirmType: correlated
    publisherReturns: true
    listener:
      simple:
        concurrency: 5
        maxConcurrency: 10
        prefetch: 5
        acknowledgeMode: MANUAL
        retry:
          enabled: true
          initialInterval: 3000
          maxAttempts: 3
        defaultRequeueRejected: false
  • 實體類

記錄充值金額及賬戶信息

@Entity
@Table(name = "t_pay_info")
public class PayInfo implements Serializable{
 @Id
 private Long id;
 private BigDecimal money ;
 private Long accountId ;
}
  • DAO及Service
public interface PayInfoRepository extends JpaRepository<PayInfo, Long> {
 PayInfo findByOrderId(String orderId) ;
}
@Service
public class PayInfoService {
  
  @Resource
  private PayInfoRepository payInfoRepository ;
  @Resource
  private RabbitTemplate rabbitTemplate ;
  
  // 數據保存完后發送消息(這里發送消息可以應用確認模式或事物模式)
  @Transactional
  public PayInfo savePayInfo(PayInfo payInfo) {
    payInfo.setId(System.currentTimeMillis()) ;
    PayInfo result = payInfoRepository.save(payInfo) ;
    CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString().replaceAll("-", "")) ;
    try {
      rabbitTemplate.convertAndSend("pay-exchange", "pay.#", new ObjectMapper().writeValueAsString(payInfo), correlationData) ;
    } catch (AmqpException | JsonProcessingException e) {
      e.printStackTrace();
    }
    return result ;
  }
  
  public PayInfo queryByOrderId(String orderId) {
    return payInfoRepository.findByOrderId(orderId) ;
  }
  
}

支付完成后發送消息。

  • Controller接口
@RestController
@RequestMapping("/payInfos")
public class PayInfoController {
 @Resource
 private PayInfoService payInfoService ;
  
  // 支付接口
 @PostMapping("/pay")
 public Object pay(@RequestBody PayInfo payInfo) {
  payInfoService.savePayInfo(payInfo) ;
  return "支付已提交,等待結果" ;
 }
  
 @GetMapping("/queryPay")
 public Object queryPay(String orderId) {
  return payInfoService.queryByOrderId(orderId) ;
 }
  
}

子模塊users-manager

  • 應用配置
server:
  port: 8081
---
spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
    virtual-host: /
    publisherConfirmType: correlated
    publisherReturns: true
    listener:
      simple:
        concurrency: 5
        maxConcurrency: 10
        prefetch: 5
        acknowledgeMode: MANUAL
        retry:
          enabled: true
          initialInterval: 3000
          maxAttempts: 3
        defaultRequeueRejected: false
  • 實體類
@Entity
@Table(name = "t_users")
public class Users {
 @Id
 private Long id;
 private String name ;
 private BigDecimal money ;
}

賬戶信息表

@Entity
@Table(name = "t_users_log")
public class UsersLog {
 @Id
 private Long id;
 private String orderId ;
 // 0:支付中,1:已支付,2:已取消
 @Column(columnDefinition = "int default 0")
 private Integer status = 0 ;
 private BigDecimal money ;
 private Date createTime ;
}

賬戶充值記錄表(去重)

  • DAO及Service
public interface UsersRepository extends JpaRepository<Users, Long> {
}
public interface UsersLogRepository extends JpaRepository<UsersLog, Long> {
 UsersLog findByOrderId(String orderId) ;
}
  • Service類
@Service
public class UsersService {  
  @Resource
  private UsersRepository usersRepository ;
  @Resource
  private UsersLogRepository usersLogRepository ;
  
 @Transactional
 public boolean updateMoneyAndLogStatus(Long id, String orderId) {
  UsersLog usersLog = usersLogRepository.findByOrderId(orderId) ;
  if (usersLog != null && 1 == usersLog.getStatus()) {
   throw new RuntimeException("已支付") ;
  }
  Users users = usersRepository.findById(id).orElse(null) ;
  if (users == null) {
   throw new RuntimeException("賬戶不存在") ;
  }
  users.setMoney(users.getMoney().add(usersLog.getMoney())) ;
  usersRepository.save(users) ;
  usersLog.setStatus(1) ;
  usersLogRepository.save(usersLog) ;
  return true ;
 }
  
 @Transactional
 public boolean saveLog(UsersLog usersLog) {
  usersLog.setId(System.currentTimeMillis()) ;
  usersLogRepository.save(usersLog) ;
  return true ;
 }
}
  • 消息監聽
@Component
public class PayMessageListener {
  
 private static final Logger logger = LoggerFactory.getLogger(PayMessageListener.class) ;
  
 @Resource
 private  UsersService usersService ;
  
 @SuppressWarnings("unchecked")
 @RabbitListener(queues = {"pay-queue"})
 @RabbitHandler
 public void receive(Message message, Channel channel) {
  long deliveryTag = message.getMessageProperties().getDeliveryTag() ;
  byte[] buf =  null ;
  try {
   buf = message.getBody() ;
   logger.info("接受到消息:{}", new String(buf, "UTF-8")) ;
   Map<String, Object> result = new JsonMapper().readValue(buf, Map.class) ;
   Long id = ((Integer) result.get("accountId")) + 0L ;
   String orderId = (String) result.get("orderId") ;
   usersService.updateMoneyAndLogStatus(id, orderId) ;
   channel.basicAck(deliveryTag, true) ;
  } catch (Exception e) {
   logger.error("消息接受出現異常:{}, 異常消息:{}", e.getMessage(), new String(buf, Charset.forName("UTF-8"))) ;
   e.printStackTrace() ;
   try {
    // 應該將這類異常的消息放入死信隊列中,以便人工排查。
    channel.basicReject(deliveryTag, false);
   } catch (IOException e1) {
    logger.error("拒絕消息重入隊列異常:{}", e1.getMessage()) ;
    e1.printStackTrace();
   }
  }
 }
}
  • Controller接口
@RestController
@RequestMapping("/users")
public class UsersController {
  
  @Resource
  private RestTemplate restTemplate ;
  @Resource
  private UsersService usersService ;
  
  @PostMapping("/pay")
  public Object pay(Long id, BigDecimal money) throws Exception {
    HttpHeaders headers = new HttpHeaders() ;
    headers.setContentType(MediaType.APPLICATION_JSON) ;
    String orderId = UUID.randomUUID().toString().replaceAll("-", "") ;
    Map<String, String> params = new HashMap<>() ;
    params.put("accountId", String.valueOf(id)) ;
    params.put("orderId", orderId) ;
    params.put("money", money.toString()) ;
    
    UsersLog usersLog = new UsersLog() ;
    usersLog.setCreateTime(new Date()) ;
    usersLog.setOrderId(orderId);
    usersLog.setMoney(money) ;
    usersLog.setStatus(0) ;
    usersService.saveLog(usersLog) ;
    HttpEntity<String> requestEntity = new HttpEntity<String>(new ObjectMapper().writeValueAsString(params), headers) ;
    return restTemplate.postForObject("http://localhost:8080/payInfos/pay", requestEntity, String.class) ;
  }
  
}

以上是兩個子模塊的所有代碼了

測試

初始數據

圖片圖片

圖片圖片

賬戶子模塊控制臺

圖片圖片

支付子模塊控制臺

圖片圖片

數據表數據

圖片圖片

完畢!!!

責任編輯:武曉燕 來源: Spring全家桶實戰案例源碼
相關推薦

2021-04-16 16:02:13

SpringBoot分布式最大努力通知

2024-06-11 13:50:43

2022-06-27 08:21:05

Seata分布式事務微服務

2022-06-14 10:47:00

分布式事務數據

2022-06-21 08:27:22

Seata分布式事務

2017-07-26 15:08:05

大數據分布式事務

2020-03-31 08:05:23

分布式開發技術

2021-08-06 08:33:27

Springboot分布式Seata

2019-10-10 09:16:34

Zookeeper架構分布式

2025-06-11 08:01:06

2009-06-19 15:28:31

JDBC分布式事務

2021-09-29 09:07:37

分布式架構系統

2009-09-18 15:10:13

分布式事務LINQ TO SQL

2023-01-13 07:39:07

2023-01-06 09:19:12

Seata分布式事務

2021-12-09 10:45:19

分布式事務框架

2025-05-13 02:10:00

2025-04-29 04:00:00

分布式事務事務消息

2019-06-26 09:41:44

分布式事務微服務

2022-03-24 07:51:27

seata分布式事務Java
點贊
收藏

51CTO技術棧公眾號

久久久久久草| 精品乱码亚洲一区二区不卡| 欧美专区一二三| 在线观看国产精品入口男同| 日本久久一二三四| 日韩一区二区高清| 日韩精品xxxx| 国产私拍精品| 国产一区二区三区不卡在线观看| 久久久亚洲精选| 中文字幕在线观看免费高清| 精品国产一级| 黑人狂躁日本妞一区二区三区 | 国产三级精品视频| 91亚洲国产成人久久精品网站| 日韩免费视频网站| 国产精品麻豆久久| 亚洲欧美国产日韩天堂区| 国产一级免费大片| 中文不卡1区2区3区| 国产精品短视频| 久久精品99| 国产高潮流白浆喷水视频| 老牛国产精品一区的观看方式| 欧美成人精品激情在线观看| 国产传媒国产传媒| 久久电影在线| 7878成人国产在线观看| 日本在线观看a| segui88久久综合| 中文字幕在线不卡| 日日骚一区二区网站| 欧美一区二区黄片| 国精产品一区一区三区mba桃花| 欧美中文字幕在线视频| 免费在线观看国产精品| 国产精品久久久久9999赢消| 亚洲丝袜av一区| 日韩av无码一区二区三区不卡| 电影91久久久| 一区二区三区日韩精品视频| 欧美性色aⅴ视频一区日韩精品| 日韩免费av一区二区三区| 色一情一乱一乱一区91av| 国产精品1024| 亚洲jizzjizz日本少妇| 一本色道久久综合无码人妻| 日韩激情中文字幕| 日韩免费视频在线观看| 国产一区二区三区影院| 黄色在线成人| 久久久久久久色| 免费人成在线观看| 欧美99久久| 九九热这里只有在线精品视| 91高清免费观看| 98精品久久久久久久| 色偷偷888欧美精品久久久| 日本精品在线观看视频| 欧美日韩国产高清电影| 国产一区二区三区在线视频| 国产综合精品在线| 日韩aaaa| 视频直播国产精品| 日韩精品123区| 亚洲欧美在线专区| 欧美理论电影在线观看| 国产精品日日夜夜| 一区二区三区精品视频在线观看| 97精品欧美一区二区三区| 日韩激情在线播放| 国产精品毛片一区二区三区| 日本91av在线播放| 中国女人一级一次看片| 精品在线免费观看| 99理论电影网| 四虎免费在线观看| 久久精品亚洲国产奇米99| 亚洲精品二区| 在线免费观看a视频| 亚洲成人免费看| 亚洲中文字幕无码专区| av在线不卡精品| 欧美日韩精品系列| 制服下的诱惑暮生| 欧美精品密入口播放| 亚洲一区二区久久久| 亚洲欧美另类日本| 在线观看一区视频| 国产精品扒开腿做爽爽爽男男| 一本色道久久综合无码人妻| 国产精品69久久久久水密桃| 国产一区二区高清不卡| 韩日视频在线| 一区二区三区四区不卡在线| 丰满爆乳一区二区三区| 日本欧美不卡| 日韩精品一区二区在线| caopeng视频| 综合五月婷婷| 日韩av片电影专区| 国产美女www爽爽爽视频| 91在线精品秘密一区二区| 日韩欧美亚洲日产国产| 欧美日韩经典丝袜| 欧美在线一区二区三区| 逼特逼视频在线观看| 欧美先锋资源| 午夜精品一区二区三区在线| 亚洲天堂男人网| 成a人片亚洲日本久久| 亚洲人成网站在线播放2019| 超碰91在线观看| 91麻豆精品国产| 性欧美13一14内谢| 亚洲韩日在线| 91在线网站视频| 成人高清网站| 天天免费综合色| 天天干天天曰天天操| 欧美精品系列| 91av免费观看91av精品在线| 国产富婆一级全黄大片| 国产精品久久久久久久久动漫 | 免费在线看黄| 欧美色欧美亚洲高清在线视频| 一级片免费在线观看视频| 久久99青青| 91精品国产91久久久久久| 99国产精品一区二区三区| 亚洲国产精品传媒在线观看| 欧美a在线视频| 粉嫩av一区二区| 欧美大胆a视频| 一本色道久久综合熟妇| 中文字幕av一区二区三区免费看 | 精品一区二区三区自拍图片区| 黄色网在线免费观看| 欧美熟乱第一页| 久久久久久久久久久久| 亚洲一区黄色| 精品亚洲欧美日韩| 国产传媒在线观看| 亚洲成av人乱码色午夜| 久久99久久久| 国产成人亚洲精品狼色在线| 日本一道在线观看| 色诱色偷偷久久综合| 色噜噜狠狠狠综合曰曰曰| 男操女视频网站| 国产欧美综合在线观看第十页 | 激情久久久久久久久久久久久久久久| 日本一区二区三不卡| 香蕉视频亚洲一级| 亚洲一区二区黄| 在线观看免费视频一区| 中文字幕不卡三区| 亚洲午夜精品一区| 亚洲老妇激情| 波多野结衣精品久久| 丁香花在线观看完整版电影| 亚洲国产精品va在线看黑人| 成年人免费看毛片| 久久蜜臀精品av| 亚洲成人福利在线观看| 日韩在线二区| 91久久久久久久久| 在线你懂的视频| 亚洲黄色成人网| 秋霞av一区二区三区| 中文字幕二三区不卡| 激情久久综合网| 欧美三区视频| 久久久久欧美| 8av国产精品爽爽ⅴa在线观看| 中文字幕在线视频日韩| jlzzjlzzjlzz亚洲人| 亚洲国产精品一区二区久久恐怖片| 成熟妇人a片免费看网站| 视频在线观看国产精品| 在线视频不卡一区二区三区| 2021年精品国产福利在线| 97在线免费观看| 国产亚洲依依| 日韩视频免费直播| 国产精品久久久久久久久久精爆| 国产人久久人人人人爽| 日韩成人av免费| 国产日韩精品视频一区二区三区 | 国产精品hd| 国产伦精品一区二区三区免费视频| 中国色在线日|韩| 精品国产一区二区三区在线观看| 亚洲春色一区二区三区| 91福利视频久久久久| 亚洲色图综合区| 久久毛片高清国产| 91人妻一区二区三区| 久久免费高清| 91网站在线观看免费| 国产在线日韩精品| 成人免费观看网站| 成人免费一区| 91成人免费观看网站| 欧美性猛交xxx乱大交3蜜桃| 亚洲精品乱码久久久久久按摩观| 中文字幕人妻丝袜乱一区三区| 亚洲成人综合视频| 日本裸体美女视频| 久久亚洲精品小早川怜子| 国产成人精品综合久久久久99| 狂野欧美性猛交xxxx巴西| 妺妺窝人体色777777| 我不卡影院28| 日韩精品欧美专区| 日本福利一区| 99久久精品久久久久久ai换脸| 日韩视频网站在线观看| 91国内在线视频| 男女羞羞视频在线观看| 日韩在线观看免费av| 国产午夜在线观看| 国产视频精品免费播放| 免费看av毛片| 日韩一卡二卡三卡四卡| 一区二区小视频| 欧美中文字幕久久| 国产精品久久久久久久久久久久久久久久久| 亚洲色图欧美激情| 国产又粗又长又黄的视频| 久久精品综合网| 亚洲av无码一区二区三区观看| 国产成人一级电影| 婷婷中文字幕在线观看| 麻豆国产一区二区| 88av.com| 久久久久网站| 国产成人无码一二三区视频| 136国产福利精品导航网址| 国内精品国产三级国产99| 国产国产精品| 成人手机视频在线| 久久精品高清| 亚洲啪啪av| 久久神马影院| 亚洲在线视频一区二区| 日韩精品久久| 亚洲一区二区三区免费看| 精品国产123区| 青青草国产精品| 国产免费久久| 日韩高清av电影| 凹凸成人精品亚洲精品密奴| 日本不卡免费新一二三区| 亚洲宅男网av| 日本欧洲国产一区二区| 精品国产精品国产偷麻豆| 天天综合狠狠精品| 四季av一区二区凹凸精品| 亚洲三级一区| 亚洲视频电影在线| 99久久免费观看| 99在线精品视频在线观看| 波多野结衣家庭教师在线| 性欧美xxxx大乳国产app| 丁香啪啪综合成人亚洲| 男女男精品视频| 男人的天堂最新网址| 国产在线精品免费| 超碰人人cao| 波多野洁衣一区| 精品少妇一区二区三区免费观| 久久一留热品黄| 欧美大波大乳巨大乳| 中文字幕一区二区三区在线播放 | 4444欧美成人kkkk| 都市激情综合| 国产精品自拍偷拍| 亚洲日本va| 精品国产一区二区三区免费 | 亚洲日本欧美日韩高观看| www.成人.com| 欧美床上激情在线观看| 麻豆mv在线看| 国产精品丝袜白浆摸在线| 国产精品日韩精品在线播放| 国产精品久久亚洲7777| 黑人操亚洲人| 2022中文字幕| 亚洲一区激情| 国产精品999.| 91免费视频网| 成人一级黄色大片| 精品成人久久av| 中文字幕av无码一区二区三区| 日韩欧美国产午夜精品| 蜜芽tv福利在线视频| 久久九九全国免费精品观看| 96av在线| 成人国产精品一区| 日韩一级电影| 国产免费一区二区三区四在线播放| 激情六月综合| 国内国产精品天干天干| 99re这里只有精品首页| 欧美特黄一级片| 色婷婷亚洲综合| 亚洲第一免费视频| 色999日韩欧美国产| 超碰在线公开| 亚洲尤物视频网| 亚洲欧洲av| 女人帮男人橹视频播放| 六月婷婷色综合| 精品夜夜澡人妻无码av| 亚洲欧美日韩国产另类专区| 国产无套丰满白嫩对白| 日韩欧美一级二级| 91在线视频| 国外成人在线播放| 欧美一区=区三区| 欧美日韩一区综合| 99亚洲伊人久久精品影院红桃| 日本中文字幕在线不卡| 中文成人av在线| 极品国产91在线网站| 亚洲成人黄色网址| 国产网站在线免费观看| 国产精品欧美一区二区| 亚洲bt欧美bt精品777| 草b视频在线观看| 国产精品综合视频| 日韩国产第一页| 欧美日韩中文一区| 国产三级电影在线| 国产91成人在在线播放| 精品福利一区| 亚洲人精品午夜射精日韩| 国产凹凸在线观看一区二区| 2025国产精品自拍| 欧美一区二区三区人| 毛片在线看网站| 成人欧美一区二区三区黑人孕妇| 欧美丝袜激情| 在线观看的毛片| 中文字幕av一区二区三区高 | 老司机精品久久| 亚洲第一页av| 日韩欧美亚洲一二三区| 日韩在线无毛| 人人做人人澡人人爽欧美| 性人久久久久| 国产精品亚洲a| 久久天天做天天爱综合色| 欧产日产国产69| 亚洲欧洲一区二区三区在线观看| 亚洲黄色免费看| 欧美激情论坛| 日韩在线a电影| 懂色av蜜桃av| 欧美视频一区在线观看| 777电影在线观看| 成人美女免费网站视频| 亚洲a视频在线| 亚洲人成在线影院| 色狠狠色狠狠综合| 欧美综合在线观看视频| 免费观看成人性生生活片| 色综合色狠狠综合色| 久草精品在线播放| 成人在线中文| 日韩欧美一区中文| 国产极品一区二区| 中文字幕av一区二区三区人| 欧美男生操女生| 99在线精品免费视频| 天天做天天爱综合| 性鲍视频在线观看| 亚洲一区二区三区精品在线| 色婷婷中文字幕| 日本一区二区在线播放| 日韩理论电影大全| 超碰91在线播放| 黄色一区二区在线观看| 国产精品一区二区婷婷| 成人欧美一区二区三区在线湿哒哒| 欧美激情日韩| 魔女鞋交玉足榨精调教| 欧美日韩第一区日日骚| 欧美videossex| 欧美性大战久久久久| 韩国毛片一区二区三区| 日韩久久久久久久久| 中文字幕av一区中文字幕天堂| 日本一区二区三区视频在线看 | 扒开伸进免费视频| 色综合久久久久久久| 天天干在线视频论坛| 日本一区二区久久精品| 成人免费视频caoporn|