幂等性的研究及实例应用

引入:
这段时间在做新渠道的接入,把以前的核心拿过来copy一份进行改造,在进行代码重读的时候,发现了一个好玩的东西,在申请入件的时候,需要经过一步校验,注释上写的是,对于短时间重复提交的验证。当时我就很好奇点了进去,看一看到底是什么东西,然后点开之后大吃一惊,里面做的操作是:取到这笔件的身份证信息,使用其作为标识去查询有没有这个标识的线程,如果有则返回失败,这笔件短时间内重复提交了,如果没有返回成功,这笔件短时间内没有重复提交,并以身份证为标识创建一个线程然后挂起这个线程n毫秒(算作重复性提交的时间)。

这里问题就大了,意思是一笔件进入系统的时候,如果需要做重复申请验证,则会新开一个子线程挂起,我们都知道对于线程的操作,无论是创建挂起销毁都好,会需要进行OS切换操作,这种OS操作十分占用资源,在没有必要的时候尽量避免反复的创建线程,而且这个验证会在每一次入件时都会执行。这对我们写的程序是一个极大的负担,于是我向上级反映此问题并且接到了优化代码的任务。在查询资料之后,发现对于这种验证短时间内是否重复提交的操作有一个专用的名词去形容他,也就是我要去研究的内容:幂等性验证。

一、幂等性的概念

幂等(idempotent、idempotence)是一个数学与计算机学概念,常见于抽象代数中。
在编程中.一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。幂等函数,或幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的函数。这些函数不会影响系统状态,也不用担心重复执行会对系统造成改变。复杂的操作幂等保证是利用唯一交易号(流水号)实现.【百度百科】

数学中的幂等是指一个数对自己进行函数运算,其结果等于他自己。数学表达式为(f(x)) = f(x):也就是某个函数或者某个接口使用相同参数调用一次或者无限次,其造成的后果是一样的

在业务层面上来说,由于我们是提供接口的一方供他人调用,别人在调用时完全可以发送无数笔相同的数据(由于bug之类)调用你的接口,这样你在提供服务的时候,必须进行幂等性运算来控制重复的申请。

实际上TCP传输协议是支持幂等的,他使用了一个唯一的序列号作为标示来保证数据的幂等性。我们在进行应用层面上的幂等性验证的时候也是同理,需要使用一个唯一的序列号进行验证,通常是我们与对接方约定的流水号来进行控制,其特点是唯一性。

二、幂等性的验证实验

在网上保证接口幂等的方法很多,最简单常用的方法时,select+insert 先查询有没有此笔数据,然后再进行数据变更操作,但是这种方法很明显效率比较低下,在高并发的程序中不建议使用。然后比较多的就是乐观锁和悲观锁,悲观锁的原理是使用select for update的形式,这种方式要求你select的条件必须是主键或者唯一索引,否则会导致锁表,在你更新时任何人做不了表格操作。乐观锁是只在更新的一瞬间进行锁表,效率上要高很多,但要通过辅助的状态参数来进行验证,如:
  update table set name=’name’,version=version+1 where version=version
由于进行更新的时候会使其版本+1如果是并发的两条信息同时对表格操作时,第二笔就会因为版本号不对更新失败,这样也能保证幂等性。当然,你使用其他状态进行控制也是可行的,如果可以最好加上唯一索引,能够大幅度提高效率。
正常与其他机构进行交互的时候,往往对方会提供流水号并且保证流水号唯一,这样作为己方就可以使用数据来源+对方提供的流水号作为唯一索引来进行幂等性校验。

三、解决实际问题

虽然查了这么多资料,但是发现幂等性校验并没有解决我的实际问题,应需求(可能是为了分担我们后台的核心专家系统压力,也可能是以前出过什么大量重复bug),我需要在程序中不牵扯到数据库操作的情况下,控制同一个人(身份证号,这两笔申请可能是不同的,但是只要是一个人就不允许连续操作)在短时间内不能进行重复申请操作。于是我想到了,设置一个缓存区来解决这个问题,思路如下:

  • 设置一个hashmap,key储存身份证信息,value储存申请时的时间信息
  • 在一笔申请提交进来的时候,将身份证信息和时间信息存入map
  • 在信息存入map之前进行判断,如果这个key在map中存在则判断其value与现在时间是否超过允许重复提交时长,如果是则更新数据,返回通过,否则返回不通过。
  • 由于入键数可能比较多,一直往map中增加值可能会导致map非常大,后入的键验证效率变差,于是在map达到一定大小时将开一个子线程,循环遍历map中的值,将与当前时间相差大于允许重复提交时间的键全部删除
    实现代码如下:
public static final Map<String,Long> MAP = new HashMap<String,Long>();public static final long OUT_TIME=1000;public static final int OUT_SIZE=100;//验证是否短时间重复申请public static boolean isRepeat(String idNum){boolean flag =false;//检查是否存在keyif(MAP.containsKey(idNum)){if(System.currentTimeMillis()-MAP.get(idNum)>OUT_TIME){flag= true;}else{flag= false;}}else{flag= true;}MAP.put(idNum, System.currentTimeMillis());//当数量过多做一次清除if(MAP.size()>OUT_SIZE){new Thread(){@Overridepublic void run() {for (Entry<String, Long> entry :MAP.entrySet() ) {if(System.currentTimeMillis()-entry.getValue()>OUT_TIME){MAP.remove(entry.getKey());}       }}}.start();}return flag;}

幂等性的研究及后台验证短时间内同一申请是否重复提交的方案相关推荐

  1. Struts2表单验证、模型驱动、防重复提交、数据回显

    1)表单验证 strus的表单验证通过使用struts内置的vlidation拦截器来完成.使用相对比较简单,有以下步骤需要完成. a,写一个xml配置文件(和需要验证的action必须同包),文件名 ...

  2. java 后端 验证码逻辑_Java后端产生验证码后台验证功能的实现代码

    直接跳severlet在java后台生成验证码: @RequestMapping(value="yzm.action") public void Yzm(HttpSession s ...

  3. Spring Boot 后台验证 Hibernate Validation

    后台验证详解 开发项目过程中,后台在很多地方需要进行校验操作,比如:前台表单提交,调用系统接口,数据传输等.而现在多数项目都采用MVC分层式设计,每层都需要进行相应地校验. 针对这个问题, JCP 出 ...

  4. asp.net mvc中的后台验证

    asp.net mvc的验证包含后台验证和前端验证.后台验证主要通过数据注解的形式实现对model中属性的验证,其验证过程发生在model绑定的过程中.前端验证是通过结合jquery.validate ...

  5. 干货-Google支付后台验证操作流程【业务后台-GP后台流程】

    整个开发背景是前端在调用完google play支付流程后,需要后台验证支付结果以及在自己的服务生成订单相关信息. 由此着手对google后台验证的调研,首先官方流程: 点我查看官方流程 整个操作流程 ...

  6. 谷歌pay服务端文档_google支付后台验证操作流程

    整个开发背景是前端在调用完google play支付流程后,需要后台验证支付结果以及在自己的服务生成订单相关信息.由此着手对google后台验证的调研,首先官方流程: https://develope ...

  7. 风吹雪支付系统易支付去后台验证版本代理系统

    介绍: 风吹雪系统易去后台验证版本代理系统个人易完整100%可运行网站源码 自带微信宝官方通道,资质需要自己申请,也可以对接免签平台,如需对接其他接口自行对接! 整站系统包含:总管理后台,代理功能,商 ...

  8. 解决:微信支付坑多?其实很简单!在WXPayEntryActivity回调方法中向后台验证支付结果,但获取不到OrderID,下面几种办法应该可以解决。

    如标题,好久没做微信支付,之前的坑忘了,今天又遇到,记下来供朋友们参考,话不多说,先大致简单的介绍一下集成微信支付的流程,就几行字的事,希望朋友们有点耐心. Step1. 在微信开放平台上下载微信的S ...

  9. css3 滑动验证,Vue 实现拖动滑块验证功能(只有css+js没有后台验证步骤)

    vue验证滑块功能,在生活中很多地方都可以见到,那么使用起来非常方便,基于vue如何实现滑块验证呢?下面通过代码给大家讲解. 效果图如下所示: 拖动前 拖动后 代码引用的css与js都是线上的 将代码 ...

最新文章

  1. dows 性能监控软件 Spotlight On Windows
  2. POJ3692 最大点权独立集元素个数
  3. 深度学习(计算机视觉)面试中问题(一)
  4. 【项目实战课】基于Pytorch的3DCNN视频分类与行为识别实战
  5. Boost.Flyweight 序列化示例
  6. php 弹窗代码大全,PHP_asp.net弹出窗口代码大全,//关闭,父窗口弹出对话框,子窗 - phpStudy...
  7. Windows环境下安装、卸载Apache
  8. groovy+mysql数据库_使用Groovy连接到MySQL
  9. 关于OpenCV的基本数据类型
  10. 苹果Mac侧边栏笔记工具:​​​​​​​​SideNotes
  11. JESD204B学习之关键点问答
  12. 利用R语言进行具有周期性的时间序列分析
  13. 合唱队形java_动态规划练习题-合唱队形
  14. FPGA集成开发环境
  15. 微信小程序发布时需要校验违法违规内容、图片,Java后端接口
  16. js 去掉字符串最后一个逗号
  17. 最通俗易懂的python与mysql数据库交互
  18. 红旗linux 输入法问题,红旗Linux牵手搜狗输入法 带给用户无拘无束输入体
  19. 2022登高架设考试模拟100题模拟考试平台操作
  20. 法律部门和法律体系(概念、我国现行的法律部门和法律体系 )、法 律 关 系(概念、构成要素:主体、内容、客体)、法律事实(法律事件、法律行为)

热门文章

  1. CPU数,核心数,线程数的关系
  2. 火锅馆取名支那引发公愤续:老板下跪道歉
  3. 编译内核报错Cannot generate ORC metadata for CONFIG_UNWINDER_ORC=y, please install libelf-dev, libelf-deve
  4. 华为Mate40、华为Mate40Pro、华为Mate40Pro+和华为Mate40RS保时捷值得买吗
  5. 关于as608指纹模块的学习心得
  6. 台式计算机怎么看有没有开独显,台式机独立显卡怎么样打开
  7. volatile为什么不能保证原子性
  8. Linux换装win7蓝屏,惠普280 Pro G5 MT电脑Win10改Win7蓝屏重启解决方法
  9. 工具-maya2014软件操作细节(持续更新……)
  10. sap 查看服务器文件夹,查看系统状态