衍生到微服务领域,幂等指的是使用相同的参数屡次调用相同的API,对后端产生的影响是一致的,许多人理解为屡次调用返回的结果是同样,这种观点是错误的,连最基本的查询接口也不多是屡次查询返回一样的结果,幂等的侧重点是对后端的影响,并不关心返回的数据。幂等是全部客户端-服务端系统都须要考虑的问题,不管你是C-S仍是B-S模式,但在B-S模式下,这个问题更为突出,尤为是近几年流行的微服务架构下,这是由于在微服务模式下,单个应用简单,但服务总体更为复杂,完成一个功能须要走较长的调用链,总体链路可能由不一样的语言不一样框架实现,每一个微服务为了保证服务的质量,经常会对一些不肯定的因素(如:网络异常、资源耗尽等)致使的问题进行容错处理,典型措施就是重试。上图是互联网应用中很是精简的调用流程,应该说许多公司的链路远比这个复杂,流程中的每一个环节均可能出现重试:前端
若是请求只涉及到资源查询,显然调用屡次并不会对后端数据发生更改,因此查询类的API自然就是幂等的,但若是这是一个创单接口,咱们就不得不考虑幂等的问题,创单过程当中会涉及到库存扣减、余额扣减、订单数据入库、消息通知等等修改后端资源的操做,为了防止这类请求重复提交到后端,前端页面一般会在用户点击提交后禁用按钮,后端成功后清空表单跳转到提示页面,对于后端服务来说,一般会采用如下方式实现幂等:java
Token机制的核心就是要求客户端的每次请求里必须携带一个UUID,产生UUID的算法不少,如:雪花算法,ObjectID,经常使用的开发语言也有对应的实现,即便client生成UUID有困难,也能够调用ID生成器预先生成一批缓存到本地,这里就不一一展开。有了这个UUID,能够在多个环节实现拦截,并且这种判断是很是高效的,几乎都是O(1)的时间复杂度,远比数据库惟一约束判断快,譬如在nginx里,咱们可使用lua获取到请求里的UUID,将该UUID放入leveldb、redis、memcache,下次请求时判断该值是否存在,存在直接返回错误不然放行,若是不是使用nginx或者实施上述方案有困难,能够在网关层实现,对于java语言(其余语言也相似),能够作到透明化处理:在网关里注册Idempotentfilter,该filter提取UUID,一样经过leveldb、redis、memcache等高速缓存判断是否能够放行,显然token方案能够尽早发现和拦截订单,大大下降资源消耗,减小数据库压力,对业务也是透明无浸入,但只依赖token机制显然是有缺陷的:当缓存服务出错ldb文件丢失,redis数据意外清空,memcache意外重启等,会致使咱们的UUID标志丢失,这时就须要数据库来兜底,数据库的惟一约束是不可或缺的,当出现这些极端状况时,即便请求达到DB,也不会形成数据重复。有幂等需求的接口,建议采用token机制实现高效的排除重复请求,固然最终落地式须要结合具体的业务场景.nginx