幂等性设计与实现

这篇具有很好参考价值的文章主要介绍了幂等性设计与实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

幂等性(Idempotence)是一个在计算机科学中使用的术语。当某个操作无论进行一次或多次都产生相同的结果,我们就说这个操作是幂等的。

例如,删除文件的操作就是幂等的,因为无论你尝试删除一次还是两次,结果都是文件被删除。相对地,计数器增加操作就不是幂等的,因为每次操作,计数器的值都会改变。

在分布式系统和网络协议中,幂等性是非常重要的特性。由于网络延迟,服务端可能会接收到同一条消息的多个副本,如果此类操作是幂等的,那么就不会出现任何问题。

解决方案:

    1. 全局唯一ID :为每个请求分配一个唯一的任务 ID,并确保服务器对每个任务只执行一次。如果服务器接收到相同的任务 ID,它将忽略这个任务或返回之前任务的结果。
    1. Token 机制: 根据业务的操作和内容生成一个Token值(全局唯一ID,执行之前判断方法是否执行过。
    1. 发送确认消息:客户端在发送完请求后并不立即进行下一步操作,而是等待服务器的确认消息。如果客户端没有收到确认消息,那么它会重新发送请求。
    1. 使用分布式锁或事务:通过这种方式,可以确保一次只有一个任务在执行,避免因重复执行同一个任务而产生的问题。
    1. 使用乐观锁:乐观锁对数据进行更新时,会检查数据在此期间是否被别人修改过,如果被修改过,则拒绝更新。
    1. 使用“compare-and-swap”等原子操作:原子操作可以在不使用锁的情况下完成复杂的更新操作,这也可以保证幂等性。

幂等可以用来解决什么问题?
幂等性可以用于解决在分布式系统中的重复请求问题。在分布式系统中,由于网络等原因,可能会导致同一个请求被多次执行,从而可能会造成脏数据或资源浪费等问题。通过实现幂等性,可以确保相同的请求只被执行一次,从而防止出现重复请求的情况。这样可以提高系统的稳定性、可靠性和性能。另外,幂等性也可以用于实现事务的原子性,确保事务只被执行一次,从而防止出现数据不一致的情况。

1.全局唯一ID

全局唯一ID的生成,需要根据实际的业务需要进行生成,单机的部署一般使用UUID或者数据库自增ID就ok,分布式下现在比较流行的雪花算法生成全局唯一ID。单机也需要考虑后期业务的扩展进行使用全局唯一ID,根据阿里规范:单表行数超过500万行或者单表容量超过2GB,才推荐进行分库分表

1.1 前端防止重复提交

一般开发中,前端也会做一些简单防止重复提交操作,一般的操作就是提交请求后禁用操作。此处就不在赘述,比较简单,此做法不能解决问题,只能简单解决人为的操作。
解决不了由于网络波动,网络重试机制导致数据不一致问题。

1.2 token机制

Token的机制通过进行业务操作之前进行根据业务生成一个token,token可以使用雪花算法进行生成,进行业务操作之前先获取token,获取成功请求业务携带token,请求,后台会根据逻辑进行有效操作的判断。后端判断该 token 是否存在,如存在,则为第一次提交,放行并删除token,如无token,第二次提交,阻拦该请求。

幂等性设计与实现,Java,java,幂等性
高并发环境下还需要考虑操作的原子性。
此处使用redis来存生成的token。
安装和具体的操作参考:
centos7下安装redis以及本地连接注意事项
Springboot整合redis

简单token服务代码

/**
 * token服务
 */
@Service
public class TokenService {

    @Autowired
    RedisService redisService;

    /**
     * 获取token
     * @param bizType
     * @return
     */
    public String getToken(String bizType){
        ///业务的key
        String key = bizType+":"+UUID.randomUUID().toString();
        redisService.saveKeyValue(key,1,10);
        return key;
    }
    /**
     * 校验token
     * @param token
     * @return
     */
    public boolean verifyToken(String token){
        ///token
        String value = redisService.getValueByKey(token);
        //判断值是否存在
        if(!StringUtils.isEmpty(value)){
            //存在删除
            redisService.delete(token);
            return true;
        }
        return false;
    }

controller:

@RestController
public class TokenController {

    @Autowired
    TokenService tokenService;

    @GetMapping("/getToken/{bizType}")
    public String getToken(@PathVariable("bizType") String bizType){
      return tokenService.getToken(bizType);
    }
}

幂等性设计与实现,Java,java,幂等性

1.3 数据库表加唯一约束

比如用户表加上身份证号作为唯一的约束,也可以防止重复提交用户注册。对于一些业务唯一不明确的也能导致不幂等性。

2.幂等下 ABA问题 与乐观锁

ABA问题:是在并发环境中经常会遇到的问题,最典型的例子就是CAS(Compare And Swap)操作。CAS操作是一种乐观加锁机制,它执行时首先把某个内存值A读入到未提交缓冤区,在此期间可能其他线程也修改了这个内存场所的值变成了B,若这个时候重来执行CAS操作,尽管它能检测到这个内存值已经被修改过,但修改过后的这个值B又被其他线程改变成了A,这样CAS操作就可能错误地成功。这就是ABA问题。

2.1 乐观锁

乐观锁一种并发控制技术。在写入数据时,并不加锁,而是假定没有其他线程与其同时修改数据。当操作系统执行写入操作时,它会检查没有线程已经修改从开头到现在的数据。如果检测到其他线程已经修改了该数据,那么操作系统就会拒绝写入,并通知失败。需要重试直到没有其他线程修改需要写入的数据。
乐观锁主要解决了悲观锁长期占据锁而导致其他线程长时间等待锁的问题。

2.2 如何解决ABA问题?

  1. 使用版本号:在每个变量后面追加上版本号,每次修改该变量都对版本号加一,这就能解决ABA问题了。
  2. 使用原子类:Java从1.5开始提供了一个原子包(java.util.concurrent.atomic),在这个包中提供了一些原子类,其中ABA问题可以使用类AtomicStampedReference进行解决,它通过控制变量的版本解决了ABA问题。

3.分布式锁和事务

3.1 分布式锁:

其主要目的是在系统内提供一种机制,来确保在任何时刻只有一个节点可以执行某个程序区块,所以分布式锁主要目的是为了防止并发操作引发的数据不一致问题。
分布式锁通过一种协议来决定哪一个请求可以获得锁,以执行相应的操作。例如,一个典型的应用程序可能需要对数据库中的一个数据进行更新,程序在进行更新操作的时候会先尝试获取分布式锁,如果获取成功则进行操作,如果获取失败则等待或者抛出错误。

3.2. 分布式事务

事务的核心是:ACID原则(原子性、一致性、隔离性、持久性)。

在一个分布式系统中,为了保证跨多个节点的数据一致性和操作可靠性,通常需要引入一种机制——分布式事务。该机制可以确保分布式系统中多个操作要么全都成功执行,要么全都不执行(如果某处失败,其他所有成功的操作也需要回滚)。

分布式锁主要用于保证在多节点环境下,某一时刻只有一个节点能够操作某资源,用于解决并发问题;而分布式事务,主要用于确保在多节点环境下,一个业务流程中包含的多个操作要么全部成功,要么全部失败,从而保证数据的一致性。文章来源地址https://www.toymoban.com/news/detail-600653.html

到了这里,关于幂等性设计与实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【微信小程序】Java实现微信支付(小程序支付JSAPI-V3)java-sdk工具包(包含支付出现的多次回调的问题解析,接口幂等性)

          对于一个没有写过支付的小白,打开微信支付官方文档时彻底懵逼 ,因为 微信支付文档太过详细, 导致我无从下手,所以写此文章,帮助第一次写支付的小伙伴梳理一下。 一、流程分为三个接口:(这是前言,先看一遍,保持印象,方便理解代码) 1、第一个接口:

    2024年01月16日
    浏览(61)
  • 幂等性设计,及案例分析

    上面代码中,锁起不了作用; ——count方法,和insert方法在同一事务中,事务中包含锁,锁没有作用,锁的范围内,事务没提交,但释放锁后,事务提交前,被另一线程抢了执行权后,因为事务还没提交,另一线程拿到的count还是0。 以上代码问题: 对事物的理解使用有问题

    2024年02月06日
    浏览(25)
  • 一文搞定接口幂等性架构设计方案

    现如今很多系统都会基于分布式或微服务思想完成对系统的架构设计。那么在这一个系统中,就会存在若干个微服务,而且服务间也会产生相互通信调用。那么既然产生了服务调用,就必然会存在服务调用延迟或失败的问题。当出现这种问题,服务端会进行重试等操作或客户

    2023年04月20日
    浏览(26)
  • 腾讯二面:如何保证接口幂等性?高并发下的接口幂等性如何实现?

    什么是接口幂等性 接口幂等性这一概念源于数学,原意是指一个操作如果连续执行多次所产生的结果与仅执行一次的效果相同,那么我们就称这个操作是幂等的。在互联网领域,特别是在Web服务、API设计和分布式系统中,接口幂等性具有非常重要的意义。 具体到HTTP接口或者

    2024年03月19日
    浏览(36)
  • 【分布式】: 幂等性和实现方式

    幂等(idempotent、idempotence)是一个数学与计算机学概念, 常见于抽象代数中。在编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。幂等函数,或幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的函数。这些函数不会影响系统

    2024年02月08日
    浏览(32)
  • 一个注解实现接口幂等性,真心优雅!

    简单来说,就是对一个接口执行重复的多次请求,与一次请求所产生的结果是相同的,听起来非常容易理解,但要真正的在系统中要始终保持这个目标,是需要很严谨的设计的,在实际的生产环境下,我们应该保证任何接口都是幂等的,而如何正确的实现幂等,就是本文要讨

    2024年02月03日
    浏览(32)
  • rabbitmq+springboot实现幂等性操作

    文章目录 1.场景描述 1.1 场景1 1.2 场景2 2.原理 3.实战开发 3.1 建表 3.2 集成mybatis-plus 3.3 集成RabbitMq 3.3.1 安装mq 3.3.2 springBoot集成mq 3.4 具体实现 3.4.1 mq配置类 3.4.2 生产者 3.4.3 消费者 消息中间件是分布式系统常用的组件,无论是异步化、解耦、削峰等都有广泛的应用价值。我们

    2024年02月10日
    浏览(31)
  • Spring Boot 实现接口幂等性的 4 种方案

    现在的系统或平台,为了追求体验性、内容丰富性,都是前后端分离,系统为了解藕会引入各种MQ等,都不可避免就引入了数据幂等性的问题。 幂等是一个数学与计算机学概念,在数学中某一运算为幂等时,其作用在任一元素两次会和其作用一次的结果相同。 在计算机编程中

    2024年02月06日
    浏览(36)
  • SpringBoot Redis 注解 拦截器来实现接口幂等性校验

    幂等性, 通俗的说就是一个接口, 多次发起同一个请求, 必须保证操作只能执行一次 比如:订单接口, 不能多次创建订单 支付接口, 重复支付同一笔订单只能扣一次钱 支付宝回调接口, 可能会多次回调, 必须处理重复回调 普通表单提交接口, 因为网络超时等原因多次点击提

    2024年01月19日
    浏览(46)
  • SpringBoot中接口幂等性实现方案-自定义注解+Redis+拦截器实现防止订单重复提交

    SpringBoot+Redis+自定义注解实现接口防刷(限制不同接口单位时间内最大请求次数): SpringBoot+Redis+自定义注解实现接口防刷(限制不同接口单位时间内最大请求次数)_redis防刷_霸道流氓气质的博客-CSDN博客 以下接口幂等性的实现方式与上面博客类似,可参考。 什么是幂等性? 幂等

    2024年02月15日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包