标签:date insert 公众号 没有 update from 创建 ref n+1
分布式系统的幂等性你们是怎么设计的?公众号关注 “架构师学习营”
设为 “星标”,带你学习更多架构师知识!
大家好,这里是架构师学习营。
本文和探讨一下分布式系统中幂等性的设计。
1、什么是幂等性?
对于同一笔业务,执行一次或者多次,产生的结果都是一样的,幂等性主要是为了解决重复处理的问题。
2、来看一个场景
我们有个电商系统,可以通过支付宝进行充值。
用户看到的过程如下:
1.电商网站,用户输入金额,点击充值
2.电商生成充值订单,订单状态为待支付
3.跳转到支付宝页面,用户确定支付
4.支付那边操作完成之后,会携带充值结果重定向到商户的结果页面,此时页面显示充值成功
此时电商中的充值订单并没有去修改,而支付宝会将充值结果异步通知给电商。
电商系统接收到充值通知结果之后,处理过程如下:
if(判断订单状态是否为待支付){ //@1
给用户账户加钱
将订单状态置为充值成功
}
可能会由于网络故障,通知无法到达商户,所以支付宝为了让通知能够达到商户,可能会出现并发重复通知的情况。br/>若支付宝同时来了2个通知,同时到达@1,会出现什么后果???
若用户充值1万,最终会导致2万,严重线上事故。
为什么会出现重复处理?
由于存在并发情况,导致了,条件判断失效,从而导致了重复处理。
主要原因:并发
那么,如果没有并发,是不是就不会出现问题了?
确实,如果没有并发,就没有上面的问题了。
解决问题的根本办法?
让并发操作排队执行,并行的操作变成一个个执行,问题自然就消失了。
3、方式1:乐观锁
订单表需添加一个字段:version(版本号),默认为0,每次更新+1。
业务伪代码:
Order order = 获取订单信息;
if(order是否未处理){
int upCount = update set version = version+1, status=已处理 where id = 订单号 and version = order.version;
if(upCount==1){
执行业务操作:给用户加钱
}
}
db中对于同一条数据,更新的时候会上锁,所以如果有并发更新,也只能一个个处理。
上面的重点在于update操作,将版本号作为条件来更新,并且更新的时候将version = version+1,并发的情况下,只会有一个线程更新成功,update操作会返回更新行数upCount,若upCount和期望的结果一致,说明更新成功了,然后执行业务操作;其他的upCount会为0,直接跳过业务操作。
4、方式2:分布式锁
通常我们的系统采用集群的方式进行部署,集群环境中,可以通过分布式锁来让并发操作变成排队执行。
获取到锁的可以执行,获取不到的排队等待或者直接跳过。
boolean lock = getLock(业务订单唯一id);
if(lock){
执行业务操作;
}
5、方式3:数据库唯一约束
通用的方式,db中添加一个表
CREATE TABLE `t_uq_dipose` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`ref_type` varchar(32) NOT NULL DEFAULT ‘‘ COMMENT ‘关联对象类型‘,
`ref_id` varchar(64) NOT NULL DEFAULT ‘‘ COMMENT ‘关联对象id‘,
PRIMARY KEY (`id`),
UNIQUE KEY `uq_1` (`ref_type`,`ref_id`) COMMENT ‘保证业务唯一性‘
);
业务操作伪代码
try{
1.先查询一下订单在t_uq_dipose中是否存在
int count = select count(*) from t_uq_dipose where ref_type = ‘充值订单‘ and ref_id = ‘充值订单唯一id‘;
if(count==0){
2.开启事务
3.insert into t_uq_dipose (ref_type,ref_id) values (‘充值订单‘,‘充值订单唯一id‘);
4.执行业务操作
5.提交本地事务
}
}catch(Exception e){
6.回滚本地事务;
}
这种方式存在瓶颈:t_uq_dipose单表 + 唯一约束,写上面存在系统瓶颈。
如何解决这种瓶颈?
分库分表,大家要有这种解决问题的思想,并发导致性能出现瓶颈,得就想办法分片,这样落到每个分片上面的并发量就比较小了,从而提升系统性能。
t_uq_dipose表可以创建很多个,比如创建64个:
t_uq_dipose_0
t_uq_dipose_1
.....
t_uq_dipose_63
业务来了之后,可以先定位到表名,可以通过hash值取模的方式找到对应的表:
hashCode(ref_type+ref_id) % 64
大家用哪种方案呢?欢迎留言一起交流。
6、更多好文
微服务精品学习线路图,收藏慢慢看!
什么是分布式事务、CAP、BASE 理论?
分布式事务中的2PC是什么?
分布式事务中的3PC是什么?
分布式事务中的2PC是什么?
分布式事务之TCC
分布式事务之可靠消息
分布式事务之最大努力通知型
---------- END ----------
欢迎关注我的公众号“架构师学习营”,如果有收获,麻烦点一下“在看”~
标签:date insert 公众号 没有 update from 创建 ref n+1
原文地址:https://blog.51cto.com/14977534/2545951