【实用技巧】MD5 的重复请求应用以及性能测试
1 前言
大家可能都遇到幂等或者娇艳重复提交的问题,比如重复的 JSON 请求、文件上传相同的文件重复上传了两次等,当然了确实存在某种情况比如人家用户一会上传了一个文件隔了一会儿又上传一个同样的文件是合理的,我们要做的就是短时间内的重复提交。
这个时候我们可以通过计算请求的 MD5值来进行过滤,比如计算出来的 MD5 放到 Redis 里(设置上过期时间比如1分钟),然后每次请求先看下Redis 中是否存在相同的 MD5,有的话说明是重复请求直接打回即可,当然了前端也能校验,但是后端的校验还是要有的。
MD5 的特点:相同的内容每次计算的MD5值一样,但凡有一丁点变化 MD5 就不一样
那么比如对于某个文件可能有 10K、5M、60M、100M,那么 MD5 值的计算效率如何呢?我们本节来小测一下。
2 实践
2.1 测试代码
我这里就直接贴了哈:
package com.virtuous.demo.laboratory.algorithm.md5; import org.springframework.util.StopWatch; import java.io.*; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class MD5FileExample { // 8K 缓冲区 private static final int BUFFER_SIZE = 8192; public static String calculateMD5(File file) throws NoSuchAlgorithmException, IOException { MessageDigest md = MessageDigest.getInstance("MD5"); try ( InputStream is = new FileInputStream(file); BufferedInputStream bis = new BufferedInputStream(is); ) { byte[] buffer = new byte[BUFFER_SIZE]; int bytesRead; while ((bytesRead = bis.read(buffer)) != -1) { // 逐增更新 MD5 md.update(buffer, 0, bytesRead); } } byte[] digest = md.digest(); StringBuilder sb = new StringBuilder(); for (byte b : digest) { sb.append(String.format("%02x", b)); } return sb.toString(); } public static void main(String[] args) { // 替换为你的文件路径 StopWatch stopWatch = new StopWatch(); stopWatch.start(); File file = new File("/Users/kuku/projects/wode/virtuous-demo/src/main/resources/test.docx"); try { String md5Hash = calculateMD5(file); stopWatch.stop(); System.out.println("总计耗时:" + stopWatch.getTotalTimeMillis()); System.out.println("MD5: " + md5Hash); } catch (NoSuchAlgorithmException | IOException e) { e.printStackTrace(); } } }
2.2 测试效果
2.2.1 MD5 效果
我们先看看 MD5 的效果:
我这里有个文件,我们先看看在不改变文件内容的情况下,是不是每次计算的 MD5 值是不是一样的,按理应该是一样的哈。
我这里就不拿 Jmeter 压测了哈,我就测了几遍:
应该都是一样的哈,当我把文件内容只改了一个字的时候,再来计算一下:
可以看到已经变化了哈,还别说这玩意挺强啊。
2.2.2 MD5 计算性能测试
这里我就不一一截图了哈,我直接把我的数据贴出来哈(每个文件我都执行了3次):
文件大小 | 耗时 |
22K | 50ms左右 |
223K | 60ms左右 |
1.4M | 70ms左右 |
4.4M | 80ms左右 偶尔102ms |
12M | 90ms左右 偶尔124ms |
33M | 190ms左右 偶尔142ms 偶尔214ms |
看上去这个效果我是觉得还行。
3 小结
好啦,大家也可以测试一下,一起来讨论一下。