前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【坑】接口等幂性实施策略

【坑】接口等幂性实施策略

作者头像
林老师带你学编程
发布2019-05-25 23:51:28
5300
发布2019-05-25 23:51:28
举报
文章被收录于专栏:强仔仔强仔仔

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://cloud.tencent.com/developer/article/1434172

项目刚开始的时候,只关注于功能行开发,但是当功能开发完毕的时候,就会暴露很多问题出来,比如今天要讲的接口等幂性。今天会针对实际的应用场景和大家详情的介绍一下,接口是如何实现等幂性。

场景应用

  1. 积分兑换(调用第三方接口)
  2. 供应商入驻(表单重复提交)
  3. 供应商结算申请/运营平台结算审核(表单重复提交)
  4. 线下门店同步订单流水(对外接口)
  5. 多个用户同时注册同一个手机号(并发操作)
  6. 用户申请退款、运营平台审核退款(并发操作)

需要做接口等幂性的地方有太多了,我就以上面的应用场景和大家具体介绍一下他们各自的解决方案。

积分兑换:

我们先来说一下第一种情况(积分兑换),A系统(也就是我们系统)调用B系统进行积分兑换,这个过程可能发送表单重复提交和并发问题,大家可能会疑问是如何发生的呢?

错误场景:

同时多次点击积分兑换按钮,因为B系统(对方系统)没有做接口等幂性,这就会发生多次兑换的的情况,如果是用户故意刷单,对方的系统可能会被刷爆,用户自己本身积分也会被兑换成负数。

解决方法:

我们可以采用redis锁机制,以这个用户id作为锁颗粒,如果是同一个用户并发请求,就必须排队等待。通过这种方式,我们就可以解决上述问题了。

供应商入驻:

电商平台一般都会有供应商入驻流程,需要填写供应商基础信息和证件信息,填写完毕之后就是提交审核了,这个问题就发生在提交审核上面。

错误场景:

不同浏览器同时登录,然后都填写好入驻资料,最后同时点击提交,这个时候如果不做校验,后台就会有两条一模一样的入驻数据。

解决方法:

像这种表单重复提交有很多种解决方法,下面我就和大家一一说一下。

一、我们可以用悲观锁来实现,但是悲观锁效率太低,虽然可以解决表单重复提交问题,但是会严重影响性能。

二、悲观锁使用的时候会将查询也一起锁了,所以这边相对于悲观锁,用乐观锁更好,查询不做限制,修改的时候做限制就可以了。

三、如果是单点服务的话,我们就可以采用同步锁(synchronized)来实现这个机制,用同步锁的时候一定要注意锁的颗粒,如果颗粒太大,那就是一种灾难了。

四、下一种就是分布式锁了,这边我们可以用redis锁来实现,例如上面所说的供应商入驻表单重复提交,就可以采用redis锁实现,可以用供应商账号来作为锁的颗粒,这样其它用户入驻就完全不会有任何影响。

五、非并发情况下,我们就可以采用先select查询是否存在这个账号,存在返回已经提交成功,如果不存在就插入数据。

六、通过前后端token校验来校验是否是重复提交,例如前端每次进入的时候都获取到一个token值,后端会将这个token存储在redis中,然后提交的时候一起将token传过去,检验如果是同一个token就可以插入数据库,如果不是同一个就返回失败。

七、我们可以通过一个状态机幂来做表单校验,如果表单已经提交通过,这个时候状态会发生改变,下次重复提交的时候发现状态已经修改过了,就会直接返回提交失败。

八、我们可以利用唯一索引来防止表单重复提交,这种主要是通过数据库本身来校验是否主键冲突,这种方式一般也不推荐,代价太大了而且主键现在一般都是自己生成。

供应商结算申请/运营平台结算审核:

作为电商系统,肯定会涉及到供应商结算系统,供应商可以申请结算,运营平台审核通过之后就会将钱转到用户账号中,然后用户就可以申请提现到自己银行卡中。可见这个过程是整个系统的重中之重,任何一点过错,都有可能照成金额错误。

错误场景:

供应商多个浏览器同时申请同一笔结算审核,这个时候如果运营平台没有做限制,就有可能结算多次,这个时候就意味着平台多转账给供应商。多个运营平台人员同时审核同一位供应商的结算申请,如果没有做任何限制,也就意味着平台多转账给供应商。如果这两个都没做限制。。。那也就意味着平台破产了。

解决方法:

这边我们同样可以采用redis锁机制,以这个供应商id作为锁颗粒,同一个供应商的请求就会加锁,按照顺序执行,然后再执行,第一步就会判断这个供应商是否申请过,通过这种方式就可以解决供应商多次结算申请的问题了。运营平台多次审核也可以采用redis锁来实现,我们这边以结算申请id作为锁单位,这样同一笔结算申请就必须顺序执行,然后再执行的第一个进行是否审核过的查询就ok了。

线下门店同步订单流水:

我们电商平台有对应的线下门店,每次交易之后,线下门店都会同步流水到平台系统中来。

错误场景:

这个时候就会涉及到订单的漏单和错单的问题,如果出现这种情况,线下门店肯定会进行补单申请提交。这个时候如果系统平台不做接口的等幂性,就会有一堆的重复流水订单产生。

解决方法:

这边我们同样可以用redis锁机制来实现,将流水号作为锁的最小颗粒,就可以保证不影响高并发的情况下,又可以防止重复数据的产生。

总结:

其实场景都八斤八两,我们需要选择最适合当前场景下的方案,来解决对应的问题。下面我们再来总结一下接口等幂性的解决方法:1.数据库乐观锁、2.数据库悲观锁、3.同步锁(synchronized)、4.分布式锁(redis锁)、5.select后update、6.token校验、7.状态机幂等、8.唯一索引。上面的场景当然不仅仅是可以用redis锁来实现,肯定还有其它的,只是我这边最方便的就是这一种。好了今天的内容就介绍到这边了,谢谢大家的阅读~

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年10月20日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档