您现在的位置是:亿华云 > 数据库
互联网业务幂等性实现之基于MySQL
亿华云2025-10-05 14:02:39【数据库】7人已围观
简介背景在互联网业务领域中,我们经常会遇到应用到请求幂等性问题,即多次重复请求,所得到的结果,和一次请求一致。以某互联网电商的取消订单为例子,当订单取消,需要返回给消费者下单所消费的虚拟产品,如优惠券、红
背景
在互联网业务领域中,互联我们经常会遇到应用到请求幂等性问题,网业务幂即多次重复请求,等性所得到的实现结果,和一次请求一致。互联
以某互联网电商的网业务幂取消订单为例子,当订单取消,等性需要返回给消费者下单所消费的实现虚拟产品,如优惠券、互联红包、网业务幂京豆等。等性通过幂等形式,实现确保返还给消费者的互联权益不多、不少。网业务幂
那幂等性具体开发是等性怎么实现的呢?本文带来基于MySQL的UNIQUE KEY的实现方案。
实现
众所周知,UNIQUE KEY是数据库中的唯一索引,数据库的记录中不允许有重复的值,我们可以利用这点,站群服务器在处理业务前,先进行唯一索引数据(如订单id)的插入操作:
插入成功,说明是第一次插入,正常处理业务;插入失败,说明该业务逻辑已经处理过了,不做处理,提前返回;如此,即可实现幂等性。
1.数据库设计幂等性辅助表设计如下:
CREATE TABLE `idempotent_validate` (
`id` bigint NOT NULL,
`create_time` time DEFAULT NULL,
`order_id` bigint DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UK_orssam7fgn4uj0lo2sn4on6vg` (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;其中的一个字段order_id,我们定义为唯一索引。
2.代码编写我们主要实现了订单取消方法cancelOrder:
package com.example.idempotentmysql.service.impl;
import com.example.idempotentmysql.bean.IdempotentValidate;
import com.example.idempotentmysql.bean.OrderInfo;
import com.example.idempotentmysql.bean.ProductInfo;
import com.example.idempotentmysql.bean.UserInfo;
import com.example.idempotentmysql.repository.IdempotentValidateRepository;
import com.example.idempotentmysql.repository.OrderInfoRepository;
import com.example.idempotentmysql.repository.ProductInfoRepository;
import com.example.idempotentmysql.repository.UserInfoRepository;
import com.example.idempotentmysql.service.OrderService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Optional;
/
*** 订单服务
** @author hongcunlin
*/
@Service
public class OrderServiceImpl implements OrderService {
/
*** 日志
*/
private static final Logger LOGGER = LoggerFactory.getLogger(OrderServiceImpl.class);
/
*** 用户repository
*/
@Resource
private UserInfoRepository userInfoRepository;
/
*** 商品repository
*/
@Resource
private ProductInfoRepository productInfoRepository;
/
*** 订单repository
*/
@Resource
private OrderInfoRepository orderInfoRepository;
/
*** 幂等性校验
*/
@Resource
private IdempotentValidateRepository idempotentValidateRepository;
/
*** 取消订单(带幂等性校验)
** @param orderId 订单id
*/
@Override
public void cancelOrder(Long orderId) {
// 1.幂等性校验
try {
IdempotentValidate idempotentValidate = new IdempotentValidate();
idempotentValidate.setOrderId(orderId);
idempotentValidateRepository.save(idempotentValidate);
} catch (Exception e) {
LOGGER.info("订单退款幂等");
return;
}
// 2.退款
Optional orderInfoOptional = orderInfoRepository.findById(orderId);
if (orderInfoOptional.isPresent()) {
OrderInfo orderInfo = orderInfoOptional.get();
OptionaluserInfoOptional = userInfoRepository.findById(orderInfo.getUserId());
Optional productInfoOptional = productInfoRepository.findById(orderInfo.getProductId());
if (userInfoOptional.isPresent() && productInfoOptional.isPresent()) {
UserInfo userInfo = userInfoOptional.get();
ProductInfo productInfo = productInfoOptional.get();
userInfo.setMoney(userInfo.getMoney().add(productInfo.getPrice()));
userInfoRepository.save(userInfo);
}
}
LOGGER.info("订单成功退款");
}
}从代码中可以看到,我们在除了订单退款前,幂等性表先拿订单id进行插入操作,若插入成功,说明是第一次取消订单,执行下面的退款逻辑;
若插入失败,说明之前已经进行过退款逻辑了,我们提前返回,不做下面的退款操作。
如此,便实现了订单退款的幂等性。
3.测试我们对订单进行3次取消操作:
package com.example.idempotentmysql.service;
import com.example.idempotentmysql.bean.OrderInfo;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
@SpringBootTest
public class OrderServiceTest {
@Resource
private OrderService orderService;
@Test
public void cancelOrderTest() {
orderService.cancelOrder(6L);
orderService.cancelOrder(6L);
orderService.cancelOrder(6L);
}
}可以看到,只有第一次是服务器托管退款成功的,后面2次触发幂等性,退款失败,符合我们的预期。
其他
幂等性的实现方式还有很多种,基于MySQL的UNIQUE KEY的实现方案,实现起来相当简单,仅适合业务简单,并发量不高的场景。原因是MySQL的qps有限,且MySQL作为系统的最底层的应用,过于后置,如果最终幂等返回,比较浪费前置的业务处理所消耗的资源。
本文代码已经上传到github上了,有需要的同学可以下载参考:https://github.com/larger5/idempotent-mysql
很赞哦!(8912)
上一篇: 什么样的邮箱才是安全的电子邮件地址?
下一篇: 二、如何选择合适的域名
相关文章
- 4、企业无形资产:通用网站已成为企业网络知识产权的重要组成部分,属于企业的无形资产,也有助于提升企业的品牌形象和技术领先形象。它是企业品牌资产不可或缺的一部分。
- 我们一起聊聊Tomcat和Jetty中的对象池技术
- 夏季数据中心运维要注意哪些问题
- 创新电源如何推动数据中心走向可持续发展
- 为什么现在中文域名觉得好?使用中文域名有什么好处?
- 如何实现数据中心的性能优化和负载均衡?
- 每瓦性能提升2.6倍、机架密度升3倍,Intel 3开山之作不简单
- 数据中心的关键性和冗余性
- (4) 使用何种形式的域名后缀对网页搜索影响不大,但域名后缀也需要考虑方便用户记忆
- 英伟达发布史上最大的GPU芯片!盘点GTC2024上的重磅硬件产品
热门文章
站长推荐
3、商标域名一经注册,就可以作为域名裁决过程中的主要信息之一。这可以大大增加公司被抢注的相关域名胜诉的机会。
Tomcat如何支持异步Servlet?
数据中心和区域供热:完美的组合
NVIDIA 发布 Project GR00T 人形机器人基础模型和 Isaac 机器人平台重大更新
因为域名解析需要同步到DNS根服务器,而DNS根服务器会不定时刷,只有DNS根服务器刷新后域名才能正常访问,新增解析一般会在10分钟左右生效,最长不会超过24小时,修改解析时间会稍微延长。
AI First:戴尔帮助各种规模的企业加速 AI 创新
警惕!数据中心过剩危机背后的三大认知误区
英特尔扩展至强6产品组合,AI性能飙升2倍,网络性能飞跃