“幂等”不等于“分布式锁”,也不得不考虑返回值

. 概览

在分布式系统中,幂等是一个非常重要的概念,常常与“重试”一起出现。当调用一个远程服务发生超时,调用方并不知道请求是否执行成功,这就是典型的“第三态”问题。对于这个问题最常见的解决方案便是进行主动重试,假如该操作是一个数据库插入操作,重试将对系统产生副作用(创建多条记录),这时我们常常会说,被调用接口需要保障幂等。

1.1. 背景

幂等可以简单定义如下:任意多次执行所产生的影响均与第一次执行的影响相同。

【注】从幂等定义上看,重心放在了操作之后的影响,及多次操作不会破坏内部状态。但在实际工作当中,除了内部状态外,接口的返回值也是一个重要要素,多次重复操作返回相同的结果往往更符合使用者的预期。

举个例子,在订单系统中,用户使用优惠券下单后会调用冻结接口对优惠券进行冻结操作,站着订单系统的视角,当进行冻结重试时你期望:

  1. 优惠券抛出异常,告知订单优惠券已经冻结;
  2. 优惠券直接返回上次的结果 “冻结成功;

大家可以思考下两种方案在下游使用时的异同,当然最好提供两种机制,由使用方根据场景进行定制。

在不同的场景下,幂等保护的方案是不同的,常见幂等处理策略有:

  1. 天然具有幂等性,不需要保护。比如读操作、按主键数据删除等;
  2. 使用上游信息作为下游主键或唯一键的插入场景,由于有键的约束,可以保障幂等。比如以 userId 作为 Card(名片)的主键;
  3. 数据库字段的直接更新操作也具有一定的幂等性。比如用户修改姓名;
  4. 直接使用外部存储,以幂等键为标识,对方法执行情况进行记录,并以此为判断依据完成幂等保护;

由于其他策略与场景强绑定,idempotent 重心放在方案4上,已覆盖更多的业务场景。

1.2. 目标

快速为非幂等接口增加幂等保护。

  1. 基于“能力声明化”的方式,为接口快速添加幂等保护;
  2. 支持常见的两种幂等保护策略;
    1. 直接返回上次的执行结果;
    2. 抛出异常告知重复提交;
  3. 支持存储层的扩展,并提供常见的存储实现,包括:
    1. redis 实现,适用于一般通用场景,性能好但缓存过期后可能存在幂等不生效的情况;
    2. db 实现,适用于比较严格的场景,比如与订单、金额相关的业务;

2. 快速入门

2.1. 准备工作

首先,引入 lego starter,在 maven pom 中添加如下信息:

<groupId>com.geekhalo.lego</groupId>
<artifactId>lego-starter</artifactId>
<version>0.1.15-idempotent-SNAPSHOT</version>

然后,以 JpaRepository 为例实现对 IdempotentExecutorFactory 的配置,具体如下:

@Configuration
public class IdempotentConfiguration extends IdempotentConfigurationSupport {
    @Bean("dbExecutorFactory")
    public IdempotentExecutorFactory redisExecutorFactory(JpaBasedExecutionRecordRepository recordRepository){
        return createExecutorFactory(recordRepository);
    }
}

其中,
IdempotentConfigurationSupport 已经提供 idempotent 所需的很多 Bean,同时提供 createExecutorFactory(repository) 方法,用以完成 IdempotentExecutorFactory 的创建。

使用 Jpa 需要调整 EnableJpaRepositories 相关配置,具体如下:

@Configuration
@EnableJpaRepositories(basePackages = {
        "com.geekhalo.lego.core.idempotent.support.repository"
}, repositoryFactoryBeanClass = JpaBasedQueryObjectRepositoryFactoryBean.class)
public class SpringDataJpaConfiguration {
}

其中,
com.geekhalo.lego.core.idempotent.suppor

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用分布式锁实现幂等性和不使用分布式锁实现幂等性是两种不同的方式,它们各自有一些优缺点。 使用分布式锁实现幂等性的优点是: 1.保证了接口的幂等性。使用分布式锁可以避免并发请求重复操作,确保接口只会被调用一次,从而保证了接口的幂等性。 2.操作简单方便。通过使用Redis等分布式锁工具,可以很方便地实现分布式锁,代码实现也相对简单。 使用分布式锁实现幂等性的缺点是: 1.性能开销较大。使用分布式锁需要对锁的实现方式、锁的粒度等进行优化,否则会对系统的性能产生影响。 2.锁的超时时间设置问题。如果锁设置的超时时间过短,可能会导致请求无法执行,如果设置的过长,则可能会导致请求等待的时间过长,影响系统的性能。 不使用分布式锁实现幂等性的优点是: 1.性能开销较小。不使用分布式锁实现幂等性,可以避免分布式锁带来的额外开销,提高系统的性能。 2.实现灵活方便。不使用分布式锁实现幂等性,可以通过代码实现幂等性,实现灵活方便。 不使用分布式锁实现幂等性的缺点是: 1.实现难度较大。在不使用分布式锁的情况下,需要通过代码实现幂等性,实现难度较大。 2.容易出现逻辑错误。在不使用分布式锁的情况下,容易出现逻辑错误,导致接口无法实现幂等性。 综上所述,使用分布式锁实现幂等性和不使用分布式锁实现幂等性各有优缺点,需要根据具体的业务场景和性能需求进行选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值