幂等简单的定义:
系统中的多次操作,不管多少次,都应该产生一样的效果,或返回一样的效果。
比如实际的业务请求为创建一个活动,理论上需要根据业务形态开发幂等创建活动的接口,这样在相同参数调用接口多次创建活动时,只可以创建成功一次。
由于查询天生的是幂等请求,所以针对于查询场景可以不做业务角度的幂等约束,查询幂等的约束多是针对于资源控制,安全防刷,流控来做的。
试想有这样一个场景: A系统传递userId和活动Id调用B系统发券,如果B系统发券成功,需要返回A系统本次发券userId和发券code。 由于B系统需要对自己发出去的券进行限制防止超发,所以会根据userId和code建立幂等拦截。 但是A系统的调用次数是不受信的,B系统会对多次重复的请求做拦截,这样造成一部分A的请求为无效请求,被直接打回。 但是A系统接受B系统的返回值中是需要code的,如果没有收到code,A系统会认为调用B系统失败,进行重试,结果就造成了A系统不停被重试,B系统拦截无效请求,返回默认值,A再重试的死循环。
解决这个场景问题有两种方法:
第一种方案明显的缺点在于,针对于重复发送的请求都会转化成一次查询操作,这样无形中加大了对于B系统资源的浪费,同时由于发券接口逻辑中引入了查询逻辑,造成此接口违反了“单一职能原则”,在未来围绕这个接口的新业务逻辑造成的代码修改时,比如允许对同一个用户发送多张券,可能出现潜在的bug问题。
第二种方案则是我选择的更好的方案,也是更支持的方案,一个接口最好只做一件事,这样一个接口只做发券,同时对于多次重复发券做请求拦截,没有必要放无效请求到系统核心逻辑中,更没有必要因此引入查询逻辑消耗系统资源。 在调用B系统发券接口因为拦截重复请求,返回重复请求状态码后,系统A调用B系统的查询接口,进行已发送code的查询,这样在使用角度和后期业务迭代角度及系统资源使用和未来优化角度来说,都存在一定的空间,而不会造成代码复杂度提升引入隐患bug。
针对于幂等操作还有如下几种方案: