背景:
闲聊八卦下,最近在优化系统的性能,通过pinpont分析,发现许多查询在Redis这块耗时特别不稳定,如下图

那么,框架组大佬丢来了一个解决方案,通过Redis Pipeline管道进行操作的话,会提升处理性能,说白了,就是节省请求-响应往返的时间(简称RTT)
揣着对Pipeline的好奇,以及在多大数据量的情况下的使用场景,于是,搭建了下环境写了几行代码测试下它和普通处理的性能
测试环境
1、应用程序和redis集群皆本机开发环境,避免网络延迟,Redis Cluster master节点3个,无slave节点
2、主要测试查询性能,查询type类型为hash的key 1数据,如下所示:
127.0.0.1:6479> hgetall 1
1) "sex"
2) ""
3) "name"
4) "\"yubing\""
5) "id"
6) "1"
7) "age"
8) "22"
测试代码
1、应用配置信息
spring.application.name=exec-data-redis
server.port=8981
#redis连接配置型
spring.redis.database=0
#spring.redis.host=127.0.0.1
#spring.redis.port=6379
#spring.redis.password=
#redis之 jedis配置信息
##连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=8
##连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=-1
##连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=8
##连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
##连接超时时间(毫秒)
spring.redis.timeout=1000
spring.redis.cluster.nodes=192.168.197.198:6379,192.168.197.198:6479,192.168.197.198:6579
spring.redis.cluster.max-redirects=2
2、单元代码测试样例
@Test
public void pipelineTest() {
long totalCostTime = 0;
int totalNum = 3000;
for (int num = 0; num < totalNum; num++) {
long startTime = System.currentTimeMillis();
redisTemplate.executePipelined(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection redisConnection) throws DataAccessException {
redisConnection.openPipeline();
for (int i = 0; i < 10; i++) {
redisConnection.hashCommands().hGetAll("1".getBytes());
}
return null;
}
});
long costTime = System.currentTimeMillis() - startTime;
totalCostTime += costTime;
System.out.println("pipelineTest查询次数【" + (num + 1) + "】耗时:" + (costTime));
}
System.out.println("================================================================");
System.out.println("total nums :" + totalNum);
System.out.println("total cost times :" + totalCostTime);
System.out.println("avg cost times :" + totalCostTime / totalNum);
System.out.println("================================================================");
}
@Test
public void queryForHashTest() {
long totalCostTime = 0;
int totalNum = 3000;
for (int num = 0; num < totalNum; num++) {
long startTime = System.currentTimeMillis();
for (int i = 0; i < 10; i++) {
redisTemplate.opsForHash().entries("1");
}
long costTime = System.currentTimeMillis() - startTime;
totalCostTime += costTime;
System.out.println("queryForHashTest查询次数【" + (num + 1) + "】耗时:" + (costTime));
}
System.out.println("================================================================");
System.out.println("total nums :" + totalNum);
System.out.println("total cost times :" + totalCostTime);
System.out.println("avg cost times :" + totalCostTime / totalNum);
System.out.println("================================================================");
}
3、结果及结论
| 一次读取数据 | 10 | 20 | 30 | 40 | 80 | 120 | 160 | 200 | 400 | 900 | 1200 |
| 3000次 pipeline查询-平均耗时(单位:毫秒) | 23 | 24 | 24 | 25 | 26 | 28 | 30 | 31 | 41 | 58 | 73 |
| 3000次 普通查询-平均耗时(单位:毫秒) | 2 | 4 | 5 | 7 | 15 | 21 | 24 | 36 | 70 | 156 | 202 |
| 3000次 pipeline总耗时(单位:毫秒) | 70641 | 72735 | 74535 | 75955 | 79011 | 85730 | 90732 | 95646 | 123435 | 176692 | 220023 |
| 3000次 普通查询-平均耗时(单位:毫秒) | 6714 | 12811 | 17454 | 23977 | 45219 | 65830 | 73137 | 109228 | 212814 | 468435 | 607516 |
(1)在每次小数据量查询操作的时候,目测<200的时候(仅参考),普通查询的处理明显优于Redis Pipeline管道查询的处理
(2)Redis Pipeline 管道处理,在随着数据量的逐步增加,处理的耗时增长表现得非常平稳缓慢
(3)普通查询随着数据量的逐步增加,处理的能力逐步减弱,耗时增加
(4)需要注意的是,在第一次执行查询的时候,耗时都比较久,初步判断是由于从Redis连接池获取连接的影响

以上仅做参考,具体的还是要根据实际的系统环境、业务去评判,有不对的地方,请多多包涵!

本文通过测试发现,对于小于200的数据量,普通查询的处理速度优于Redis Pipeline。然而,随着数据量增加,Pipeline处理耗时增长平缓,而普通查询性能下降明显。初次执行查询时,由于连接池获取连接的影响,耗时较长。测试结果仅供参考,实际应用中应结合系统环境和业务需求评估。
755

被折叠的 条评论
为什么被折叠?



