幂等概念

   在计算机中,表示对同一个过程应用相同的参数多次和应用一次产生的效果是一样,这样的过程即被称为满足幂等性。

   也可以进行如下表述:一个HTTP请求方法,如果被请求多次和被请求一次效果相同,被认为是幂等的,比如PUT、DELETE和其他安全的请求方法都是幂等的。

   幂等:

update test_user set user_age = 25 where user_id = 2

   这种情况无论执行多少次,结果都不受影响,所以是幂等的。

   非幂等:

update test_user set user_times = user_times + 1 where user_id = 2

   这样的更新语句每执行一次,结果都会不一样,所以是非幂等的。

幂等实现方法

1 全局唯一ID

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

   使用全局唯一ID是一个通用方案,可以支持插入、更新、删除业务操作。比较适用于有限制导入导出操作,比如:希望一个账号在同一时间内只能导入或导出一次数据,这个时候就可以在导入前根据账号建立一个对账号唯一的key值放入redis中,执行业务方法时判断是否存在,最后执行成功或失败后删除redis的Key

   但是这个方案看起来很美但是实现起来比较麻烦,下面的方案适用于特定的场景,但是实现起来比较简单。

2 去重表

   这种方法适用于在业务中有唯一标的插入场景中。

   比如在以上的支付场景中,如果一个订单只会支付一次,那么订单ID可以作为唯一标识。这时,我们就可以建一张去重表,并且把唯一标识作为唯一索引,用以记录订单支付信息。在实现时,把创建支付单据和写入去重表放在一个事务中,如果重复创建,数据库会抛出唯一约束异常,操作就会回滚。这个方法其实也是用到唯一ID,与上面全局唯一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<$

5 状态机控制

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

update goods_order set status=#{status} where id=#{id} and

status<#

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

小结

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

  • UUID
  • Snowflake
  • 数据库自增ID
  • 业务本身的唯一约束
  • 业务字段+时间戳拼接

Java进阶知识点:接口幂等性的更多相关文章

  1. Java进阶知识点: 枚举值

    Java进阶知识点1:白捡的扩展性 - 枚举值也是对象   一.背景 枚举经常被大家用来储存一组有限个数的候选常量.比如下面定义了一组常见数据库类型: public enum DatabaseType ...

  2. Java进阶知识点:协变与逆变

    一.背景 要搞懂Java中的协办与逆变,不得不从继承说起,如果没有继承,协变与逆变也天然不存在了. 我们知道,在Java的世界中,存在继承机制.比如MochaCoffee类是Coffee类的派生类,那 ...

  3. Java进阶知识点:更优雅地关闭资源 - try-with-resource

    一.背景 我们知道,在Java编程过程中,如果打开了外部资源(文件.数据库连接.网络连接等),我们必须在这些外部资源使用完毕后,手动关闭它们.因为外部资源不由JVM管理,无法享用JVM的垃圾回收机制, ...

  4. Java进阶知识点3:更优雅地关闭资源 - try-with-resource及其异常抑制

    一.背景 我们知道,在Java编程过程中,如果打开了外部资源(文件.数据库连接.网络连接等),我们必须在这些外部资源使用完毕后,手动关闭它们.因为外部资源不由JVM管理,无法享用JVM的垃圾回收机制, ...

  5. Java进阶知识点2:看不懂的代码 - 协变与逆变

    一.背景 要搞懂Java中的协办与逆变,不得不从继承说起,如果没有继承,协变与逆变也天然不存在了. 我们知道,在Java的世界中,存在继承机制.比如MochaCoffee类是Coffee类的派生类,那 ...

  6. Java进阶知识点:不要只会写synchronized - JDK十大并发编程组件总结

    一.背景 提到Java中的并发编程,首先想到的便是使用synchronized代码块,保证代码块在并发环境下有序执行,从而避免冲突.如果涉及多线程间通信,可以再在synchronized代码块中使用w ...

  7. Java进阶知识点:服务端高并发的基石 - NIO与Reactor AIO与Proactor

    一.背景 要提升服务器的并发处理能力,通常有两大方向的思路. 1.系统架构层面.比如负载均衡.多级缓存.单元化部署等等. 2.单节点优化层面.比如修复代码级别的性能Bug.JVM参数调优.IO优化等等 ...

  8. Java进阶知识点8:高可扩展架构的利器 - 动态模块加载核心技术(ClassLoader、反射、依赖隔离)

    一.背景 功能模块化是实现系统能力高可扩展性的常见思路.而模块化又可分为静态模块化和动态模块化两类: 1. 静态模块化:指在编译期可以通过引入新的模块扩展系统能力.比如:通过maven/gradle引 ...

  9. Java进阶知识点7:不要只会写synchronized - JDK十大并发编程组件总结

    一.背景 提到Java中的并发编程,首先想到的便是使用synchronized代码块,保证代码块在并发环境下有序执行,从而避免冲突.如果涉及多线程间通信,可以再在synchronized代码块中使用w ...

  10. Java进阶知识点5:服务端高并发的基石 - NIO与Reactor模式以及AIO与Proactor模式

    一.背景 要提升服务器的并发处理能力,通常有两大方向的思路. 1.系统架构层面.比如负载均衡.多级缓存.单元化部署等等. 2.单节点优化层面.比如修复代码级别的性能Bug.JVM参数调优.IO优化等等 ...

随机推荐

  1. Pycharm pull 报错“Pull Failed: refusing to merge unrelated histories”

    分析: 在github已将建立仓库 pycharm clone到本地 pycharm pull 在第3步报错 "Pull Failed: refusing to merge unrelate ...

  2. manim边学边做--线性变换的场景类

    在数学可视化领域,Manim的LinearTransformationScene类为线性代数教学提供了强大的工具. 这个专门设计的场景类继承自VectorScene,通过内置的变换动画和坐标系管理,能 ...

  3. Web前端入门第 16 问:学会使用开发者工具调试 HTML 页面

    HELLO,这里是大熊学习前端开发的入门笔记. 本系列笔记基于 windows 系统. 有没有好奇,前面文章中的截图是怎么来的?怎样查看 HTML 的渲染结果? Web 开发者的照妖镜 曾经火狐( F ...

  4. MOS管的引脚,G、S、D分别代表什么?

    引脚解析: G:gate 栅极,N沟道的电源一般接在D. S:source 源极,输出S,P沟道的电源一般接在S. D:drain 漏极,输出D.增强耗尽接法基本一样. mos管是金属(metal)- ...

  5. Linux下对LVM逻辑卷分区大小调整 [针对xfs和ext4文件系统]

    当我们在安装系统的时候,由于没有合理分配分区空间,在后续维护过程中,发现有些分区空间不够使用,而有的分区空间却有很多剩余空间.如果这些分区在装系统的时候使用了lvm(前提是这些分区要是lvm逻辑卷分区 ...

  6. Cursor 老改坏代码?六哥这几招超管用!

    大家好,我是六哥!最近不少小伙伴和我吐槽,在使用Cursor时,AI老是把代码改坏,让人头疼不已.我自己也用了大几十个小时Cursor,今天就来给大家分享一些实用小窍门,教大家如何巧妙规避这类问题. ...

  7. Hyperledger Fabric - 自定义createChannel命令

    前提条件 启动上一步的自定义network网络 ./network-myself.sh up 拷贝配置文件 以下文件是配置文件及相关脚本文件: mkdir configtx #创建配置文件目录 cp ...

  8. 2024 蓝桥杯模拟赛3(div1+div2)

    2024 蓝桥杯模拟赛3(div1+div2) P8834 [传智杯 #3 决赛] 序列 简单的模拟,数据范围很小,暴力即可 点击查看代码 #include <bits/stdc++.h> ...

  9. Hello, PostgreSQL

    Hello, PostgreSQL Whoami:5年+金融.政府.医疗领域工作经验的DBA Certificate:PGCM.OCP.YCP Skill:Oracle.Mysql.PostgreSQ ...

  10. redis的作用:高性能和高并发

    一.高性能 假设这么个场景,你有个操作,一个请求过来,吭哧吭哧你各种乱七八糟操作mysql,半天查出来一个结果,耗时600ms.但是这个结果可能接下来几个小时都不会变了,或者变了也可以不用立即反馈给用 ...