使用redis限流几个问题

背景

自己搭建一个短信中间服务,上游网关限流100tps,否则发送失败,要求短信中间服务出去的tps不能大于100,之前使用过漏斗算法,后来因为服务双节点问题想使用redis一同管控,使用一段时间发现redis限流失败,一顿瞎折腾,折腾过程记录如下。

原因分析

1,请求量较多(100+)导致redis报错Jedis [B cannot be cast to java.lang.Long

2,当限流触发后继续频繁无效请求,浪费资源

调试过程

1,问题1:Jedis [B cannot be cast to java.lang.Long

主要原因是在于并发多线程环境下,如果一直使用单实例Jedis,单请求/线程没问题,多线程会争抢资源,就会出现B cannot be cast to java.lang.Long等错误。
调试发现出现问题的几段代码处,均是直接操作jedis的方法调用,没有进行调用后close实例:

#代码片段
public Jedis getJedis() throws Exception {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();//获取一个jedis实例
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("错误日志:" + e.getMessage());
        }
        return jedis;
    }
#错误调用jedis方法
 getJedis().zcard("xxxx");
 #-----------------------------------------------------------------------------------
 #封装jedis方法
 public long zcard(String key){
        Jedis jedis = null;
        long count = 0;
        try {
            jedis = jedisPool.getResource();//获取一个jedis实例
            count=jedis.zcard(key);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("错误日志:" + e.getMessage());
        } finally {
            jedis.close();
        }
        return count;
    }
#正确调用示例
xxjedisUtil.zcard("xxxx");

2,问题2-限流后频繁无效请求

由于拦截后直接return,请求过来再继续拦截,浪费系统资源,计划增加一段间隔期,1s后再继续执行,使用了几种方案。
1,尝试使用sleep(1000),测试发现多线程下sleep时间会叠加,出现10s以上的中断期,具体原因还未搞清楚,哪位大神了解请指教
2,尝试使用wait(),关于sleep和wait的区别大家可以自行搜索,看了半天也没搞懂,最开始是直接实例化一个object对象后调用wait方法,运行发现会抛一个异常:在这里插入图片描述
3,后来使用同步锁解决该异常

Object lock = new Object();
        synchronized (lock) {
            if (!FunnelRateRedisLimiter.isPeriodLimiting("CONSUMER_MSG_LIMIT_" + smsQueueName, 1,
                Integer.valueOf(smsQueueNameLimit))) {
                channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
                logger.error(smsQueueName + "!!!:触发限流控制");
//                Object object=new Object();
                //等待1s后再请求
                lock.wait(1000);
                lock.notify();
//                object.notify();
//                Thread.sleep(1000);
                return;
            }
            smsProcess(message, channel);
        }

调整线程数以及流控数量适配流控需求

调整线程池大小

调整流控大小

附录

关于限流方案:https://blog.csdn.net/liaojiamin0102/article/details/106532857/

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值