shiro redis获取在线人数超过1W时,造成redis慢查询问题

博主有个springboot项目有个获取在线人数的需求,session使用的是shiro、redis分布式存储。一开始直接用了 Collection sessions = redisSessionDAO.getActiveSessions();这个方法内部是使用了redis命令中的keys *。

keys *命令的原理是扫描整个redis里面所有的key,然后根据通配符模糊查找出来,所以他的时间复杂度是O(N)。在匹配key少的话是没问题的。超过1w的情况下,查询时间能达到10S。因为redis是单线程的,这样就会长时间占用cpu,可能导致其他的redi连接超时。所以就想优化下。在网上搜了版本,发现了可以用scan命令替代keys *命令。

相比于keys命令,scan命令有两个比较明显的优势:

  1. scan命令的时间复杂度虽然也是O(N),但它是分次进行的,不会阻塞线程。
  2. scan命令提供了limit参数,可以控制每次返回结果的最大条数。

不过scan命令也并不是完美的,它返回的结果有可能重复,因此需要客户端去重。但博主的获取在线人数只是个参考,不需要非常精确,所以也没有去重O(∩_∩)O哈哈~ 。至于scan为什么会重复,大家可以查看 redis scan原理.下面直接上代码


                    int size = 0;
                    String realKey="shiro_redis_session" + "*";
                    Long count = 1000L;
                    List<Integer> numList = new ArrayList<>();
      
                        redisTemplate.execute((RedisCallback<Integer>) connection -> {
                            Cursor<byte[]> cursor = connection.scan(new ScanOptions.ScanOptionsBuilder().match(realKey).count(count).build());
                            while (cursor.hasNext()) {
                                byte bytes[] = cursor.next();
                                Session session = (Session) SerializeUtils.deserialize(redisSessionDAO.getRedisManager().get(bytes));
                                if(session == null){
                                    continue;
                                }
                                Map<String,Object> mapUser = (Map<String,Object>) SerializeUtils.deserialize((byte[]) session.getAttribute("user"));
                                if(CollectionUtils.isEmpty(mapUser)){
                                    continue;
                                }
                                numList.add(1);
                            }
                            return 1;
                        });
                        size = numList.size();
后记

后面部署上线发现,redis慢查询没有了,但是cpu却是每次执行这个命令,会飙升至 90%。因为我们这个代码执行逻辑是1小时一次。所以cpu每隔1小时就会飙升,然后迅速下降。这个问题让我很是纠结。下面是redis cpu使用率图
在这里插入图片描述

大家有什么改善的方法吗,可以给我留言。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

haohao123nana

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值