ddmcc / interview

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

如何保证服务幂等性? 1、概念:接⼝的幂等性实际上就是接⼝可重复调⽤,在调⽤⽅多次调⽤的情况下,接⼝最终得到的结果是⼀致的。有些接⼝可以天 然的实现幂等性,⽐如查询接⼝,对于查询来说,你查询⼀次和两次,对于系统来说,没有任何影响,查出的结果也是⼀样。

2、GET幂等:值得注意,幂等性指的是作⽤于结果⽽⾮资源本身。怎么理解呢?例如,这个HTTP GET⽅法可能会每次得到不同的返 回内容,但并不影响资源。

3、POST⾮幂等:因为它会对资源本身产⽣影响,每次调⽤都会有新的资源产⽣,因此不满⾜幂等性。

4、如何保证幂等性:

  • 1、全局唯⼀id:如果使⽤全局唯⼀ID,就是根据业务的操作和内容⽣成⼀个全局ID,在执⾏操作前先根据这个全局唯⼀ID是否存 在,来判断这个操作是否已经执⾏。如果不存在则把全局ID,存储到存储系统中,⽐如数据库、redis等。如果存在则表示该⽅法已经 执⾏。

从⼯程的⻆度来说,使⽤全局ID做幂等可以作为⼀个业务的基础的微服务存在,在很多的微服务中都会⽤到这样的服务,在 每个微服务中都完成这样的功能,会存在⼯作量重复。另外打造⼀个⾼可靠的幂等服务还需要考虑很多问题,⽐如⼀台机器虽然把全 局ID先写⼊了存储,但是在写⼊之后挂了,这就需要引⼊全局ID的超时机制。

使⽤全局唯⼀ID是⼀个通⽤⽅案,可以⽀持插⼊、更新、删除业务操作。但是这个⽅案看起来很美但是实现起来⽐较麻烦, 下⾯的⽅案适⽤于特定的场景,但是实现起来⽐较简单。

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

  • 3、插⼊或更新:这种⽅法插⼊并且有唯⼀索引的情况,⽐如我们要关联商品品类,其中商品的ID和品类的ID可以构成唯⼀索 引,并且在数据表中也增加了唯⼀索引。这时就可以使⽤InsertOrUpdate操作。在mysql数据库中如下:

insert into goods_category (goods_id,category_id,create_time,update_time) values(#{goodsId},#{categoryId},now(),now()) on DUPLICATE KEY UPDATE update_time=now()

  • 4、多版本控制:这种⽅法适合在更新的场景中,⽐如我们要更新商品的名字,这时我们就可以在更新的接⼝中增加⼀个版本 号,来做幂等

boolean updateGoodsName(int id,String newName,int version);

在实现时可以如下

update goods set name=#{newName},version=#{version} where id=#{id} and version<${version}

  • 5、状态机控制:这种⽅法适合在有状态机流转的情况下,⽐如就会订单的创建和付款,订单的付款肯定是在之前,这时我们可 以通过在设计状态字段时,使⽤int类型,并且通过值类型的⼤⼩来做幂等,⽐如订单的创建为0,付款成功为100。付款失败为99 在做状态机更新时,我们就这可以这样控制

update order set status=#{status} where id=#{id} and status<#{status

About


Languages

Language:Java 100.0%