幂等 2022-12-08 13:10 > https://mp.weixin.qq.com/s/46b_jVU1G98ThplvB62H9g ### 什么是幂等性? 对于同一笔业务操作,不管调用多少次,得到的结果都是一样的。 以下解决方案,核心是利用数据库回滚事务来保证只有一个成功。 trade_no是支付宝订单号,唯一。 ### 乐观锁: ```sql CREATE TABLE t_order ( id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键,自动增长', user_id BIGINT NOT NULL COMMENT '用户id', order_id VARCHAR(255) NOT NULL DEFAULT '' COMMENT '订单号', status INT NOT NULL DEFAULT 0 COMMENT '订单状态' ) COMMENT '订单表'; CREATE TABLE t_account ( id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键,自动增长', user_id BIGINT NOT NULL COMMENT '用户id', account DECIMAL(13,3) DEFAULT 0 COMMENT '用户余额' ) COMMENT '账户表'; ``` 1.接收到支付宝支付成功请求 2.查询订单信息 ```sql select * from t_order where order_id = trade_no; ``` 3.判断订单是否已处理 4.如果订单已处理直接返回,若未处理,继续向下执行 5.打开本地事务 6.给本地系统给用户加钱 7.将订单状态置为成功,注意这块是重点,伪代码: ```sql update t_order set status = 1 where order_id = trade_no and status = 0; //上面的update操作会返回影响的行数num if(num==1){ //表示更新成功 提交事务; }else{ //表示更新失败 回滚事务; } ``` #### 代码: https://github.com/hanhanhanxu/Idempotent #### 压测 ab -n 50 -c 50 -p 123.txt -T application/json -k http://localhost:8080/api/recharge 123.txt: { "tradeNo":"123" } ### 唯一约束: ```sql CREATE TABLE `t_uq_dipose` ( `id` bigint(20) NOT NULL AUTO_INCREMENT PRIMARY KEY, `ref_type` varchar(32) NOT NULL DEFAULT '' COMMENT '关联对象类型', `ref_id` varchar(255) NOT NULL DEFAULT '' COMMENT '关联对象id', UNIQUE KEY `uq_1` (`ref_type`,`ref_id`) COMMENT '保证业务唯一性' ); ``` 1.接收到支付宝支付成功请求 2.查询t_uq_dipose(条件ref_id,ref_type),可以判断订单是否已处理 ``` select * from t_uq_dipose where ref_type = '充值订单' and ref_id = trade_no; ``` 3.判断订单是已处理 4.如果订单已处理直接返回,若未处理,继续向下执行 5.打开本地事物 6.给本地系统给用户加钱 7.将订单状态置为成功 8.向t_uq_dipose插入数据,插入成功,提交本地事务,插入失败,回滚本地事务,伪代码: ```sql try{ insert into t_uq_dipose (ref_type,ref_id) values ('充值订单',trade_no); //提交本地事务: }catch(Exception e){ //回滚本地事务; } ``` --END--
发表评论