分布式系统关联查询_分布式系统的幂等性你们是怎么设计的?

公众号关注 “架构师学习营”

设为 “星标”,带你学习更多架构师知识!

大家好,这里是架构师学习营

本文和探讨一下分布式系统中幂等性的设计。

1、什么是幂等性?

对于同一笔业务,执行一次或者多次,产生的结果都是一样的,幂等性主要是为了解决重复处理的问题。

2、来看一个场景

我们有个电商系统,可以通过支付宝进行充值。

用户看到的过程如下:

1.电商网站,用户输入金额,点击充值

2.电商生成充值订单,订单状态为待支付

3.跳转到支付宝页面,用户确定支付

4.支付那边操作完成之后,会携带充值结果重定向到商户的结果页面,此时页面显示充值成功

此时电商中的充值订单并没有去修改,而支付宝会将充值结果异步通知给电商。

电商系统接收到充值通知结果之后,处理过程如下:

if(判断订单状态是否为待支付){ //@1
 给用户账户加钱
 将订单状态置为充值成功
}

可能会由于网络故障,通知无法到达商户,所以支付宝为了让通知能够达到商户,可能会出现并发重复通知的情况。

若支付宝同时来了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、更多好文

  1. 微服务精品学习线路图,收藏慢慢看!
  2. 什么是分布式事务、CAP、BASE 理论?
  3. 分布式事务中的2PC是什么?
  4. 分布式事务中的3PC是什么?
  5. 分布式事务中的2PC是什么?
  6. 分布式事务之TCC
  7. 分布式事务之可靠消息
  8. 分布式事务之最大努力通知型
----------  END  ----------欢迎关注我的公众号“架构师学习营”,如果有收获,麻烦点一下“在看”~

54cf4b02d8a7a9554932881a62b93ab7.png

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值