一.测试背景与目标
了解Redis和memcached在高并发条件下的响应时间、吞吐量情况,以及对于服务器的压力情况(包括CPU、IO、网络);考察目前的memcached存储timeline的方式的在高并发条件下的响应时间、吞吐量、负载情况,以及使用redis存储timeline的优势
二.测试环境
1.服务器
buzz090,刀片服务器
2.操作系统
CentOS release 5.5系统,内核版本:Linux version 2.6.18-194.el5
3.硬件
Intel(R) Xeon(R) CPU E5640 @ 2.67GHz 16CPU;48G内存;千兆网卡
4.软件:
uRedis版本:2.6.0-rc5(2.5.11),主要为了以后测试lua script功能,部署三个节点,每个节点开2G内存,共6G。开启AOF,策略every second;关闭RDB;开启lru,策略:allkeys-lru
uMemcached版本:1.4.5. 部署三个节点,每个节点开2G内存,共6G
5.客户端
buzz097,硬件环境、操作系统和buzz090一致。
客户端和服务器使用内网互联。
三.测试工具
1.Redis客户端
jedis,版本号2.1.0. 池设置使用默认,未调优。超时时间为5s
2.Memcached客户端
xmemcached,版本号1.3.5,使用一致性hash,使用BinaryCommandFactory,使用failure mode,不过未配置备机(-_-).超时时间为5s
3.压力测试工具
海波写的压力测试框架(strike)
四.测试方法
1.测试方法
分别以100、200、500、1000个并发线程压力测试redis、memcached的方法,运行时间为20-60分钟不等,每轮压力测试取样3000次,压力测试中观察如下参数:
u单次操作的响应时间
u3000次操作的响应时间(吞吐量)
uCPU情况
u网络rx、tx
uIO
2.压力测试的方法
Redis:set、zadd、evalSha
Memcached:set、(gets、cas的操作组合)
3.一些说明
对于读操作做了少量测试,发现性能与set操作类似,就不做单独的测试报告了。读操作重要的一点是:在redis中,对于一个很大的sorted set,使用zrange时一定要指定范围,否则将得到大量的错误
五.测试用例:
1.Redis的set方法和memcached的set方法比较
u测试方法:使用java产生的伪随机数不断的对redis进行set操作,对memcached做set操作。
u测试结果:
Redis:
100个线程下,单次操作时间为0-1ms;运行3000次的时间为80-95ms,即吞吐量为32000-38000;CPU idle 96%;IO wr_sec/s为4000;网络rxKB/s:3000,txKb/s为1500-2000
200个线程下,单次操作时间0-1ms;运行3000次的时间为87-105ms,即吞吐量为28500-34500;CPU idle 96%;IO wr_sec/s为4000;网络rxKB/s:3000,txKb/s为1500-2000
500个线程下,单次操作时间0-1ms;运行3000次的时间为95-110ms,即吞吐量为27000-31500;CPU idle 96%;IO wr_sec/s为4000;网络rxKB/s:3000,txKb/s为1500-2000
1000个线程下,单次操作时间0-1ms;运行3000次的时间为97-120ms,即吞吐量为25000-30000;CPU idle 96%;IO wr_sec/s为4000;网络rxKB/s:3000,txKb/s为1500-2000
Memcached:
100、200、500个线程下,基本相差不大:单次操作时间;运行3000次的时间为65-85ms,即吞吐量为35000-46000;CPU idle 97%;IO wr_sec/s为260-350;网络rxKB/s:3000,txKb/s为3000
u小结
Memcached在小数据的写入方面性能要优于redis的,不仅吞吐量大,而且在服务器的负载、IO方面都有明显的优势。
Redis的关闭AOF后,性能大概上升了5%-10%,值得使用!
Redis在lru的时候感觉不到性能上的损耗
2.Redis的zadd方法和memcached的gets cas方法组合的比较:
u背景:目前微博的timeline使用memcached的gets cas组合的方式,实现乐观锁,保证timeline的一致性。
u测试方法:为redis构建37个sorted set,为memcached构建3700个key,并发的写入。其中redis使用zadd方法;memcached比较复杂,模拟当前微博系统中timeline的写入方式:从memcached中gets,将结果数组做二分查找,插入新的timeline,在java虚拟机中做数组的移动、cas回memcached中。
u测试结果
Redis:
100个线程下,单次操作时间为0-1ms;运行3000次的时间为80-95ms,即吞吐量为32000-38000;CPU idle 96%;IO wr_sec/s为5000;网络rxKB/s:5000,txKb/s为2500
200个线程下,单次操作时间0-1ms;运行3000次的时间为87-105ms,即吞吐量为28500-34500;CPU idle 96%;IO wr_sec/s为5000;网络rxKB/s:5000,txKb/s为2500
500个线程下,单次操作时间0-1ms;运行3000次的时间为95-110ms,即吞吐量为27000-31500;CPU idle 96%;IO wr_sec/s为5500;网络rxKB/s:5000-6000,txKb/s为2500
1000个线程下,单次操作时间0-1ms;运行3000次的时间为97-120ms,即吞吐量为25000-30000;CPU idle 96%;IO wr_sec/s为6000;网络rxKB/s:6000,txKb/s为2500
Memcached:
100个线程下:开始时单次写入时间以及3000次的写入时间均略优于redis,但是随着时间推移,一分钟后,3000次响应时间从80ms上升至250ms,五分钟后上升至400ms,十分钟后上升至600ms,二十分钟后接近800ms。单次响应时间也有类似的增长。
同时,网络rxKB/s:100000,txKb/s为100000
u小结
Redis的zadd方法在响应时间和吞吐量上与set方法基本无区别
当存储的数组很大时,memcached在网络性能、响应时间和吞吐量上均有较大程度的退步,而redis则无明显变化
对于timeline这样的数组的存储,redis更加适合!
3.Redis的zadd方法和Redis的lua script方法的比较
u背景:微博中的timeline分为两类:固定长度,长度无限增长。对应于redis,长度无限增长对应于zadd方法;
固定长度可以是用lua script脚本实现,具体的脚本为:
脚本中执行三次redis操作(zadd、zcard和zremrangebyrank),一次赋值、一次比较操作
Script在第一次时load到redis中,而后使用evalSha进行调用
u测试方法:分别构建37个sorted set,不断的用这两个方法、使用不同的线程数来压力测试
u测试结果:
Zadd(见上)
Lua script:
100个线程下:单次写入时间为2-5ms,3000次响应时间为105-115ms,即吞吐量为26000-28500;CPU idle 80%-90%;IO wr_sec/s为15000-22000;网络rxKB/s:5000-6000,txKb/s为2500
200个线程下:单次写入时间为7-9ms,3000次响应时间为112-120ms,即吞吐量为25000-27000;CPU idle 80%-90%;IO wr_sec/s为15000-22000;网络rxKB/s:5000-6000,txKb/s为2500
500个线程下:单次写入时间为12-21ms,3000次响应时间为125-135ms,即吞吐量为22000-24000;CPU idle 80%-90%;IO wr_sec/s为15000-22000;网络rxKB/s:5000-6000,txKb/s为2500
1000个线程下:单次写入时间为30-40ms,3000次响应时间为145-155ms,即吞吐量为19000-20500;CPU idle 80%-90%;IO wr_sec/s为15000-22000;网络rxKB/s:5000-6000,txKb/s为2500
如果每一次重新load script到服务器中,500个线程下:3000次响应时间为180-220ms,即吞吐量为13600-16600;CPU idle 80%-90%;IO wr_sec/s为15000-22000;网络rxKB/s:10000-12000,txKb/s为5000
u小结
以上lua脚本的性能大概是zadd的70%-80%,但是在可接受的范围内,在生产环境可以使用。负载大概是zadd的1.5-2倍,网络流量相差不大,IO是zadd的3倍(可能是开启了AOF,执行了三次操作?)
Lua一定要只load一次,然后循环使用,否则会有很大的性能缺失
Lua script所在的2.6.0-rc5版虽然不是stable版,官方网站也提到要在生产环境谨慎使用,但是测试下来没有发现bug
六.总结
1.Memcached在简单数据的写入上是有优势的,无论在响应时间、吞吐量、服务器的负载、IO、网络流量上都要优于redis
2.对于Timeline数组这样的数据,redis先天的类型丰富的优势可以极大的降低响应时间、提高吞吐量、提升服务器的性能指标。
3.Redis的zadd和set方法性能相差不大
4.Lua script可以实现在服务器端原子的执行多个操作的功能,性能大约是zadd的70-80%(和脚本的复杂程度有关),但是肯定比将脚本拆开单次的请求redis要好
5.AOF的开启会带来很小的性能损失,值得尝试
6.Redis在执行lru的时候,性能损失基本可以忽略