注意到redis写入慢的问题
开始发现问题是因为发现写入redis越来越慢
刚开始做法
for {
//获取redis连接,
//写入一条
//释放连接
}
这样子3w条redis数据 需要24分钟
第一次尝试
修改逻辑为只获得一次连接
//获取redis连接
for{
//写入一条
}
//释放连接
速度有了提高 但是仍在5分钟左右
最终解决方案
//获取redis连接
//创建管道
for{
//写入管道
}
//将管道数据写入redis
速度显著提高 插入3w条数据 只需要8秒
原因
- redis和java项目不在同一台服务器 建立连接开销比在同一台物理机大得多 这是前提
- redis是一个cs模式的tcp server,使用和http类似的请求响应协议。一个client可以通过一个socket连接发起多个请求命令。每个请求命令发出后client通常会阻塞并等待redis服务处理,redis处理完后请求命令后会将结果通过响应报文返回给client.基本上四个命令需要8个tcp报文才能完成。由于通信会有网络延迟,假如从client和server之间的包传输时间需要0.125秒。那么上面的四个命令8个报文至少会需要1秒才能完成。这样即使redis每秒能处理100个命令,而我们的client也只能一秒钟发出四个命令。这显示没有充分利用 redis的处理能力。除了可以利用mget,mset 之类的单条命令处理多个key的命令外我们还可以利用pipeline的方式从client打包多条命令一起发出,不需要等待单条命令的响应返回,而redis服务端会处理完多条命令后会将多条命令的处理结果打包到一起返回给客户端。
解决方案代码
Jedis client = jedisPool.getResource(); try { Pipeline pipeline = client.pipelined(); for (String key:inMap.keySet()){ Map<String , String> valueMap = inMap.get(key); pipeline.hmset(key, valueMap); pipeline.expire(key, 60*60); } pipeline.sync(); }catch (Exception e){ logger.error("inser into redis error!", e); }finally { jedisPool.returnResource(client); }