作者:慕容千语
来源:http://suo.im/5PaEZI
前言:
在实际的开发项目中,一个对外暴露的接口往往会面临,瞬间大量的重复的请求提交,如果想过滤掉重复请求造成对业务的伤害,那就需要实现幂等!
我们来解释一下幂等的概念:
任意多次执行所产生的影响均与一次执行的影响相同。按照这个含义,最终的含义就是 对数据库的影响只能是一次性的,不能重复处理。
如何保证其幂等性,通常有以下手段:
1、数据库建立唯一性索引,可以保证最终插入数据库的只有一条数据
2、token机制,每次接口请求前先获取一个token,然后再下次请求的时候在请求的header体中加上这个token,后台进行验证,如果验证通过删除token,下次请求再次判断token
3、悲观锁或者乐观锁,悲观锁可以保证每次for update的时候其他sql无法update数据(在数据库引擎是innodb的时候,select的条件必须是唯一索引,防止锁全表)
4、先查询后判断,首先通过查询数据库是否存在数据,如果存在证明已经请求过了,直接拒绝该请求,如果没有存在,就证明是第一次进来,直接放行。
redis实现自动幂等的原理图:
一、搭建redis的服务Api
1、首先是搭建redis服务器。
2、引入springboot中到的redis的stater,或者Spring封装的jedis也可以,后面主要用到的api就是它的set方法和exists方法,这里我们使用springboot的封装好的redisTemplate
-
/**
-
* redis工具类
-
*/
-
@Component
-
public class RedisService {
-
@Autowired
-
private RedisTemplate redisTemplate;
-
/**
-
* 写入缓存
-
* @param key
-
* @param value
-
* @return
-
*/
-
public boolean set(final String key, Object value) {
-
boolean result = false;
-
try {
-
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
-
operations.set(key, value);
-
result = true;
-
} catch (Exception e) {
-
e.printStackTrace();
-
}
-
return result;
-
}
-
/**
-
* 写入缓存设置时效时间
-
* @param key
-
* @param value
-
* @return
-
*/
-
public boolean setEx(final String key, Object value, Long expireTime) {
-
boolean result = false;
-
try {
-
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
-
operations.set(key, value);
-
redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
-
result = true;
-
} catch (Exception e) {
-
e.printStackTrace();
-
}
-
return result;
-
}
-
/**
-
* 判断缓存中是否有对应的value
-
* @param key
-
* @return
-
*/
-
public boolean exists(final String key) {
-
return redisTemplate.hasKey(key);
-
}
-
/**
-
* 读取缓存
-
* @param key