redis 消息隊列性能測試

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

測試思路

  • 開啓固定數量生產線程進行寫操作
  • 開啓固定數量的消費線程,進行阻塞消費操作
  • 分別統計固定消息的生產者的吞吐量和消費的者的吞吐量

性能測試

---------write end ------
---------開始時間--------------結束時間-------------寫入條數-----使用時間----------吞吐量-----測試運行線程數量---
-2016-12-16 17:35:42---2016-12-16 17:36:20------1000000------38------26315------4
[framework] 2016-12-16 17:36:22,863 - com.jiazq.jizq.redis.mq.RedisMqConsumerSchudler -40656 [redisMq-consumer-i] ERROR com.jiazq.jizq.redis.mq.RedisMqConsumerSchudler  - 
---------開始時間--------------結束時間-----消費消息條數-------花費時間------吞吐量------測試運行線程數量-----
-2016-12-16 17:35:42---2016-12-16 17:36:22------1000001------40------25000------4


---------開始時間--------------結束時間-------------寫入條數-----使用時間----------吞吐量-----測試運行線程數量---
-2016-12-16 17:39:09---2016-12-16 17:40:25------2000000------75------26666------4
[framework] 2016-12-16 17:40:29,547 - com.jiazq.jizq.redis.mq.RedisMqConsumerSchudler -79935 [redisMq-consumer-i] ERROR com.jiazq.jizq.redis.mq.RedisMqConsumerSchudler  - 
---------開始時間--------------結束時間-----消費消息條數-------花費時間------吞吐量------測試運行線程數量-----
-2016-12-16 17:39:09---2016-12-16 17:40:29------2000001------79------25316------4

---------write end ------
---------開始時間--------------結束時間-------------寫入條數-----使用時間----------吞吐量-----測試運行線程數量---
-2016-12-16 17:43:08---2016-12-16 17:45:03------3000000------114------26315------4
[framework] 2016-12-16 17:45:11,143 - com.jiazq.jizq.redis.mq.RedisMqConsumerSchudler -122312 [redisMq-consumer-i] ERROR com.jiazq.jizq.redis.mq.RedisMqConsumerSchudler  - 
---------開始時間--------------結束時間-----消費消息條數-------花費時間------吞吐量------測試運行線程數量-----
-2016-12-16 17:43:08---2016-12-16 17:45:11------3000001------122------24590------4

結果分析

  • 生產者性能略高於消費者
  • 生產者和消費者的吞吐量都在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);

                        //loopWait(jedis, count);
                    }




                } catch (Throwable t) {

                    logger.error("",t);

                    // 連接失敗
                    if (!jedis.isConnected()) {

                        //返回連接池裏面
                        jedis.close();
                        // 重新獲取連接
                        jedis = JedisManager.instance().getJedis();
                    }
                }

            }

        }

    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章