redis动态计算限制次数

基于第三方接口调用情况,某个第三方接口次数超过限制时,会锁定账号,账号锁定后需要进行一系列麻烦的操作解锁账号,所以会限制在一定时间内第三方接口调用次数。比如,限制1分钟中内调用次数不超过35次,一小时内不超过350次。具体实现思路如下:

redis提供相关的接口能够统计有效期内key的个数,该方法如下

//	 yh1mKey表示前缀,前缀一般固定,比如项目名demo:YH1H,“*”表示后缀任意
Set keys = stringRedisTemplate.keys(yh1mKey + "*");

只要满足相关的条件,继续调用接口,否则忽略接口调用,不做任何处理,结束调用流程。

1.核心类YHKiss

java代码:

@Autowired
private StringRedisTemplate stringRedisTemplate;

private int hour = 350;
private int minute = 35;

//检查是否超过接口调用次数
public boolean checkEnable() throws InterruptedException {
	String yh1m = "test:YH1M";
	String yh1h = "test:YH1H";
	KissCount count1m = count(yh1m);
	KissCount count1h = count(yh1h);
	if (count1m.getCount() < minute && count1h.getCount() < hour) {
		this.set(yh1m + "_" + UUID.randomUUID().toString(), "1", 60l);
		this.set(yh1h + "_" + UUID.randomUUID().toString(), "1", 3600l);
		return true;
	} else {
		log.info(
				"YHCX-分钟:" + count1m.getCount() + ",最近等待:" + (count1m.getCount() < minute ? 0 : count1m.getNext()));
		log.info("YHCX-小时:" + count1h.getCount() + ",最近等待:" + (count1h.getCount() < hour ? 0 : count1h.getNext()));
		return false;
	}

}

//set redis
private boolean set(final String key, String value, Long expireTime) {
	boolean result = false;
	try {
		stringRedisTemplate.opsForValue().set(key, value, expireTime, TimeUnit.SECONDS);
		result = true;
	} catch (Exception e) {
		e.printStackTrace();
	}
	return result;
}

//统计相应key有效期内在redis的确定个数
private KissCount count(String yh1mKey) {
	KissCount count = new KissCount();
	Set keys = stringRedisTemplate.keys(yh1mKey + "*");
	count.setCount(keys.size());
	int next = Integer.MAX_VALUE;
	for (String key : keys) {
		if (key != null && get(key) != null) {
			Long e = stringRedisTemplate.getExpire(key);
			next = Math.min(next, e.intValue());
		}
	}
	count.setNext(next);
	return count;
}

public Object get(final String key) {
	final String result = stringRedisTemplate.opsForValue().get(key);
	return result;
}

2.测试类

@Test
public void test2() throws Exception {
    for (int i=0; i<300; i++) {
        boolean rs = YhKiss.checkEnable();
        if (rs) {
            System.out.println("未超");
            stringRedisTemplate.opsForValue().set("test" + i, i + "", 60, TimeUnit.SECONDS);
        } else {
            System.out.println("超了");
        }
    }
}

3.demo地址
https://github.com/13162576590/redis-demo

你可能感兴趣的:(java,redis,java,redis)