
无意中发现阿里云开发社区的训练营活动,其中有一个7天玩转Redis、tair训练营计划,里面可以免费领取三个月的试用礼包,因为是参营任务,不领取都不行的那种,领取之后放着也是放着,不如跑跑数据看看Redis和Tair的性能有什么区别,简单的压力测试下,本次测试并不精确,也不具有太多参考意义,真的就是为了测试而测试。
活动地址链接见最下面的
什么是Tair
这里有具体介绍Tair的视频,里面详细介绍了阿里云Redis和自建Redis的对比分析
https://edu.aliyun.com/course/3114106/lesson/19637
测试工作
本次没有使用Redis自带的Redis Benchmark工具,想着为了测试而测试,就为了测试而开发吧。
一:准备工作
- 领取Redis与Tair三个月免费额度
- 编写压力测试代码
- 准备测试数据。
二:测试方案设计
- 批量插入数据查看总体时延,与不同数据量下时延曲线表,记录总体耗时
- 批量数据查询,记录查询QPS,内存情况,网络流量等
- 将数据库内存空间打满后,查看相同淘汰策略下内容优化情况
三:进行压力测试
- 先进行功能测试,校验系统功能在高负载下是否正常。
- 加大并发用户数或请求流量,模拟峰值压力情况。
- 观察记录关键指标,分析系统瓶颈。
四:机器指标
为了去除本地机器、网络带来的干扰,这次的代码都会运行在ECS服务器中,但自己的ECS服务器都不是杭州区的,还是要通过外网域名的形式连接Redis、Tair,不过数据传输速率也是可靠的。
Redis | Tair | ECS服务器1 | ECS服务器1 | |
---|---|---|---|---|
规格 | 2 GB 增强版 (vCPU shared) | 2 GB 增强版 (vCPU shared) | 4C8G | 4C8G |
最大连接数 | 10,000 | 30,000 | ||
最大带宽 | 96 MB/s | 96 MB/s | ||
参考QPS | 100,000 | 300,000 | ||
副本数 | 2副本 | 2副本 | ||
分片数量 | 1 | 1 | ||
Redis版本 | Redis 5.0 | 版本兼容性:Redis 6.0 | ||
存储空间 | 10G | 10G | ||
架构类型 | 非集群 | 非集群 | ||
maxmemory-policy | volatile-lru (按照LRU算法逐出原有数据,但仅逐出设置了过期时间的数据) | volatile-lru (按照LRU算法逐出原有数据,但仅逐出设置了过期时间的数据) |
五:运行代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
package org.rain; import redis.clients.jedis.*; import java.io.BufferedReader; import java.io.File; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; public class Main { public static void readTxtFile(String filePath, JedisPool pool) { try { File file = new File(filePath); if (file.isFile() && file.exists()) { InputStreamReader isr = new InputStreamReader(Files.newInputStream(file.toPath()), StandardCharsets.UTF_8); BufferedReader br = new BufferedReader(isr); String lineTxt = null; AtomicInteger i = new AtomicInteger(); ExecutorService executorService = new ThreadPoolExecutor(50, 50, 100L, TimeUnit.MILLISECONDS, new SynchronousQueue<Runnable>(), new ThreadPoolExecutor.CallerRunsPolicy()); while ((lineTxt = br.readLine()) != null) { String[] textArr = lineTxt.split("\t"); if (textArr.length <= 6) { continue; } executorService.submit(() -> { try (Jedis jedis = pool.getResource()) { jedis.setex(textArr[0] + "-" + i.getAndIncrement(), 14400, textArr[6]); // System.out.println("已处理第" + i); } }); executorService.submit(() -> { try (Jedis jedis = pool.getResource()) { jedis.setex(textArr[1] + "-" + i.getAndIncrement(), 14400, textArr[6]); // System.out.println("已处理第" + i); } }); } System.out.println("处理完毕,共处理:" + i); executorService.shutdown(); br.close(); } else { System.out.println("文件不存在!"); } } catch (Exception e) { System.out.println("文件读取错误!" + e); } } public static void main(String[] args) { JedisPoolConfig config = new JedisPoolConfig(); config.setMaxIdle(200); config.setMaxTotal(300); config.setTestOnBorrow(false); config.setTestOnReturn(false); String redisHost = "r-.redis.rds.aliyuncs.com"; String redisUser = "r-"; String redisPassword = ""; String tairHost = "r-.redis.rds.aliyuncs.com"; String tairUser = "r-"; String tairPassword = ""; JedisPool pool; if ("redis".equals(args[0])) { System.out.println("redis"); pool = new JedisPool(config, redisHost, 6379, redisUser, redisPassword); } else { System.out.println("tair"); pool = new JedisPool(config, tairHost, 6379, tairUser, tairPassword); } String filePath = "local".equals(args[1]) ? "/Users/Downloads/weibo_train_data.txt" : "/home/weibo_train_data.txt"; System.out.println(filePath); readTxtFile(filePath, pool); } } |
六:模拟数据
1229619条微博用户发帖数据
写入性能截图
Redis
Tair
服务器负载
从图里看,在没有调整任何参数的情况下,插入250w条数据,Redis和Tair基本没有太大的区别,只是Tair的平均时延有些高,两者的QPS都能达到1000,还没有跑满官方的参考值。
读取测试截图
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
public static void getTxtFile(String filePath, JedisPool pool) { try { File file = new File(filePath); if (file.isFile() && file.exists()) { InputStreamReader isr = new InputStreamReader(Files.newInputStream(file.toPath()), StandardCharsets.UTF_8); BufferedReader br = new BufferedReader(isr); String lineTxt = null; AtomicInteger i = new AtomicInteger(); ExecutorService executorService = new ThreadPoolExecutor(50, 50, 100L, TimeUnit.MILLISECONDS, new SynchronousQueue<Runnable>(), new ThreadPoolExecutor.CallerRunsPolicy()); while ((lineTxt = br.readLine()) != null) { String[] textArr = lineTxt.split("\t"); if (textArr.length <= 6) { continue; } executorService.submit(() -> { try (Jedis jedis = pool.getResource()) { System.out.println(jedis.get(textArr[0] + "-" + i.getAndIncrement())); } }); executorService.submit(() -> { try (Jedis jedis = pool.getResource()) { System.out.println(jedis.get(textArr[1] + "-" + i.getAndIncrement())); } }); } System.out.println("处理完毕,共处理:" + i); executorService.shutdown(); br.close(); } else { System.out.println("文件不存在!"); } } catch (Exception e) { System.out.println("文件读取错误!" + e); } } |
Redis
Tair
总结
通过监控报表的分析,主要的差距还是在平均时延上,在并发50情况下,QPS达到1000左右时,redis的平均时延要比Tair低很多,写入和读取时延都有所差距。其他的两者完全相似。