前言

在业务设计中防重设计是一个关键点,以接口设计为例,防重就是防止接口被多次调用而产生脏数据,比如支付订单出现重复支付,所以说防重至关重要,在如何防重之前我们首先看一下是如何出现重复请求的。

何时出现多次调用

多次调用接口的出现有主观原因比如:人为的重复请求攻击,用户的误操作等;也有客观原因比如:为了健壮性进行超时重试;重复请求攻击

对于这种恶意攻击,其实已经属于安全范畴了,我们可以通过黑名单+限流来处理,下一步再考虑防重处理;用户的误操作

比如用户在界面点击提交按钮,因为手误出现多次点击提交,这种情况客户端可以做一些处理,减少用户的误操作,比如提交完按钮变灰等;当然提供方的防重处理也是必不可少的;超时重试

接口调用方为了保证系统的健壮性,往往会做一些重试处理,比如各种RPC框架都已经帮我们内置了容错机制,提供方需要做好防重;

如何做好防重处理,其实核心就是保证多个相同的请求只有一次被执行,或者说多次调用和一次调用产生的效果是一样的,也就是我们经常说的要保证幂等性;

何时需要防重

所有的操作说到底都是增删改查,其实我们真正需要做防重处理的,更重要的是增加和修改;查询和删除本身执行一次和多次,产生的效果是一样的,有天然幂等性,虽然说有天然幂等性,但是查询和删除本身也是要消耗资源的,如果能防止重复执行,也能节省资源; 增加和修改是必须要做防重的,增加可以以下单为例,修改可以以更新库存为例,如果没有做好防重后果是非常严重的;下面具体看看都有哪些防重的措施;

如何防重

上面说到主要是针对增加和修改需要做好防重处理,当然针对增加和修改其实是有不同的防重措施,也有统一的方式,下面分别介绍;

统一防重token机制

服务器需要提供获取token机制的服务,这样每次客户端请求的时候先获取token,服务器端会将token保存在redis中;客户端发送请求的时候会带上token,这样服务器端可以拿到token直接去redis中做删除处理,根据返回值判断是否成功:localhost:0>get token "111" localhost:0>del token "1" localhost:0>del token "0"

通过redis存放token,这样在分布式环境下也能很好的工作;防重key

根据请求参数生成md5密文,然后用此密文作为key存入redis中,可以通过使用setnx命令来保证只有一个能保存成功;key = MD5.md5("param1="+param1+"¶m2="+param2...) localhost:0>setnx key 1 "1" localhost:0>setnx key 1 "0"防重表

可以利用表的唯一索引约束,可以使用类似防重key作为唯一索引字段,多次请求过来只会有一个插入成功,为了防止防重表数据过多,可以启动一个定时器定时清理;

以上几种方式其实和具体的业务关系不大,可以适用大部分场景;而且通过redis或者数据库,以及原子性操作来保证在分布式环境下也可以很好的运行;

插入防重select+insert

插入数据最先想到就是先检查有没有,然后在插入,但是这样明显存在两个操作,不是原子性操作,单节点下还能通过锁来解决,分布式环境下就需要用到分布式锁来保证原子性了;当然也可以结合其他方式一起使用,比如下面的唯一主键机制;唯一主键

这种方式其实就是不直接使用数据库的自增主键了,使用分布式id算法生成,这样在插入数据的时候就可以通过唯一主键来进行约束,保证只会有一条成功;回滚机制

有些业务其实是有正向流程和逆向流程,比如支付订单,在接收到银行返回的支付成功通知时判断订单的状态,如果已经支付成功,可以直接走退款流程;

更新防重乐观锁方式

乐观锁常被用在更新场景中,如下面通过版本号的方式来实现:update table_name sale = sale + 1, version = version + 1, WHERE id = #{id} AND version = #{version}状态机乐观锁

在相关订单的业务中,很多都会涉及到状态机,状态是流转的,有了上一个状态才会有下一个状态,比如常见的购物订单包括:提交未支付,支付成功,待发货,发货中,已签收等,每个状态都需要前置状态;update table_name set  status = 下一个状态    where  id = #{id} and status = #{status}

总结

防重的方法很多,我们往往需要更加自己的业务做相关的选择,不同的业务,不同的业务量,不同的容忍程度都会影响我们如何去做防重;每种方式也不是都是独立存在的,有时候往往需要多种方式整合起来。

java 防重_如何做一个防重设计相关推荐

  1. java字符存储_用java的类集框架做一个字符存储器(15)

    11.这是java的关于java的类集框架做一个字符存储器的源代码可以直接进行编译运行,希望大家能够从中获益良多. package niming; //导入ArrayList这个类 import ja ...

  2. 网站留言板防重复留言_如何做一个2000年风格复古的个人网站(3)创建个人小站-主页...

    上一章,我们创建了首页. 下面我们准备开始做主页. 先新建一个页面:home.htm 主页相对于展现个性的首页,内容要多很多,那么就要讲究排版了. 当时流程的排版还是用 table,div 大概是 2 ...

  3. java 正负随机_如何产生一个随机的[0, n)范围内的Short值

    背景 最近在做一个Java的随机对象生成器.需要随机产生一些在[0, n)范围内的short值. 坑 很多人可能会说,这有什么难的,我刚学编程的时候就会了.然后给出下面代码. short value ...

  4. 用python做生日礼物_如何做一个网页送给女朋友做生日礼物?

    如何做一个网页送给女朋友做生日礼物 本文里面涉及到python,HTML ,css,JavaScript的知识,是基于python的flask框架做的一个小型网站,里面可以实现跳转功能,怎么配置fla ...

  5. Java项目之模仿CSDN做一个DBB博客

    项目源代码下载地址:https://download.csdn.net/download/mdxiaohu/10596423 不打算深入讲解,只做个记录. 上个月,做了个博客小项目练手. 当时的想法就 ...

  6. 小程序从浏览器返回有一个空白页_北京做一个小程序

    北京做一个q0430f小程序 婚纱摄影行业一直被认为是暴利行业.除了进入门槛低,没有积压货物的风险.但近年来,随着各种数码设备的普及和私人摄影师的崛起,婚纱摄影店基本告别了"暴利时代&quo ...

  7. 一个form 如何做两次提交_如何做一个优秀的家长

    如何做一个优秀的家长 文|潍坊坊子崇文中学 父母对待孩子无外乎三种情况:一是事事管.时时管,做了很多事,效果却不好:二是什么都不管,什么都不做,放任自流,不闻不问,结果更不好:三是也管但不全管,做得不 ...

  8. 一个form 如何做两次提交_如何做一个自信魅力的女人

    有一种常见的说法是外观完全决定了吸引力,错,如果你希望人们被你吸引,如果你想做一个优秀的.成功的.万众瞩目的女性,那么你必须做很多努力,才能成为一个有魅力的人. 1做自己 不要复制像杰西卡兰格或安德里 ...

  9. 城市代码表_从零开始做一个SLG游戏(六)游戏系统以及配置表

    本文主要是来梳理下游戏内的基本系统(虽然只是照搬polytopia的,但是还是要总结一下),并预先做一些配置表,并实现读取. 一.经济系统 1.总述 经济系统可以是整个游戏的核心.在本游戏中只有一种资 ...

最新文章

  1. 一个“Internal”牵扯出的代码泄露,阿里云独家回应
  2. 网络 IO 演变过程
  3. hdfs中与file数组类似的数组_Chapter05 Java中的数组
  4. WPF 表格控件 ReoGrid 的简单使用
  5. 程序员 rs编码_为什么声明性编码使您成为更好的程序员
  6. 05_DecisionTree_统计学习方法
  7. TortoiseSVN 命令 (命令行执行工具)
  8. 2016 Android Top 10 Library
  9. visio中公式太小_冲压模具设计:冲床吨位计算公式、实例分析,设计师值得一看...
  10. 烽火FSU设备通过中国铁塔测试
  11. 微信小程序(十二)uni-app框架开发及组件库
  12. linux下对IP地址的转发和端口的伪装----利用iptables部署
  13. XP系统访问网页无法下载php,window_WinXP因配额不足导致无法访问如何解决,  WindowsXP系统虽然说是已经 - phpStudy...
  14. 升级啦!二维码签到适用PC+andriod+IOS-PHP源码-开源代码
  15. dp入门(01/28)
  16. 快速检查局域网内网络延迟
  17. 如何优雅的将Mybatis日志中的Preparing与Parameters转换为可执行SQL
  18. AltiumDesigner如何绘制PCB封装
  19. 记一次JVM故障排除
  20. java计算机毕业设计数据分析星辰网智能手机销售网站源码+mysql数据库+系统+lw文档+部署

热门文章

  1. BZOJ2424 [HAOI2010]订货
  2. [Android]AndroidInject增加sqlite3数据库映射注解(ORM)
  3. 【深入】java 单例模式
  4. SVG与CSS的特殊性
  5. jQuery框架总体分析
  6. Web应用开发平台 OpenJWeb
  7. 没有主清单属性_梦幻西游电脑版:神威组第一大唐?大佬两天更新200W硬件,这身属性难被超越!太狠了...
  8. ldaptemplate 分页_UI设计干货分享:设计语言 - 侧边导航栏/分页
  9. 中科罗伯特机器人吧_延庆旧县南站附近继续教育
  10. 适合节日促销的海报设计PSD分层模板|夜晚烟花,浓浓喜庆氛围