redis实现访问限制
来源:互联网 发布:淘宝开店要注册公司吗 编辑:程序博客网 时间:2024/05/29 19:05
package redis;import redis.clients.jedis.HostAndPort;import redis.clients.jedis.JedisCluster;import java.util.Arrays;import java.util.HashSet;import java.util.Set;public class RedisLimit { private JedisCluster jedisCluster; private String key; /** * 限制次数 */ private int limit; /** * 限制时间 毫秒 */ private long expire; private static final String LUA_SIMPLE_CHECK = " local size = redis.call('get',KEYS[1]) " + " if size and tonumber(size) >= tonumber(ARGV[1]) then " + " return 1 " + " end " + " local incr = redis.call('incr',KEYS[1]) " + " if incr == 1 then " + " redis.call('pexpire',KEYS[1],ARGV[2]) " + " end " + " return 0 "; private static String luaSimpleCheckSha; private static final String LUA_PRECISE_CHECK = " local size = redis.call('llen',KEYS[1]) " + " local timeNow = tonumber(ARGV[3])" + " if size >= tonumber(ARGV[1]) then " + " local tiemOld = redis.call('lpop',KEYS[1]) " + " redis.call('rpush',KEYS[1],timeNow) " + " if timeNow - tonumber(tiemOld) < tonumber(ARGV[2]) then" + " return 1 " + " else " + " return 0" + " end " + " end " + " redis.call('rpush',KEYS[1],timeNow)" + " return 0"; private static String luaPreciseCheckSha; public RedisLimit(JedisCluster jedisCluster, String key, int limit, int expire) { this.jedisCluster = jedisCluster; this.key = key; this.limit = limit; this.expire = expire; } /** * 在给定的时间内限制访问多少次。如果超过了则返回true * 简单判断不够准确 优点存储数据量低 * 这些操作不是原子性的 */ public boolean simpleCheck() { String sizeStr = jedisCluster.get(key); if (sizeStr != null && Long.valueOf(sizeStr) >= limit) { return true; } Long incr = jedisCluster.incr(key); if (incr == 1) { jedisCluster.pexpire(key, expire); } return false; } /** * 在给定的时间内限制访问多少次。如果超过了则返回true * 简单判断不够准确 优点存储数据量低 * 通过lua实现原子性操作 */ public boolean simpelCheckByLua() { if (luaSimpleCheckSha == null) { luaSimpleCheckSha = jedisCluster.scriptLoad(LUA_SIMPLE_CHECK, "luaSimpleCheck"); } Long eval; try { eval = (Long) jedisCluster.evalsha(luaSimpleCheckSha, Arrays.asList(key), Arrays.asList(String.valueOf(limit), String.valueOf(expire))); } catch (Exception e) { //TODO 打印日志 e.printStackTrace(); eval = (Long) jedisCluster.eval(LUA_SIMPLE_CHECK, Arrays.asList(key), Arrays.asList(String.valueOf(limit), String.valueOf(expire))); } return eval == 1; } /** * 精确判断 缺点是存储数据量多 依赖服务器时间戳 */ public boolean preciseCheck() { Long card = jedisCluster.llen(key); if (card >= limit) { //移除最早访问时间 String timeOld = jedisCluster.lpop(key); //当前访问时间 long timeNow = System.currentTimeMillis(); jedisCluster.rpush(key, String.valueOf(timeNow)); if (timeNow - Long.valueOf(timeOld) < expire) { return true; } else { return false; } } long timeNow = System.currentTimeMillis(); jedisCluster.rpush(key, String.valueOf(timeNow)); return false; } public boolean preciseCheckByLua() { if (luaPreciseCheckSha == null) { luaPreciseCheckSha = jedisCluster.scriptLoad(LUA_PRECISE_CHECK, "luaPreciseCheck"); } Long eval; try { eval = (Long) jedisCluster.evalsha(luaPreciseCheckSha, Arrays.asList(key), Arrays.asList(String.valueOf(limit), String.valueOf(expire), String.valueOf(System.currentTimeMillis()))); } catch (Exception e) { //TODO 打印日志 e.printStackTrace(); eval = (Long) jedisCluster.eval(LUA_PRECISE_CHECK, Arrays.asList(key), Arrays.asList(String.valueOf(limit), String.valueOf(expire), String.valueOf(System.currentTimeMillis()))); } return eval == 1; } public static void main(String[] args) { HostAndPort hostAndPort1 = new HostAndPort("ip", 20621); HostAndPort hostAndPort2 = new HostAndPort("ip", 20622); HostAndPort hostAndPort3 = new HostAndPort("ip", 20622); Set<HostAndPort> set = new HashSet<>(); set.add(hostAndPort1); set.add(hostAndPort2); set.add(hostAndPort3); JedisCluster jedisCluster = new JedisCluster(set); RedisLimit redisLimit = new RedisLimit(jedisCluster, "localhostzhpincr", 10, 100); for (int i = 0; i < 50; i++) { if (redisLimit.simpelCheckByLua()) { System.out.println("超过限制"); } else { System.out.println("可以执行"); } } }}
阅读全文
0 0
- redis实现访问限制
- redis实现访问频次限制的几种方式
- redis实现访问频次限制的几种方式
- 0140 redis实现访问频次限制的几种方式
- Java通过redis实现接口ip访问频率限制
- Redis小案例(一):实现网站访问频率限制
- redis 限制并发锁访问
- redis 实现 ip 限制
- PHP中Yii2框架用redis实现限制接口访问次数
- Redis 过期时间、访问限制与缓存
- redis 开放外网访问限制
- 【三】Springboot+Redis实现密码次数限制
- java实现redis数据库访问
- Redis实现访问流量控制
- php 使用redis锁限制并发访问类
- redis限制单ip、单用户的访问次数
- php 使用redis锁限制并发访问类
- redis限制单ip、单用户的访问次数
- Nexus3的功能介绍-简单版
- vue新建项目(二)vue-cli项目结构
- 软件开发环境-开发环境、测试环境、生产环境的区别
- [Codeforces 894E] Ralph and Mushrooms
- html5 pattern属性的使用
- redis实现访问限制
- Libcurl & Log4cplus 移植和使用 以及 Jsoncpp 简单使用
- ionic常见问题及解决方法
- spring-boot-autoconfigure 是如何工作的?
- IDEA的Springmvc单元测试
- ESP8266 Flash
- 笔试题
- 设计模式(一)工厂模式
- Linux centos ssh 暴力攻击应对方法 添加自定义root用户 更改ssh端口