精华内容
下载资源
问答
  • 微服务架构幂等

    2019-04-11 10:18:45
    微服务幂等性 微服务架构 微服务架构是一种架构概念,旨在通过将功能分解到各个离散的服务中以实现对解决方案的解耦。它的主要作用是将功能分解到离散的各个服务当中,从而降低系统的耦合性,并提供更加灵活...

    目录

    • 微服务架构
      • 单体应用的优缺点
      • 微服务的优缺点
      • 微服务网关+服务间通信
      • 服务间通信
      • 服务发现
      • 微服务幂等性
    •  

    微服务架构

    微服务架构是一种架构概念,旨在通过将功能分解到各个离散的服务中以实现对解决方案的解耦。它的主要作用是将功能分解到离散的各个服务当中,从而降低系统的耦合性,并提供更加灵活的服务支持。

    和 微服务 相对应的,这种方式一般被称为 单体式开发(Monolithic)。既所有的功能打包在一个 WAR 包里,基本没有外部依赖(除了容器),部署在一个 JavaEE 容器(Tomcat,JBoss,WebLogic)里,包含了 DO/DAO,Service,UI 等所有逻辑。

    单体应用的优缺点:

    img

    优点:

    • 开发简单,集中式管理
    • 基本不会重复开发
    • 功能都在本地,没有分布式的管理和调用消耗

    缺点:

    • 效率低:开发都在同一个项目改代码,相互等待,冲突不断
    • 维护难:代码功能耦合在一起,新人不知道何从下手
    • 不灵活:构建时间长,任何小修改都要重构整个项目,耗时
    • 稳定性差:一个微小的问题,都可能导致整个应用挂掉
    • 扩展性不够:无法满足高并发下的业务需

    微服务的优缺点:

    img

    优点:

    • 它解决了复杂问题。它把可能会变得庞大的单体应用程序分解成一套服务
    • 这种架构使得每个服务都可以由一个团队独立专注开发
    • 微服务架构模式可以实现每个微服务独立部署
    • 微服务架构模式使得每个服务能够独立扩展

    缺点(挑战):

    • 微服务是一个分布式系统,其使得整体变得复杂。开发人员需要基于RPC或者消息实现微服务之间的调用和通信,而这就使得服务之间的发现、服务调用链的跟踪和质量问题变得的相当棘手。
    • 分区的数据库体系和分布式事务。更新多个业务实体的业务交易相当普遍。这些类型的事务在单体应用中实现非常简单,因为单体应用往往只存在一个数据库。但在微服务架构下,不同服务可能拥有不同的数据库。CAP原理的约束,使得我们不得不放弃传统的强一致性,而转而追求最终一致性,这个对开发人员来说是一个挑战。
    • 跨越多服务变更。在单体应用程序中,您可以简单地修改相应的模块、整合变更并一次性部署他们。相反,在微服务中您需要仔细规划和协调出现的变更至每个服务。
    • 部署基于微服务的应用程序也是相当复杂的
    • 测试

    以上问题和挑战可大体概括为:

    • API Gateway
    • 服务间调用
    • 服务发现
    • 服务容错
    • 服务部署
    • 数据调用

    目前流行的两种微服务框架解决方案(可以解决以上问题)

    • SpringBoot + SpringCloud
      • SpringBoot是 Spring 的一套快速配置框架,可以基于spring boot 快速开发单个微服务
      • Spring Cloud基于Spring Boot,为微服务体系开发中的架构问题提供了一整套的解决方案——服务注册与发现,服务消费,服务保护与熔断,网关,分布式调用追踪,分布式配置管理等路由网关
    • Dubbo + ZooKeeper
      • Dubbo是一个阿里巴巴开源出来的一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。
      • ZooKeeper用来实现服务的注册与发现和进行负载均衡

    基于微服务架构的应用是分布式系统,增加了系统设计和实现的难度,主要有以下方面:

    • 运行环境中,微服务实例的网络地址是动态分配的,微服务运行的实例是动态变化的,需要一套发现机制,使服务调用者可以获取正确的服务地址。
    • 服务之间存在着复杂的依赖关系,在高并发访问下,依赖的稳定性影响系统的可用性及性能,因此需要提供容错机制,当依赖的服务发生故障时,不会使调用方线程被长时间占用不释放,避免故障在系统中蔓延。
    • 需要一个高效的进程间通信机制支持微服务之间的交互
    • 服务实例的启停及流量的调度和分配需要一套负载监控和负载均衡组件来管理。

    微服务架构的基本组件

    • 可持续交付的平台
    • 服务注册与发现组件(ZooKeeper)
    • 服务网关

    一般微服务在系统内部,通常是无状态的,用户登入信息和权限管理最好有一个统一的地方维护管理(OAuth)。(类似SSO单点登入)

    API网关 + 服务间通信

    • 一般在后台 N 个服务和 UI 之间一般会一个代理或者叫 API Gateway
      • 提供统一服务入口,让微服务对前台透明
      • 聚合后台的服务,节省流量,提升性能(PC、Android/IOS端只需记住API网关的IP,API网关会有一个后台服务IP列表)
      • 提供安全,过滤,流控等API管理功能
      • 其实这个 API Gateway 可以有很多广义的实现办法,可以是一个软硬一体的盒子,也可以是一个简单的 MVC 框架,甚至是一个 Node.js 的服务端

    img

    所有的微服务都是独立的 Java 进程跑在独立的虚拟机上,所以服务间的通信就是 IPC(Inter Process Communication),已经有很多成熟的方案。现在基本最通用的有两种方式

    服务间通信

    同步调用(阻塞)

    服务间通信:网络中只有字符串可以穿透防火墙

    • REST(JAX-RS,Spring Boot):Http通信
    REST
        api
         String json = /users/list;
         USer user = new USer();
         user.setId(json.getId());
    • RPC(Thrift, Dubbo):远程过程调用 User user = new RPCUser();

    同步调用比较简单,一致性强,但是容易出调用问题,性能体验上也会差些,特别是调用层次多的时候。一般 REST 基于 HTTP,更容易实现,更容易被接受,服务端实现技术也更灵活些,各个语言都能支持,同时能跨客户端,对客户端没有特殊的要求,只要封装了 HTTP 的 SDK 就能调用,所以相对使用的广一些。RPC 也有自己的优点,传输协议更高效,安全更可控,特别在一个公司内部,如果有统一个的开发规范和统一的服务框架时,他的开发效率优势更明显些。就看各自的技术积累实际条件,自己的选择了。
    (对外REST,对内RPC)

    异步消息调用

    • Kafka
    • Notify
    • MessageQueue

    异步消息的方式在分布式系统中有特别广泛的应用,他既能减低调用服务之间的耦合,又能成为调用之间的缓冲,确保消息积压不会冲垮被调用方,同时能保证调用方的服务体验,继续干自己该干的活,不至于被后台性能拖慢。不过需要付出的代价是一致性的减弱,需要接受数据 最终一致性;还有就是后台服务一般要实现 幂等性,因为消息送出于性能的考虑一般会有重复(保证消息的被收到且仅收到一次对性能是很大的考验);最后就是必须引入一个独立的 Broker(消息队列的中间服务器)

    Broker.png

    服务发现

    在微服务架构中,一般每一个服务都是有多个拷贝,来做负载均衡。一个服务随时可能下线,也可能应对临时访问压力增加新的服务节点。服务之间如何相互感知?服务如何管理?

    这就是服务发现的问题了。一般有两类做法,也各有优缺点。基本都是通过 Zookeeper 等类似技术做服务注册信息的分布式管理。当服务上线时,服务提供者将自己的服务信息注册到 ZK(或类似框架),并通过心跳维持长链接,实时更新链接信息。服务调用者通过 ZK 寻址,根据可定制算法,找到一个服务,还可以将服务信息缓存在本地以提高性能。当服务下线时,ZK 会发通知给服务客户端。

    ZooKeeper实现了分布式锁,解决单点故障问题

    服务注册

    服务注册与发现.png

    Dubbo是一个RPC通信框架;ZooKeeper服务注册与发现。此处两者结合使用。

    • 基于客户端的服务注册与发现

    优点是架构简单,扩展灵活,只对服务注册器依赖。缺点是客户端要维护所有调用服务的地址,有技术难度,一般大公司都有成熟的内部框架支持,比如 Dubbo。
    此处调用可以是Dubbo,服务注册为ZooKeeper

    img

    • 基于服务端的服务注册与发现

    优点是简单,所有服务对于前台调用方透明,一般在小公司在云服务上部署的应用采用的比较多。

    LB为负载均衡服务器,由LB去查询注册中心,再去调用对应指定的服务

    img

    微服务需要考虑的问题:

    • API Gateway
    • 服务间调用
    • 服务发现
    • 服务容错
    • 服务部署
    • 数据调用

    微服务幂等性

    分布式系统中的幂等性概念:用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。

    幂等场景:

    可能会发生重复请求或消费的场景,在微服务架构中是随处可见的。

    • 网络波动:因网络波动,可能会引起重复请求
    • 分布式消息消费:任务发布后,使用分布式消息服务来进行消费

    • 用户重复操作:用户在使用产品时,可能无意地触发多笔交易,甚至没有响应而有意触发多笔交易
    • 未关闭的重试机制:因开发人员、测试人员或运维人员没有检查出来,而开启的重试机制(如Nginx重试、RPC通信重试或业务层重试等)

    CRUD操作分析

    • 新增类请求:不具备幂等性

    • 查询类动作:重复查询不会产生或变更新的数据,查询具有天然幂等性

    • 更新类请求:
      • 基于主键的计算式Update,不具备幂等性,即UPDATE goods SET number=number-1 WHERE id=1
      • 基于主键的非计算式Update:具备幂等性,即UPDATE goods SET number=newNumber WHERE id=1
      • 基于条件查询的更新,不一定具备幂等性(需要根据实际情况进行分析判断)
    • 删除类请求:
      • 基于主键的Delete具备幂等性
      • 一般业务层面都是逻辑删除(即update操作),而基于主键的逻辑删除操作也是具有幂等性的

    幂等性的重要性

    针对一个微服务架构,如果不支持幂等操作,那将会出现以下情况:

    • 电商超卖现象
    • 重复转账、扣款或付款
    • 重复增加金币、积分或优惠券

    超卖现象
    ​ 比如某商品的库存为1,此时用户1和用户2并发购买该商品,用户1提交订单后该商品的库存被修改为0,而此时用户2并不知道的情况下提交订单,该商品的库存再次被修改为-1这就是超卖现象。

    ​ 究其深层原因,是因为数据库底层的写操作和读操作可以同时进行,虽然写操作默认带有隐式锁(即对同一数据不能同时进行写操作)但是读操作默认是不带锁的,所以当用户1去修改库存的时候,用户2依然可以都到库存为1,所以出现了超卖现象。

    ​ 解决方案A:可以对读操作加上显式锁(即在select …语句最后加上for update)这样一来用户1在进行读操作时用户2就需要排队等待了。但问题来了,如果该商品很热门并发量很高那么效率就会大大的下降,如何解决呢?(解决方案B)

    ​ 解决方案B:我们可以有条件有选择的在读操作上加锁,比如可以对库存做一个判断,当库存小于一个量时开始加锁,让购买者排队,这样一来就解决了超卖现象。

    解决方案

    • 全局唯一ID

    如果使用全局唯一ID,就是根据业务的操作和内容生成一个全局ID,在执行操作前先根据这个全局唯一ID是否存在,来判断这个操作是否已经执行。如果不存在则把全局ID,存储到存储系统中,比如数据库、Redis等。如果存在则表示该方法已经执行。

    使用全局唯一ID是一个通用方案,可以支持插入、更新、删除业务操作。但是这个方案看起来很美但是实现起来比较麻烦,下面的方案适用于特定的场景,但是实现起来比较简单。

    • 去重表

    这种方法适用于在业务中有唯一标识的插入场景中,比如在以上的支付场景中,如果一个订单只会支付一次,所以订单ID可以作为唯一标识。这时,我们就可以建一张去重表,并且把唯一标识作为唯一索引,在我们实现时,把创建支付单据写入去重表,放在一个事务中,如果重复创建,数据库会抛出唯一约束异常,操作就会回滚。

    • 插入或更新

    这种方法插入并且有唯一索引的情况,比如我们要关联商品品类,其中商品的ID和品类的ID可以构成唯一索引,并且在数据表中也增加了唯一索引。这时就可以使用InsertOrUpdate操作。

    • 多版本控制

    这种方法适合在更新的场景中,比如我们要更新商品的名字,这时我们就可以在更新的接口中增加一个版本号,来做幂等:boolean updateGoodsName(int id,String newName,int version);

    在实现时可以如下:update goods set name=#{newName},version=#{version} where id=#{id} and version<${version}

    • 状态机控制

    这种方法适合在有状态机流转的情况下,比如就会订单的创建和付款,订单的付款肯定是在之前,这时我们可以通过在设计状态字段时,使用int类型,并且通过值类型的大小来做幂等,比如订单的创建为0,付款成功为100,付款失败为99。在做状态机更新时,我们就这可以这样控制:update goods_order set status=#{status} where id=#{id} and status<#{status}

    以上就是保证接口幂等性的一些方法。

    总结

    幂等性设计不能脱离业务来讨论,一般情况下,去重表同时也是业务数据表,而针对分布式的去重ID,可以参考以下几种方式:

    • UUID
    • Snowflake
    • 数据库自增ID
    • 业务本身的唯一约束
    • 业务字段+时间戳拼接
    展开全文
  • 安全架构-幂等性设计-SQL

    千次阅读 2020-12-20 22:35:06
    安全架构-幂等性设计 幂等性设计的文章有几篇了,虽然侧重点不一样分为了api幂等,http幂等,sql幂等,实际上是一回事。 本篇从侧重SQL语句操作入手介绍sql操作保证的幂等性。 文章目录安全架构-幂等性设计前言一、...

    安全架构-幂等性设计

    幂等性设计的文章有几篇了,虽然侧重点不一样分为了api幂等,http幂等,sql幂等,实际上是一回事。
    本篇从侧重SQL语句操作入手介绍sql操作保证的幂等性。



    前言

    一、SQL幂等场景

    一、查询,select * from user where xxx,不会对数据产生任何变化,具备幂等性。

    二、新增,insert into user(userid,name) values(1,'a'),

    如userid为唯一主键,即重复操作上面的业务,只会插入一条用户数据,具备幂等性。
    如userid不是主键,可以重复,那上面业务多次操作,数据都会新增多条,不具备幂等性。
    三、修改,区分直接赋值和计算赋值。

    1、直接赋值,update user set point = 20 where
    userid=1,不管执行多少次,point都一样,具备幂等性。
    2、计算赋值,update user set point = point+ 20 where userid=1,每次操作point数据都不一样,不具备幂等性。

    四、删除,delete from user where userid=1,多次操作,结果一样,具备幂等性。

    上面场景中,我们发现新增没有唯一主键约束的数据,和修改计算赋值型操作都不具备幂等性。

    二、解决方案

    1.token机制

    跟api接口保持幂等性使用的token机制一样,此处参考知乎享学课堂的图
    在这里插入图片描述
    上图就是token+redis的幂等方案,适用绝大部分场景。主要思想:

    1、服务端提供了发送token的接口。我们在分析业务的时候,哪些业务是存在幂等问题的,就必须在执行业务前,先去获取token,服务器会把token保存到redis中。(微服务肯定是分布式了,如果单机就适用jvm缓存)
    2、然后调用业务接口请求时,把token携带过去,一般放在请求头部。
    3、服务器判断token是否存在redis中,存在表示第一次请求,可以继续执行业务,执行业务完成后,最后需要把redis中的token删除。
    4、如果判断token不存在redis中,就表示是重复操作,直接返回重复标记给client,这样就保证了业务代码,不被重复执行。
    这种方案是比较常用的方案,也是网上经常介绍的,但是有一点不同的地方:

    网上方案:检验token存在(表示第一次请求)后,就立刻删除token,再进行业务处理
    上面方案:检验token存在(表示第一次请求)后,先进行业务处理,再删除token
    关键点就是 先删除token,还是后删除token。

    一、网上方案缺点

    我们看下网上方案,先删除token,这是出现系统问题导致业务处理出现异常,业务处理没有成功,接口调用方也没有获取到明确的结果,然后进行重试,但token已经删除掉了,服务端判断token不存在,认为是重复请求,就直接返回了,无法进行业务处理了。
    二、上面方案缺点

    后删除token也是会存在问题的,如果进行业务处理成功后,删除redis中的token失败了,这样就导致了有可能会发生重复请求,因为token没有被删除。
    小伙伴们有没有发现,其实上面的问题就是数据库和缓存redis数据不一致的问题。之前老顾分享了一篇文章,里面详细介绍了如何解决数据库和缓存redis数据不一致的问题。小伙伴们可自行查阅。

    其实根据这个场景的业务,可以有个简单的处理方式。老顾推荐是网上方案先删除token,先保证不会因为重复请求,业务数据出现问题。顶多再让用户处理一次。
    出现业务异常,可以让调用方配合处理一下,重新获取新的token,再次由业务调用方发起重试请求就ok了。

    token机制缺点
    小伙伴们有没有发现,业务请求每次请求,都会有额外的请求(一次获取token请求、判断token是否存在的业务)。其实真实的生产环境中,1万请求也许只会存在10个左右的请求会发生重试,为了这10个请求,我们让9990个请求都发生了额外的请求。(当然redis性能很好,耗时不会太明显)

    2.乐观锁机制

    sql语句增加版本号

    update user set point = point + 20, version = version + 1 
    where userid=1 and version=1
    

    加上了版本号后,就让此计算赋值型业务,具备了幂等性。

    乐观锁机制缺点
    就是在操作业务前,需要先查询出当前的version版本。

    3.唯一主键机制

    这个机制是利用了数据库的主键唯一约束的特性,解决了在insert场景时幂等问题。但主键的要求不是自增的主键,这样就需要业务生成全局唯一的主键,
    如果是分库分表场景下,路由规则要保证相同请求下,落地在同一个数据库和同一表中,要不然数据库主键约束就不起效果了,因为是不同的数据库和表主键不相关。

    因为对主键有一定的要求,这个方案就跟业务有点耦合了,无法用自增主键了。

    4.去重表机制

    这个方案业务中要有唯一主键,这个去重表中只要一个字段就行,设置唯一主键约束,当然根据业务自行添加其他字段
    在这里插入图片描述
    上面的主要流程就是 把唯一主键插入去重表,再进行业务操作,且他们在同一个事务中。这个保证了重复请求时,因为去重表有唯一约束,导致请求失败,避免了幂等问题。

    这里要注意的是,去重表和业务表应该在同一库中,这样就保证了在同一个事务,即使业务操作失败了,也会把去重表的数据回滚。这个很好的保证了数据一致性。
    这个方案也是比较常用的,去重表是跟业务无关的,很多业务可以共用同一个去重表,只要规划好唯一主键就行了。

    去重表机制缺点
    多增加一个表的插入操作。

    总结

    幂等性相关的介绍有几篇文章了,可以看到,解决机制有多种,选择最适合自己的就可以。但是其中,我们能总结发现,有数据库操作的情况下,唯一主键和乐观锁比较简单方便,业务接口方面,token+redis机制和source+seq机制比较方便。

    参考资料:
    https://zhuanlan.zhihu.com/p/74046140
    https://www.cnblogs.com/javalyy/p/8882144.html

    展开全文
  • 安全架构-HTTP协议幂等

    千次阅读 2020-12-19 13:15:39
    幂等性设计是架构师必须具备的技能之一,需要深入理解幂等性设计的相关原理和解决方法。 上一篇文章中介绍了api接口的幂等性,主要从业务逻辑处理的方面进行业务保障,做到实现幂等性。本文介绍HTTP协议本身在幂等...

    安全架构-HTTP协议幂等性

    幂等性设计是架构师必须具备的技能之一,需要深入理解幂等性设计的相关原理和解决方法。


    上一篇文章中介绍了api接口的幂等性,主要从业务逻辑处理的方面进行业务保障,做到实现幂等性。本文介绍HTTP协议本身在幂等性方面的设计。


    前言

    HTTP协议是当前rpc,分布式架构,微服务架构中应用最广泛的协议之一,对HTTP需要有深入的了解,后续也将编写HTTP协议知识相关的系列文章,本文只介绍HTTP协议幂等性方面的设计。


    一、http幂等性

    首先看http协议网关里介绍的幂等性。

    9.1 Safe and Idempotent Methods
    9.1.1 Safe Methods
    Implementors should be aware that the software represents the user in their interactions over the Internet, and should be careful to allow the user to be aware of any actions they might take which may have an unexpected significance to themselves or others.

    In particular, the convention has been established that the GET and HEAD methods SHOULD NOT have the significance of taking an action other than retrieval. These methods ought to be considered “safe”. This allows user agents to represent other methods, such as POST, PUT and DELETE, in a special way, so that the user is made aware of the fact that a possibly unsafe action is being requested.

    Naturally, it is not possible to ensure that the server does not generate side-effects as a result of performing a GET request; in fact, some dynamic resources consider that a feature. The important distinction here is that the user did not request the side-effects, so therefore cannot be held accountable for them.

    9.1.2 Idempotent Methods
    Methods can also have the property of “idempotence” in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request. The methods GET, HEAD, PUT and DELETE share this property. Also, the methods OPTIONS and TRACE SHOULD NOT have side effects, and so are inherently idempotent.

    However, it is possible that a sequence of several requests is non- idempotent, even if all of the methods executed in that sequence are idempotent. (A sequence is idempotent if a single execution of the entire sequence always yields a result that is not changed by a reexecution of all, or part, of that sequence.) For example, a sequence is non-idempotent if its result depends on a value that is later modified in the same sequence.

    A sequence that never has side effects is idempotent, by definition (provided that no concurrent operations are being executed on the same set of resources).

    官网地址:https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

    二、http请求方式简述

    在这里插入图片描述
    1、OPTIONS
    返回服务器针对特定资源所支持的HTTP请求方法,也可以利用向web服务器发送‘*’的请求来测试服务器的功能性
    2、HEAD
    向服务器索与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以再不必传输整个响应内容的情况下,就可以获取包含在响应小消息头中的元信息。
    3、GET
    向特定的资源发出请求。注意:GET方法不应当被用于产生“副作用”的操作中,例如在Web Application中,其中一个原因是GET可能会被网络蜘蛛等随意访问。Loadrunner中对应get请求函数:web_link和web_url
    4、POST
    向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。 Loadrunner中对应POST请求函数:web_submit_data,web_submit_form
    5、PUT
    向指定资源位置上传其最新内容
    6、DELETE
    请求服务器删除Request-URL所标识的资源
    7、TRACE
    回显服务器收到的请求,主要用于测试或诊断
    8、CONNECT
    HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
    注意:
    1)方法名称是区分大小写的,当某个请求所针对的资源不支持对应的请求方法的时候,服务器应当返回状态码405(Mothod Not Allowed);当服务器不认识或者不支持对应的请求方法时,应返回状态码501(Not Implemented)。
    2)HTTP服务器至少应该实现GET和HEAD/POST方法,其他方法都是可选的,此外除上述方法,特定的HTTP服务器支持扩展自定义的方法。

    三、HTTP 协议的幂等性

    以我们常见的四种 HTTP method 为例,加深我们对幂等这个概念的理解。

    GET
    GET 操作是幂等的,原因是 GET 操作根本不会对服务器产生任何修改。有人可能会说我们访问 GET /last_news 可能每次拿到的结果都不一样,这里幂等的一致性指的是数据库的最终的存储结果,而不是调用方拿到的返回结果

    PUT
    PUT 方法通常是对已经存在的资源进行修改,也是幂等的。比如我们发起多个把 A 替换成 B 的请求,最终的结果还会是 B

    DELETE
    DELETE 方法也是幂等的,例如我们连续发起多个对 A 的删除请求,如果第一个成功的话,后面的请求都应返回资源找不到的错误

    POST
    POST 一般是指新增资源,不是幂等的。如果连续发起三个 A 资源的增加,最终的结果会是三个 A 资源,而不是一个

    总结

    HTTP协议在部分请求中考虑了幂等性,在POST请求中,如果需要幂等性处理,就需要结合前文中api接口幂等性设计来处理。

    参考资料
    https://www.cnblogs.com/weibanggang/p/9454581.html

    展开全文
  • 架构设计 | 幂等

    2018-01-07 10:03:08
    什么是幂等性 抄用一段数学上的定义:f(f(x)) = f(x)。x被函数f作用一次和作用无限次的结果是一样的。幂等性应用在软件系统中,我把它简单定义为:某个函数或者某个接口使用相同参数调用一次或者无限次,其造成的...

    什么是幂等性

    抄用一段数学上的定义:f(f(x)) = f(x)。x被函数f作用一次和作用无限次的结果是一样的。幂等性应用在软件系统中,我把它简单定义为:某个函数或者某个接口使用相同参数调用一次或者无限次,其造成的后果是一样的,在实际应用中一般针对于接口进行幂等性设计。举个栗子,在系统中,调用方A调用系统B的接口进行用户的扣费操作时,由于网络不稳定,A重试了N次该请求,那么不管B是否接收到多少次请求,都应该保证只会扣除该用户一次费用。

    幂等性设计

    幂等性一般应用于协议设计,TCP协议支持幂等吗?答案是肯定的,在网络不稳定时,操作系统可以肆无忌惮的重发TCP报文片段。TCP协议能够保证幂等的核心在于sequence number字段,一个序列号的在较长的一段时间内均不会出现重复。对于应用层的协议设计,原理和TCP是类似的,我们需要一个不重复的序列号。再简单一点说,在一个业务流程的处理中,我们需要一个不重复的业务流水号,以保证幂等性。

    举个实际应用场景:用户A在网页上发起一笔游戏充值请求,浏览器引导用户去银行支付,支付成功后系统给用户进行充值。

    协议设计上,我们通过全局唯一的充值订单号贯穿整个业务流程,使该业务支持幂等。

    应用实现上,我们列举在银行支付成功后回调系统,进行充值的步骤进行说明。

    func pay_notify(orderid,value,state){//有问题的实现  
             order = db.query("select * from payorder where orderid=$orderid");  
             check(order,orderid,value,state);//判断支付金额是否与订单金额一致,判断是否是支付成功回调。  
             if(order.state=='未支付'){  
                db.update("update payorder set state='已支付' where orderid=$orderid");  
                charge(order.username,value);//执行充值  
             }else{  
             return result("订单已处理")//返回订单已处理,或者返回处理成功  
            }  
        }  

    上述实现的问题在于,当回调出现并发时,order.state已经是脏读了,有可能重复充值,该实现并不能100%保证幂等。

    列举三种改进方式:

    1. 悲观锁:select for update,整个执行过程中锁定该订单对应的记录;
    2. 乐观锁:affectrows = db.update(“update payorder set state=’已支付’ where orderid=$orderid and state=’未支付’ “),如果affectrows=1,执行充值,否则返回已处理;
    3. 定义notifylog表,orderid为unique key或者primary key,执行前,先insert,若insert成功则执行充值,否则返回已处理;

    以上简单例子用以说明幂等性常用应用实现,在SOA化系统中,可能很多原子功能都被拆分到不同的进程里,如charge充值这个函数,可能在另一个进程中,那么整个业务的链路就会更长,可能回调成功了,但是充值失败。同理,只要充值接口保证幂等性,对于已经回调过但是充值结果未返回的请求,回调接收程序,应当重复发起充值请求。更深入更复杂的应用场景,在数据一致性中再细讲。

    总结

    业务层设计协议时,要求请求方定义不重复的业务流水号。应用实现时,利用数据库乐观锁、插入unique key的日志等方式保证并发时的幂等。

    幂等性把关环节,在协议设计评审中,评审重要业务RPC或者http接口是否支持幂等,代码评审中,重点把关请求并发时,是否仍旧能够保证幂等性。设计人员和具体实现人员在实现过程中,也应该时刻自审幂等性的实现是否过关。

    展开全文
  • Java架构篇rest api 幂等

    千次阅读 2018-09-14 11:08:03
    为什么需要幂等性 在设计rest api的时候,调用方由于逻辑问题或者网络问题,超时导致的retry都可能对rest接口进行多次调用,所以rest api设计的时候注意幂等性。 哪些是幂等操作 安全:不改变资源的...
  • 安全架构-api接口幂等性设计

    千次阅读 2020-12-19 12:37:30
    安全架构-api接口幂等性设计 今天开始研究API接口相关的安全性,api接口在当前互联网开发,分布式RPC,微服务架构,RESTful架构中,应用非常广泛,注意api接口的安全,也是架构师必须熟练且牢记的意识和技能。 api...
  • 跨中心微服务操作需要进行幂等验证,分布式微服务架构服务间频繁使用网络通信,由于网络不可靠网络震荡、客户端重试都导致产生重复请求,传统方式根据流水查询日志表无法保证高并发情况下的众多分布式微服务幂等。...
  • 架构思想之-不一样的幂等设计什么是幂等?为什么要保证幂等?抛开问题看本质,解决幂等最关键是啥? 什么是幂等? 简单一句话说,就是相同的请求,任何时刻,任何地点,任何次数。效果都是一样。 举例:订单支付接口...
  • 为什么80%的码农都做不了架构师?>>> ...
  • 1.1 幂等性定义 数学定义 在数学里,幂等有两种主要的定义: 在某二元运算下,幂等元素是指自己重复运算(或对于函数是为复合)的结果等于它自己的元素。例如,乘法下唯一两个幂等实数为0和1,即s*s=s 某一元运算...
  • 微服务架构幂等性问题及设计思想,你不得不知的一些幂等方案 前言 小伙伴们有没有遇到过生产环境经常出现过重复的数据?在排查问题的时候,数据又是正常的。这个是何解呢?怎么会出现这种情况,而且还很难排查...
  • 我们先看两道互联网大厂的面试...幂等这个词本身源自数学,幂等性是数学中的一个概念,常见于抽象代数中,表达的是N次变换与1次变换的结果相同,在计算机的各个领域都借用了该概念。本课程带你聊聊接口幂等性的那些事。
  • 微服务架构 微服务架构是一种架构概念,旨在通过将功能分解到各个离散的服务中以实现对解决方案的解耦。它的主要作用是将功能分解到离散的各个服务当中,从而降低系统的耦合性,并提供更加灵活的服务支持。 和 ...
  • Pre 我们来回顾下单体时代 ...分布式锁 能否解决幂等性问题? 分布式锁解决什么问题? 简言之: 解决跨进程间无法共享本地资源的问题 ,解决的是分布式场景下并发访问的问题。 为什么需要确保并发.
  • 一、幂等性概念 1、幂等简介 编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。就是说,一次和多次请求某一个资源会产生同样的作用影响。 2、HTTP请求 遵循Http协议的请求,越来越强调...
  • 关于分布式架构下接口的幂等性和并发性控制

    千次阅读 热门讨论 2021-04-01 16:32:19
    关于分布式架构下接口的幂等性和并发性控制 废话不多说直接上代码 主要思路通过注解形式实现幂等,利用redis的lua脚本解决并发执行 定义注解 /** * 幂等注解 * get请求直接 key * post的请求 body格式 user....
  • 幂等性:多次操作返回结果一样 一致性:多个副本数据一致 幂等性的实现方案 分布式系统(微服务架构)的一致性和幂等性问题相关概念解析
  • 复杂系统大都会使用分布式架构,在分布式架构中,如何保证接口在分布式的服务调度中保证幂等性,如何提高接口响应效率,是非常关键的。 在本场 Chat 中,会讲到如下内容: 接口幂等性原则 缓存多应用模式 Redis监控...
  • 幂等

    2019-11-28 23:58:22
    什么是幂等   简单说来,如果一个操作多次执行所产生的影响等价于执行一次的影响,我们就称之为幂等。   实际系统中,幂等是一个极为重要的概念。无论是在大型互联网应用还是企业级架构中,我们都见到REST API被...
  • 《究竟什么时候使用MQ》内容:什么典型场景不应该使用MQ什么典型场景应该使用MQ二、消息可达性文章:《MQ,如何做到消息必达》内容:MQ系统架构MQ消息发送过程如何实现消息必达消息必达带来的副作用三、消息幂等性...
  • 一、幂等性概念 1、幂等简介 编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。就是说,一次和多次请求某一个资源会产生同样的作用影响。 2、HTTP请求 遵循Http协议的请求,越来越...
  • Http有两个非常重要的特性 安全性和幂等性。下面来解释一下这两个特性 安全性 安全性是指访问资源的时候资源本身不会发生改变,也就是资源是安全的。举个例子,使用get操作去获取一个资源,无论如何也不会引起...
  • 幂等这个概念,是一个数学上的概念,即:f……(f(f(x))) = f(x)。用在计算机领域,指的是系统里的接口或方法对外的一种承诺,使用相同参数对同一资源重复调用某个接口或方法的结果与调用一次的结果相同。 二、业务...
  • 前篇《无限容量数据库架构设计》收到网友好评: 系统性,全局性看问题体会更深刻 简单易懂   本文再做总结,体系化介绍MQ的一些架构技术。   一、总起 文章:《究竟什么时候使用MQ》 内容: ...
  • /** ... */ @Transactional(transactionManager = "tm337", propagation = Propagation.REQUIRED) public int deleteAccount(){ int result=account337Mapper.deleteByPrimaryKey(1); return result;...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 37,972
精华内容 15,188
关键字:

幂等架构