分布式环境下的服务幂等一
Posted 马小琥
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分布式环境下的服务幂等一相关的知识,希望对你有一定的参考价值。
1,背景
当前互联网技术的发展,数据量的剧增,单机模式下已经无法满足我们的业务支撑,因此很多大型的网站和应该都采用基于多机器的集群环境来构建自己的分布式应用。
构建分布式系统相比于单机来说要复杂的多,其重要的一个因素就是系统之间的通信和数据交互受网络因素的影响增大。对应单机服务来说,一个接口调用,无非就是响应成功或者响应失败,但是对于跨进程来说,就会出现另外一种情况:服务超时。
2,案例
集群环境下:A,B位于不同的进程,当A向B发起请求时,在允许最大的等待时间内没有返回结果,就会认定为请求超时了,此时进程A就无法明确结果,什么也干不了(没有返回结果,不知道是成功还是失败,下面的业务逻辑就无法继续进行)
1,进程B执行成功:A将数据传输给B,B执行成功,可能因网络环境影响,A没有收到B的执行结果,认为超时。
2,进程B执行失败: 和成功类似
3,未执行: A在给B发送数据的过程中失败了,或者发送数据成功了,B所在的服务并没有成功消费调A给的数据等等。。
3,幂等性
超时问题在分布式应用中是必须解决的问题,否则就失去了意义,这种情况下,一般会采用让进程A尝试重试-------即重复发起之前的调用。但是就可能带来新的问题,比如,之前的操作如果已经发起成功了(在这里,针对查询操作相对还好,但是对于新增,修改操作,就没法玩了),于是幂等概念就出现了。
幂等性的定义:幂等性本来是一个数学概念,在计算机中,表示对同一个过程应用相同的参数多次和应用一次产生的效果是一样,这样的过程即被称为满足幂等性
幂等:
update test_user set user_age = 25 where user_id = 2 ,这中情况无论执行多少次,结果都不受影响,所以是幂等的。
非幂等:
update test_user set user_times = user_times + 1 where user_id = 2, 这样的更新语句每执行一次,结果都会不一样,所以是非幂等的。
4,幂等性的实现
在考虑实现幂等之前,先看看有哪些操作是天然幂等的,如上述幂等与非幂等的案例。
业务系统实现幂等的通用方式:在业务库中建一张排重表,针对业务主键建一个unique index.实现如下:
begin transaction;
count = insert ignore dup_forbidden (...biz_id...) value(...biz_id...)
if (count > 0) {
f(biz_id)
}
commit;
假设一种场景:在一个面向交易的一个分布式应用中,支付完成后支付子系统通知订单子系统,如果通过rpc调用函数f(),不管是同步还是异步,都可能存在超时,为了支持重试,我们必须保证f()是幂等的。如果已支付,直接返回成功,如果未支付,需要锁定订单(乐观锁或者悲观锁,防止并发,锁的具体实现方式就没必要在此细说了),修改订单状态,指定其他操作。当然基于悲观锁的实现在高并发系统环境下是不推荐的,大家不要断章取义,毕竟长时间的锁会降低系统的TPS.
针对分布式服务框架下的幂等性实现原理(dubbo,spring cloud),欲知后事如何,请听下次分解,ps:求大神指点文章排版技巧,留言有红包。
以上是关于分布式环境下的服务幂等一的主要内容,如果未能解决你的问题,请参考以下文章
基于redis(lua)和zookeeper分布式锁(秒杀)实现,分布式接口幂等实现,分布式速率限制实现,分布式ID生成器实现