流量限制锁:
我们用zset存储当前时间戳,只要总数量大于界限值就进行限流。
假设,限流1秒100次。
具体步骤
1、 删除大于当前时间1秒的数据。
2、 判断剩下set的size是否大于100。大于就直接的返回限流。
3、 不大于就插入当前时间戳到zset 中。
如果使用的是redis集群就需要在限流前面加锁排他锁。
代码
public boolean isOverLimitRate(String key, int num, int second) {
RedisCallback<Boolean> callback = (RedisConnection connection) -> {
RedisSerializer<String> stringSerializer = redisTemplate.getStringSerializer();
byte[] keyData = stringSerializer.serialize(key);
//添加当前时间戳到redis
connection.zAdd(keyData, System.currentTimeMillis(), stringSerializer.serialize(System.currentTimeMillis() + ""));
//删除大于限流时效的数据
connection.zRemRangeByScore(keyData, 0d, System.currentTimeMillis() - second * 1000d);
Optional<Long> optional = Optional.of(connection.zCard(keyData));
//判断数量
boolean result = optional.map(count -> count > num).orElse(Boolean.FALSE);
double percentage = (optional.get() == null || num == 0) ? 0 : optional.get() / (num + 0d);
if (percentage >= 0.8d && percentage <= 1) {
log.warn(“限流告警”);
} else if (percentage > 1) {
log.error("超出限流”);
}
return result;
};
return redisTemplate.execute(callback);
}