jedis批量删除token耗时,怎么办

业务场景描述:

当用户登录后会缓存一个新的token,该token有效期为180天,假设有个用户在多台设备上反复登录,那么当该用户更新密码时候,会删除历史所有未过期的token,数量可能很多,这时候逐个删除的话会耗时好几秒的时间。
未修改之前的代码贴上:

JwtToken jwtToken = new JwtToken();
jwtToken.setUserId(userId);
//获取数据库中当前用户所有的token记录
List<JwtToken> list = jwtTokenService.findList(jwtToken);
for (JwtToken o : list) {
    //删除redis中缓存的token
     JedisUtils.del(RedisConstant.TOKEN_KEY + o.getToken());
     JedisUtils.del(o.getToken());
}
//删除数据库中当前用户所有的token记录
jwtTokenService.deleteWithUserId(userId);

 经测试如果用户token多大上千个,操作则需要五六秒的时间。
尝试解决方法如下,开启jedis通道pipelined,关于pipelined的描述如下:

redis是一个cs模式的tcp server,使用和http类似的请求响应协议。一个client可以通过一个socket连接发起多个请求命令。每个请求命令发出后client通常会阻塞并等待redis服务处理,redis处理完后请求命令后会将结果通过响应报文返回给client。由于通信会有网络延迟,假如从client和server之间的包传输时间需要0.125秒。假设四个命令8个报文至少会需要1秒才能完成。这样即使redis每秒能处理100个命令,而我们的client也只能一秒钟发出四个命令。这显示没有充分利用 redis的处理能力。除了可以利用mget,mset 之类的单条命令处理多个key的命令外我们还可以利用pipeline的方式从client打包多条命令一起发出,不需要等待单条命令的响应返回,而redis服务端会处理完多条命令后会将多条命令的处理结果打包到一起返回给客户端。

这里再贴上修改后的代码:

@Override
    public void deleteAllToken(String userId) {

        JwtToken jwtToken = new JwtToken();
        jwtToken.setUserId(userId);
        List<JwtToken> list = jwtTokenService.findList(jwtToken);
        Jedis jedis= JedisUtils.getResource();
        Pipeline pipeline= jedis.pipelined();
        for (JwtToken o : list) {
            //JedisUtils.del(RedisConstant.TOKEN_KEY + o.getToken());
            //JedisUtils.del(o.getToken());
            pipeline.del(RedisConstant.TOKEN_KEY + o.getToken());
            pipeline.del(o.getToken());
        }


        pipeline.sync();
        jwtTokenService.deleteWithUserId(userId);
    }

经测试发现,性能显著提升,原本要五六秒的操作现在只需要一秒就操作完了。

猜你喜欢

转载自my.oschina.net/u/3387320/blog/2874876
今日推荐