项目场景:

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


问题描述

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

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. sh脚本每天创建一个文件夹_我每天创建一个月的视频。 这就是发生的事
  2. BZOJ 2429: [HAOI2006]聪明的猴子【最小生成树】
  3. Vue 项目上线优化
  4. Mycat 之 通过Keepalived 实现高可用
  5. 欧几里得算法以及推论
  6. AspNetForum 论坛整改:添加显IP功能及IP所属地
  7. 【转】oracle order by 处理NULL 值
  8. 贪吃蛇代码c语言100行,贪吃蛇代码-C语言.doc
  9. 黑鲨3怎么安装鸿蒙系统,黑鲨u盘重装系统步骤
  10. leetcode题解日练--2016.8.6
  11. 实现简单QQ聊天功能
  12. ui 名前空間の Aura コンポーネントの廃止
  13. 百度笔试题——页面调度算法
  14. 如何恢复被杀毒软件删除的文件
  15. 计科生毕业一年,做了什么?
  16. FFMpeg TS转成mp4命令
  17. 如何用摄像头来测距(opencv)
  18. 如何修改MySQL监听IP地址
  19. 小白学JS,利用JavaScripty验证通过15位和18位身份证验证性别
  20. 利用MATLAB仿真实现交通红绿灯识别的目的

热门文章

  1. 软件工程十——软件质量管理
  2. zoj1319优先队列
  3. 应用统计学学什么科目_统计学考研科目分别有哪些?你都知道吗
  4. java 排序 comparator_[Java] 用 Comparator 实现排序
  5. 03-Vue案例-计数器
  6. Do not use “@ts-ignore“ because it alters compilation errors的解决办法(不关闭ts的严格模式)
  7. android7.0 谷歌拼音,谷歌浏览器在Android 7.0及以上版本支持使用指纹验证进行无密码登录...
  8. SQL中的脏读、不可重复读、幻读
  9. python银行业务办理时间_python多线程实现代码(模拟银行服务操作流程)
  10. 快排(动图详细版,快速理解)