怎么设计一个高质量的接口API设计

简介: 什么是幂等性?对于同一笔业务交易,不管调用多少次,只会成功处理一次。二、幂等性设计我们转账业务为例,来说明一下这个问题,转账接口一定要做到幂等性,否则会出现重复转账的问题。调用转账接口从A中转100元资金给B,参数中会携带业务流水号biz_no和源账户A,目的账户B,和转账金额100,业务流水号biz_no是唯一的。转账接口实现有以下实现方式。

涉及思路
一、什么是幂等性?对于同一笔业务交易,不管调用多少次,只会成功处理一次。二、幂等性设计我们转账业务为例,来说明一下这个问题,转账接口一定要做到幂等性,否则会出现重复转账的问题。调用转账接口从A中转100元资金给B,参数中会携带业务流水号biz_no和源账户A,目的账户B,和转账金额100,业务流水号biz_no是唯一的。转账接口实现有以下实现方式


1 方式1(普通方式)过程如下:

1.接收到转账请求

2.根据biz_no查询当前订单是否处理过3.如果订单已处理直接返回,若未处理,插入一条流水,继续向下执行4.开启本地事务5.本地系统给A扣减100,B账户加1006.插入记账流水表7.将订单状态置为成功8.提交本地事务上面的过程,对于同一笔订单,如果上游重复调用了两次次,会出现什么问题?当两次次请求同时到达第2步时候,查询订单都是未处理的,会继续向下执行,最终本A会转两次钱给B,总共转了200。此方式适用于单机模式,按顺序串行执行的情况。分析:这次出现出现重复转账的原因是,两次请求同时进来,在第一次请求插入流水提交事务之前,第二次又进来了,有人会说:如果第一次请求进来的时候,我加锁,等我处理完了,才释放锁,第二次请求就得等待,直到第一次请求释放锁,再进来,那就没问题了。


2 方式2(jvm加锁方式)方式1中由于并发出现了问题,此时我们使用java中的Lock加锁,来防止并发操作,过程如下:

1.转账接口接收到上游的转账申请请求;

2.调用java中的Lock加锁

3.根据biz_no查询当前订单是否处理过

4.如果订单已处理直接返回,若未处理,插入一条流水,继续向下执行

5.如果订单已处理直接返回,若未处理,继续向下执行

6 开启本地事务

7.本地系统给A扣减100,B账户加100

8.插入记账流水表

9.将订单状态置为成功

10.提交本地事务

11.释放Lock锁分析问题:Lock只能在一个jvm中起效,如果多个请求都被同一套系统处理,上面这种使用Lock的方式是没有问题的,不过互联网系统中,多数是采用集群方式部署,同一套代码后面会部署多套,如果上游同时发来多个请求经过负载均衡转发到不同的机器,上面的锁就不起效了。此时对于多个请求相当于无锁处理了,又会出现方式1中的结果。此时我们需要分布式锁来做处理。


3 方式3(悲观锁方式)使用数据库中悲观锁实现。悲观锁类似于方式二中的Lock,只不过是依靠数据库来实现的。数据中悲观锁使用for update来实现,过程如下:

1.接收到转账申请请求

2.打开本地事物

3.查询订单信息并加悲观锁select * from t_order where biz_no = #{bizNo} for update;

4.判断订单是已处理

5.如果订单已处理直接返回,若未处理,插入一条流水,继续向下执行

6.本地系统给A扣减100,B账户加100

7.插入记账流水表8.将订单状态置为成功

8.提交本地事物分析:重点在于for update,对for update,做一下说明:


1.当线程A执行for update,数据会对当前记录加锁进行行锁,其他线程执行到此行代码的时候,会等待线程A释放锁之后,才可以获取锁,继续后续操作。


2.事物提交时,for update获取的锁会自动释放。方式

3可以正常实现我们需要的效果,能保证接口的幂等性,不过存在一些缺点:1.这种方式性能比较差,并发情况下,后面线程会长期处于等待状态,占用了很多线程,让这些线程处于无效等待状态,我们的web服务中的线程数量一般都是有限的,如果大量线程由于获取for update锁处于等待状态,不利于系统并发操作。


4 方式4(乐观锁方式)依靠数据库中的乐观锁来实现。

1.接收到转账申请请求

2.查询订单信息select * from t_order where biz_no = #{bizNo};

3.判断订单是已处理

4.如果订单已处理直接返回,若未处理,插入一条流水,继续向下执行

5.打开本地事物

6.本地系统给A扣减100,B账户加100

7.插入记账流水表

8.将订单状态置为成功,注意这块是重点,伪代码:update t_order set status = 1 where biz_no = #{bizNo} where status = 0;//上面的update操作会返回影响的行数numif(num==1){ //表示更新成功 提交事务;}else{ //表示更新失败 回滚事务;}注意:update t_order set status = 1 where biz_no = #{bizNo} where status = 0; 是依靠乐观锁来实现的,status=0作为条件去更新.执行这条sql的时候,如果有多个线程同时到达这条代码,数据内部会保证update同一条记录会排队执行,最终最有一条update会执行成功,其他未成功的,他们的num为0,然后根据num来进行提交或者回滚操作。


5 方式5(唯一约束方式)依赖数据库中唯一约束来实现。我们可以创建一个表:CREATE TABLE t_unique_controler ( id bigint(20) NOT NULL AUTO_INCREMENT, unique_biz_no varchar(64) NOT NULL DEFAULT ‘’ COMMENT ‘流水号’, PRIMARY KEY (id), UNIQUE KEY unique_biz_no (unique_biz_no) COMMENT ‘保证业务唯一性’) ENGINE=InnoDB;对于任何一笔转账请求,有一个唯一全局的业务流水号,请求进来来的时候,先查询t_unique_controler表中是否存在相关记录,若不存在,继续放行。过程如下:


1.接收到转账申请请求

2.查询t_unique_controler(条件unique_biz_no),可以判断订单是否已处理select * from t_unique_controler where unique_biz_no = #{unique_biz_no};

3.判断订单是已处理

4.如果订单已处理直接返回,若未处理,插入一条流水,继续向下执行

5.打开本地事物

6.本地系统给A扣减100,B账户加1007.插入记账流水表

7.将订单状态置为成功

8.向t_uq_dipose插入数据,插入成功,提交本地事务,插入失败,回滚本地事务,伪代码:try{ insert into t_unique_controler (unique_biz_no) values (#{unique_biz_no}); 提交本地事务:}catch(Exception e){ 回滚本地事务;}说明:对于同一笔转账请求,业务流水号unique_biz_no是一样的,当并发时,插入数据只会有一条成功,其他的会违法唯一约束,进入catch逻辑,当前事务会被回滚,最终最有一个操作会成功,从而保证了幂等性操作。关于这种方式可以写成通用的方式,不过业务量大的情况下,t_unique_controler插入数据会成为系统的瓶颈,需要考虑分表操作,解决性能问题。上面的过程中向t_unique_controler插入记录,最好放在最后执行,原因:插入操作会锁表,放在最后能让锁表的时间降到最低,提升系统的并发性。关于消息服务中,消费者如何保证消息处理的幂等性?每条消息都有一个唯一的消息id,类似于上面业务中的unique_biz_no,使用上面的方式即可实现消息消费的幂等性。三、总结1.实现幂等性常见的方式有:悲观锁(for update)、乐观锁、唯一约束2.几种方式,按照最优排序:乐观锁 > 唯一约束 > 悲观锁





相关文章
|
4天前
|
人工智能 自然语言处理 API
Multimodal Live API:谷歌推出新的 AI 接口,支持多模态交互和低延迟实时互动
谷歌推出的Multimodal Live API是一个支持多模态交互、低延迟实时互动的AI接口,能够处理文本、音频和视频输入,提供自然流畅的对话体验,适用于多种应用场景。
34 3
Multimodal Live API:谷歌推出新的 AI 接口,支持多模态交互和低延迟实时互动
|
6天前
|
XML JSON 缓存
阿里巴巴商品详情数据接口(alibaba.item_get) 丨阿里巴巴 API 实时接口指南
阿里巴巴商品详情数据接口(alibaba.item_get)允许商家通过API获取商品的详细信息,包括标题、描述、价格、销量、评价等。主要参数为商品ID(num_iid),支持多种返回数据格式,如json、xml等,便于开发者根据需求选择。使用前需注册并获得App Key与App Secret,注意遵守使用规范。
|
5天前
|
JSON API 开发者
淘宝买家秀数据接口(taobao.item_review_show)丨淘宝 API 实时接口指南
淘宝买家秀数据接口(taobao.item_review_show)可获取买家上传的图片、视频、评论等“买家秀”内容,为潜在买家提供真实参考,帮助商家优化产品和营销策略。使用前需注册开发者账号,构建请求URL并发送GET请求,解析响应数据。调用时需遵守平台规定,保护用户隐私,确保内容真实性。
|
5天前
|
搜索推荐 数据挖掘 API
淘宝天猫商品评论数据接口丨淘宝 API 实时接口指南
淘宝天猫商品评论数据接口(Taobao.item_review)提供全面的评论信息,包括文字、图片、视频评论、评分、追评等,支持实时更新和高效筛选。用户可基于此接口进行数据分析,支持情感分析、用户画像构建等,同时确保数据使用的合规性和安全性。使用步骤包括注册开发者账号、创建应用获取 API 密钥、发送 API 请求并解析返回数据。适用于电商商家、市场分析人员和消费者。
|
15天前
|
JSON API 开发工具
淘宝实时 API 接口丨淘宝商品详情接口(Taobao.item_get)
淘宝商品详情接口(Taobao.item_get)允许开发者获取商品的详细信息,包括基本信息、描述、卖家资料、图片、属性及销售情况等。开发者需注册账号、创建应用并获取API密钥,通过构建请求获取JSON格式数据,注意遵守平台规则,合理使用接口,确保数据准确性和时效性。
|
16天前
|
JSON 安全 API
Python调用API接口的方法
Python调用API接口的方法
74 5
|
16天前
|
JSON 缓存 监控
淘宝商品详情接口(Taobao.item_get)丨淘宝API接口指南
淘宝商品详情接口(Taobao.item_get)允许开发者通过HTTP GET方法获取淘宝商品的详细信息,包括商品ID、价格、库存等。请求需包含key、secret、num_iid等必选参数,支持缓存及多种返回格式。此接口广泛应用于电商数据分析、商品选品、价格监控等领域,提升商家运营效率。
|
20天前
|
JSON 搜索推荐 API
LAZADA关键词搜索API接口的获取与应用
Lazada作为东南亚领先的电商平台,为满足开发者和商户需求,开放了关键词搜索API接口。本文详细介绍该接口的获取与应用,助力提升电商业务效率。接口支持关键词搜索、指定搜索范围和排序方式,提供精准、灵活且全面的数据支持,促进电商应用和服务的优化与创新。
22 3
|
26天前
|
JSON API 数据库
电商拍立淘按图搜索API接口,数据格式示例
电商拍立淘按图搜索API接口系列为电商平台和购物应用提供了强大的图像搜索功能,以下是其文档说明的详细参考
|
28天前
|
Web App开发 API Windows
取接口访问者信息[IP,浏览器,操作系统]免费API接口教程
此API用于获取访问者的IP地址、浏览器和操作系统信息,支持70多种浏览器和操作系统。通过POST或GET请求至`https://cn.apihz.cn/api/ip/getapi.php`,需提供用户ID和KEY。返回结果包括状态码、消息、IP、浏览器和操作系统信息。示例:{"code":200,"ip":"175.154.88.178","browser":"Chrome","os":"Windows 10"}。详情见官网文档。