幂等概念

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

   也可以进行如下表述:一个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. windows mysql8安装zip

    MySQL 是一种广泛使用的关系数据库管理系统,MySQL 8 是其最新的主要版本,结合了出色的性能和丰富的功能. 一.准备工作 1. 下载MySQL 8 zip包 首先,你需要获取MySQL 8的压 ...

  2. 从RNN、LSTM到NTM、MANN——神经网络的记忆与推理进化

    从RNN.LSTM到NTM.MANN--神经网络的记忆与推理进化 一.前言:为什么要研究记忆? (温馨提示:在阅读本文之前,请确保你已经对深度学习中最基本的概念有一定的了解,例如:激活函数.多层感知机 ...

  3. 记录composer 安装 yii2项目

    先带上一个痛苦面具 前段时间换成mac系统,自己以前的yii2项目老是安装不上,因为暂时用不上就没去管,现在想用了,折腾了半天才安装好.下面我记录下坑 国内记得换镜像(我换了系统后,应该是忘记了) c ...

  4. [tldr] vscode的remote插件的config文件内容解析

    参考VS Code Remote SSH配置 解决了什么问题 vscode的remote插件可以直接通过可视化的UI新建一个连接 通过ssh指令添加服务器的连接方式 但是这种方式添加的服务器名字等于服 ...

  5. 地球OL攻略 —— 某应届生求职总结

    某应届生的苦逼求职总结 1.自我介绍,阐述一下自己过去的情况 2.目前的就业情况以及从事的就业方向 3.你在面试的时候遇到什么困难?是怎么帮忙解决的 4.当初为什么会选择选择这一行? 5.分享一下学习 ...

  6. Supervisor-进程守护工具

    前言 Supervisor是用Python开发的一套通用的进程管理程序,能将一个普通的命令行进程变为后台daemon,并监控进程状态,异常退出时能自动重启.它是通过fork/exec的方式把这些被管理 ...

  7. composer 指定php版本

    需要指定php和composer的位置,然后再去执行composer命令 ## 指定PHP版本 指定composer 指定载入包 /usr/local/php7/bin/php composer /u ...

  8. 云服务器下如何部署Django项目详细操作步骤

    前期本人完成了"编写你的第一个 Django 应用程序",有了一个简单的项目代码,在本地window系统自测没问题了,接下来就想办法部署到服务器上,可以通过公网访问我们的Djang ...

  9. 『Plotly实战指南』--柱状图绘制基础篇

    柱状图作为最基础的数据可视化形式之一,能直观展示不同类别数据的对比关系,适用于一下的场景: 比较不同类别之间的数据大小,如不同产品的销售额对比. 展示数据的分布情况,如各年龄段的人口数量分布. 分析时 ...

  10. BUUCTF---古典密码知多少

    题目 知识 一共给出四种古典密码,分别是:猪圈密码.圣堂武士密码.标准银河字母.栅栏密码 猪圈之前有介绍 圣: 标准银河字母 更多加密方式 解题 对照解密 FGCPFLIRTUASYON 再使用栅栏 ...