项目场景:

项目场景:本地项目需要保存一份数据同时需要向第三方接口也发送一份数据,并且要保证本地和第三方接口数据一致性。


问题描述

如何保证两个数据一致性呢?

1.先操作接口在操作本地数据库;

2.先操作本地数据库在操作第三方接口;


问题分析:

两种方法其实都能实现,但是想要100%保证还是很困难,只能是最大努力保证两者数据一致性。
方法1:借助RabbitMQ实现,先操作本地数据库然后发送一条消息到MQ中,通过ack机制保证消息准确到达,然后消费者消费消息发送数据到第三方接口。
方法2:保证实时性,新增时直接调用第三方接口,同步成功则接口调用成功否则调用失败。


解决方案:

这里先介绍第二种方式,这里需要借助Guava的重试机制完成。虽然不能保证100%一致性,但是基本上可以满足需求,如果需要保证100%一致性,可以借助同步日志表手动补偿保证。

  1. 首先组装请求:
//调用用户新增同步接口
HttpHeaders headers = packageRequestHttpHeaders(MediaType.APPLICATION_JSON);log.debug("请求参数是{}",JSONObject.toJSONString(userBody));HttpEntity<TtUserBody> httpEntity = new HttpEntity<TtUserBody>(userBody,headers);//StaticConstant.TT_USER_ADD_UR第三方接口的URL地址ResponseEntity<String> responseEntity = restTemplate.postForEntity(StaticConstant.TT_USER_ADD_URL, httpEntity, String.class);log.info("新增用户信息响应结果是{}",responseEntity.getBody());if(responseEntity.getStatusCode().value() == HttpStatus.OK.value()){JSONObject jsonObject = JSONObject.parseObject(responseEntity.getBody());//新增成功if(StaticConstant.REST_RESPONSE_STATUS_OK.equals(jsonObject.getString("status"))){//修改addRanger的userIdString userId = jsonObject.getString("data");return userId;}log.error("导入失败{}",jsonObject.getString("message"));}return responseEntity.getBody();
//组装请求头信息,看情况是否需要
private HttpHeaders packageRequestHttpHeaders(MediaType mediaType) {HttpHeaders headers = new HttpHeaders();headers.setContentType(mediaType);String loginTokenDigest = DigestUtils.md5DigestAsHex(appSecret.getBytes(StandardCharsets.UTF_8));headers.add("authToken", loginTokenDigest);return headers;}

2.调用同步接口

//这是一个方法的部分逻辑。主要是记录同步思路
//1.组装调用同步接口的请求体
packUserBodyRoleIds(userBody);
userBody.setUsername(PingYinUtil.getPingYin(liaisonInfo.getName())+liaisonInfo.getPhone());
userBody.setPassword(DigestUtils.md5DigestAsHex(StaticConstant.TT_USER_DEFAULT_PASSWORD.getBytes(StandardCharsets.UTF_8)));
//调用同步接口。这里是先调用同步接口再新增本地数据库,原因就是我们需要记录同步后的响应信息。
String result = ttLandCloudWorkService.ttAddUser(userBody);
JSONObject jsonObject = JSONObject.parseObject(result);
//新增业务逻辑,如果通过接口返回用户已注册同样允许添加到库中
if(StaticConstant.REST_RESPONSE_STATUS_OK.equals(result)){//这里通过编程式事务控制事务提交TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);try {//添加本地数据表LiaisonInfoEntity addRanger = new LiaisonInfoEntity();BeanUtils.copyProperties(liaisonInfo, addRanger);this.baseMapper.insert(addRanger);//添加关系表数据LzLiaisonEntity entity = new LzLiaisonEntity();entity.setResult(result);lzLiaisonService.save(entity);platformTransactionManager.commit(transactionStatus);return DataResult.success("添加成功");}catch (Exception e){//出现异常回滚事务platformTransactionManager.rollback(transactionStatus);//回滚同步信息,定义Gaava重试机制,保证数据一致性Retryer<Boolean> retry = RetryerBuilder.<Boolean>newBuilder().retryIfException().retryIfResult(Predicates.equalTo(false)).withWaitStrategy(WaitStrategies.fixedWait(1, TimeUnit.SECONDS)).withStopStrategy(StopStrategies.stopAfterAttempt(3)).build();try {retry.call(() -> {String rollbackResult = ttLandCloudWorkService.ttDeleteUser(result);log.error("用户id{}回滚结果,失败手动补偿,结果:{}",result,rollbackResult);return StaticConstant.REST_RESPONSE_STATUS_OK.equals(rollbackResult);});} catch (Exception e1) {//记录本地事务表,手动补偿保证数据一致性。//此处省略未实现。出现问题看日志直接手动改数据库,(狗头)e1.printStackTrace();}}
}

【第三方接口数据一致性】本地保存数据调用第三方接口保证数据一致性相关推荐

  1. 循序渐进BootstrapVue,开发公司门户网站(5)--- 使用实际数据接口代替本地Mock数据

    在我们开发一些门户网站功能的时候,有时候我们需要快速的创建数据模型来进行数据展示,因为数据结构可能处于不断的修正变化之中,因此服务端的接口我们可以暂时不开发,当我们基本完成数据结构和界面展示的时候,就 ...

  2. java第三方接口对接_Java中处理调用第三方接口(post/get),该如何处理,返回的数据如何处理...

    条件:1.请求URL:http://ip:port/yypt/*.jsonRequest 2.接口采用http post协议.Content-Type为application/json 调用流程: 第 ...

  3. cxf 本地wsdl_CXF动态调用wsdl接口

    1.application.properties文件中配置接口url 2.工具类 package com.vulnverify.core.utils; import java.io.IOExcepti ...

  4. WebApi接口 - 如何在应用中调用webapi接口

    » 简单做个webapi(查询+添加)接口 首先,我们需要有一个webapi接口项目,我这里以前面WebApi接口 - 响应输出xml和json文章的项目来构建本篇文章的测试用例:这里新建一个 DbD ...

  5. cmd 调用webservice接口_c# 三种方法调用WebService接口

    1.引用*.wsdl文件 WebService服务端会提供wsdl文件,客户端通过该文件生成.cs文件以及生成.dll. 注意:若服务端只提供的了URL,在URL后面加上"?wsdl&quo ...

  6. php如何调用api接口简单,在PHP中调用API接口|Post数据的方法

    PHP中调用接口 如:http://localhost/operate.php?act=get_user_list&type=json 在这里operate.php相当于一个接口,其中get_ ...

  7. Dynamo分布式系统——「RWN」协议解决多备份数据如何读写来保证数据一致性,而「向量时钟」来保证当读取到多个备份数据的时候,如何判断哪些数据是最新的这种情况...

    转自:http://blog.jqian.net/post/dynamo.html Dynamo是Amazon开发的一款高可用的分布式KV系统,已经在Amazon商店的后端存储有很成熟的应用.它的特点 ...

  8. java调用sap接口_(二)通过JAVA调用SAP接口 (增加一二级参数)

    /*** Created by gang.xu01@hand-china.com on 2018/12/4*/ public classMultiFromSAP {/*** description: ...

  9. php调用restful接口_分享一个PHP调用RestFul接口的函数

    /** * [http 调用接口函数] * @Date 2016-07-11 * @Author GeorgeHao * @param string $url [接口地址] * @param arra ...

最新文章

  1. Testing Windows Live Writer 2
  2. 身患安全杂症,企业如何“下药”?
  3. beautysoup 爬虫
  4. 一劳永逸的搞定 flex 布局
  5. 计算机视觉与深度学习 | TensorMask: A Foundation for Dense Object Segmentation(何凯明团队新作)近5年目标检测综述
  6. leetcode 463. 岛屿的周长(Java版)
  7. 编写一个程序,计算|X-Y|的值,并将结果存入RESULT单元中,其中X和Y都为带符号字数据。
  8. 通过windows远程访问linux桌面的方法(简单)
  9. mysql 修改登录用户名和密码
  10. vs2008的简单使用
  11. 最新服务器处理器天梯,2019服务器CPU天梯图之性能排行榜(双路三路四路) - 服务器百科...
  12. h2o flow初探
  13. 转转品牌升级,不只换了个LOGO
  14. 高通平台SPI配置方法
  15. Qt控件--QComboBox存储自定义数据
  16. python计算球体体积_鬼斧神工:求n维球的体积
  17. java midi版本_java-为特定MIDI设备开发软件
  18. python自定义二元一次函数_Python实现的拟合二元一次函数功能示例【基于scipy模块】...
  19. 玩转搭载眼球追踪的FOVE 0,需要多高的配置呢?
  20. WuThreat身份安全云-TVD每日漏洞情报-2023-02-27

热门文章

  1. 全面解读丨山石网科重磅发布的容器安全防护系统“云铠”,究竟是个啥?
  2. python生成字符图形_【Python AsciiArt】利用命令行打印出字符图案
  3. 集线器与交换机、虚拟局域网(3.3)
  4. Process.Net
  5. 懒人听书java_基础02 Java 跨平台原理
  6. 河南省周口市金保系统向各区县推进工作关键技术问题解决
  7. 节选自《白衣飘飘的年代:宋朝那些有趣的人和事》(重庆大学出版社)
  8. AI(8)---人工智能发展的关键技术
  9. 【iText5 生成PDF】纯Java代码实现生成PDF(自定义表格、文本水印、单元格样式)
  10. PS在园林计算机辅助设计中有哪些应用,园林计算机辅助设计课程标准.doc