redis 消息队列
redis 阻塞list
lpush key value1 value2 ..
brpop key 0
测试环境
- ubuntu
- 机器双核4G内存普通机
- 外网流量4M
- redis版本: 3.2.6
- redis 和测试服务程序在一台服务器上
- 注释了bind:127.0.0.1,
- maxmemory 3gb
- 生产消费字符串大小:672byte
测试思路
- 开启固定数量生产线程进行写操作
- 开启固定数量的消费线程,进行阻塞消费操作
- 分别统计固定消息的生产者的吞吐量和消费的者的吞吐量
性能测试
--------- ------
-----------------------------------------------------------
--- ----- ------------------------
[] -- , - ..... - [--] ..... -
----------------------------------------------------
--- ----- ------------------------
-----------------------------------------------------------
--- ----- ------------------------
[] -- , - ..... - [--] ..... -
----------------------------------------------------
--- ----- ------------------------
--------- ------
-----------------------------------------------------------
--- ----- ------------------------
[] -- , - ..... - [--] ..... -
----------------------------------------------------
--- ----- ------------------------
结果分析
- 生产者性能略高于消费者
- 生产者和消费者的吞吐量都在2.5W以上
- 高配置的计算机redis性能会更高
- 适合小型系统消息系统
部分代码
消费者
package com.jiazq.jizq.redis.mq;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.log4j.Logger;
import redis.clients.jedis.Jedis;
public class RedisMqConsumerSchudler {
private static Logger logger = Logger.getLogger(RedisMqConsumerSchudler.class);
int threadNumber;
long startTime = 0;
volatile boolean runState = true;
AtomicLong count = new AtomicLong(0);
Thread[] workers = null;
public RedisMqConsumerSchudler (int threadNumber) {
this.threadNumber = threadNumber;
workers = new Thread[threadNumber];
for (int i = 0; i < threadNumber; i++) {
workers[i] = new Thread(new ReadisConsumeTask(JedisManager.instance().getJedis()));
workers[i].setDaemon(true);
workers[i].setName("redisMq-consumer-" + "i");
}
}
/**
* 启动工作线程
*/
public void start() {
for (int i = 0; i < threadNumber; i++) {
workers[i].start();
}
startTime = System.currentTimeMillis();
}
class ReadisConsumeTask implements Runnable {
private Jedis jedis = null;
ReadisConsumeTask(Jedis jedis) {
this.jedis = jedis;
}
@Override
public void run() {
while (runState) {
try {
List<String> strs = jedis.brpop(0,ConfigManager.redis_queue);
if (null != strs && strs.size() == 2) {
count.addAndGet(1);
}
if (count.get() == ConfigManager.redis_write_count) {
StringBuilder sb = new StringBuilder();
SimpleDateFormat format = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
long useTime = (new Date().getTime()- startTime)/1000;
long throughput = count.get() / useTime;
sb.append("\n---------开始时间--------------结束时间-----消费消息条数-------花费时间------吞吐量------测试运行线程数量-----\n");
sb.append("-");
sb.append(format.format(new Date(startTime)));
sb.append("---");
sb.append(format.format(new Date()));
sb.append("------");
sb.append(count.get());
sb.append("------");
sb.append(useTime);
sb.append("------");
sb.append(throughput);
sb.append("------");
sb.append(threadNumber);
logger.error(sb.toString());
runState = false;
}
} catch (Throwable t) {
logger.error("",t);
if (!jedis.isConnected()) {
jedis.close();
jedis = JedisManager.instance().getJedis();
}
}
}
}
}
}
生产者
package com.jiazq.jizq.redis.mq;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.log4j.Logger;
import redis.clients.jedis.Jedis;
public class RedisMqProduerSchudler {
private static Logger logger = Logger.getLogger(RedisMqConsumerSchudler.class);
int threadNumber;
AtomicLong writeCount = new AtomicLong(ConfigManager.redis_write_count);
long startTime = 0;
volatile boolean runState = true;
Thread[] workers = null;
RedisMqProduerSchudler (int threadNumber) {
this.threadNumber = threadNumber;
workers = new Thread[threadNumber];
for (int i = 0; i < threadNumber; i++) {
workers[i] = new Thread(new RedisProducerTask(JedisManager.instance().getJedis()));
workers[i].setDaemon(true);
workers[i].setName("redisMq-consumer-" + "i");
}
}
/**
* 启动工作线程
* @throws InterruptedException
*/
public void start() throws InterruptedException {
for (int i = 0; i < threadNumber; i++) {
workers[i].start();
}
startTime = System.currentTimeMillis();
}
private static void loopWait(Jedis jedis, long count) throws InterruptedException {
if (count > ConfigManager.redis_write_count) {
Thread.sleep(200);
loopWait(jedis, jedis.llen(ConfigManager.redis_queue));
}
}
class RedisProducerTask implements Runnable {
private Jedis jedis;
public RedisProducerTask (Jedis jedis) {
this.jedis = jedis;
}
@Override
public void run() {
while (runState) {
try {
long number = writeCount.decrementAndGet();
if (runState & number == 0) {
runState = false;
StringBuilder sb = new StringBuilder();
SimpleDateFormat format = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
long useTime = ((new Date().getTime() - startTime)/1000);
long throughput =( ConfigManager.redis_write_count/useTime);
sb.append("\n---------write end ------\n");
sb.append("---------开始时间--------------结束时间-------------写入条数-----使用时间----------吞吐量-----测试运行线程数量---\n");
sb.append("-");
sb.append(format.format(new Date(startTime)));
sb.append("---");
sb.append(format.format(new Date()));
sb.append("------");
sb.append(ConfigManager.redis_write_count);
sb.append("------");
sb.append(useTime);
sb.append("------");
sb.append(throughput);
sb.append("------");
sb.append(threadNumber);
logger.error(sb.toString());
break;
} else {
long count = jedis.lpush(ConfigManager.redis_queue,
ConfigManager.test_string_value);
}
} catch (Throwable t) {
logger.error("",t);
if (!jedis.isConnected()) {
jedis.close();
jedis = JedisManager.instance().getJedis();
}
}
}
}
}
}