Хэш Redis очень медленная скорость записи

Я столкнулся с очень странной проблемой: я получаю очень плохую скорость записи при использовании Redis (в идеальном мире скорость записи должна приближаться к скорости записи в ОЗУ).

Вот мой ориентир:

package redisbenchmark;
import redis.clients.jedis.Jedis;

public class RedisBenchmark {

    private static final String REDIS_KEY = "anon_id";

    private Jedis conn;

    private long writeTimeNano=0;

    private RandomString stringGenerator;

    private String[] fields;

    public RedisBenchmark(){
        conn = new Jedis("localhost");
        stringGenerator = new RandomString(32);
    }

    public void run(int nbWrites, int nbReads){     
        writeBenchmark(nbWrites);
    }

    public void writeBenchmark(int amount){
        fields = new String[amount];

        for(int i=0; i< amount; i++){
            fields[i] = stringGenerator.nextString();           
        }

        long start = System.nanoTime();
        for(int i=0; i< amount; i++){
            write(fields[i]);
        }
        writeTimeNano+=System.nanoTime()-start;

        double seconds = (double)writeTimeNano / 1000000000.0;
        System.out.println("[write]nb:"+amount+"|time:"+seconds+"|speed:"+((amount*33)/(seconds*1024*1024))+" MB/s");
    }

    public void write(String anonId){       
        conn.hsetnx(REDIS_KEY, anonId, "1");
    }


    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        RedisBenchmark benchmark = new RedisBenchmark();
        benchmark.run(100000, 200);
    }
}

RandomString — это класс, который генерирует случайную строку (аргумент — это длина строки)

И ниже пара результатов:

[запись]nb:100000|время:4,408319378|скорость:0,713905907055318 МБ/с [запись]nb:100000|время:4,447246995|скорость:0,707656949946542 МБ/с

Я попытался изменить параметры сохранения на жесткий диск в файле конфигурации, но без каких-либо улучшений.

У меня есть две идеи:
1. Это проблема с сокетом, поскольку клиент и сервер (redis) находятся на одном компьютере
2. Реализация коннектора имеет проблемы с производительностью.

ОБНОВЛЕНИЕ Результаты тестов для работы с наборами:

====== SET ======
10 000 запросов, выполненных за 0,09 секунды
50 параллельных клиентов
3 байта полезной нагрузки
keep active: 1

99,51% ‹= 1 миллисекунда
100,00% ‹= 1 миллисекунда
111111,11 запросов в секунду

Спецификация системы :
— Ubuntu 11.04
— 8 ГБ ОЗУ
— процессор Intel i5

Любое предложение будет принята с благодарностью.


person Stephan    schedule 16.05.2013    source источник
comment
Какую скорость вы получите для хеш-операций, если запустите redis-benchmark?   -  person Adam    schedule 16.05.2013
comment
@ Адам хороший вопрос, так как я забыл добавить результаты тестов, но я добавлю их сейчас, и, насколько я могу судить, результаты очень хорошие.   -  person Stephan    schedule 17.05.2013


Ответы (1)


Вам нужно немного больше подумать о том, что вы действительно оцениваете с помощью этой программы. Я могу сказать вам, что это не Redis, а способность вашей системы запускать игру в пинг-понг между двумя процессами (поскольку все ваши вызовы hsetnx синхронны).

Пожалуйста, прочтите эту страницу, прежде чем пытаться сравнить Redis, она определенно вам поможет.

Ваше предположение, что скорость Redis должна приближаться к скорости записи оперативной памяти, несколько наивно. Redis — это удаленное хранилище, и для операций O(1) большая часть накладных расходов связана с затратами на связь. Для синхронного трафика (как в вашем примере) это также связано со стоимостью планировщика ОС.

Если вы хотите применить множество команд последовательно, вам нужно использовать конвейерную обработку. Или, если вас не волнует последовательность, вы можете работать одновременно с несколькими подключениями (это режим по умолчанию для redis-benchmark). Или вы можете попробовать вместо этого отправлять асинхронные команды. Во всех случаях идея состоит в том, чтобы амортизировать стоимость обращений к серверу Redis.

Благодаря конвейерной обработке нескольких соединений с асинхронным трафиком вы получите максимальную пропускную способность, которую Redis может достичь на этом компьютере.

person Didier Spezia    schedule 17.05.2013
comment
+1 за полезную информацию. Что касается скорости ОЗУ, я только сказал, что, поскольку она работает на той же машине, узких мест в сети не может быть. Я знаю об использовании нескольких клиентов или конвейерной обработки, но решил не использовать ее, поскольку хотел смоделировать наихудший сценарий: один поток, который выполняет последовательные вызовы и считывает результат после каждого вызова. Даже в этом случае я ожидал гораздо большей скорости, чем полученная. - person Stephan; 17.05.2013
comment
Отсутствие сети не означает отсутствие затрат на связь. IPC также имеют стоимость. Вы можете попробовать redis-benchmark с параметром -c 1, чтобы ограничить параллелизм одним соединением и сравнить яблоки с яблоками. - person Didier Spezia; 17.05.2013
comment
ты прав насчет яблок :D я запустил ./redis-benchmark -c 1 -d 33 -n 100000 -t SET и он выполнился за 4,32 секунды, как я и получил. Но все же я ожидал большего ... может быть, у меня нет полной ясной картины о том, почему в этом случае это медленно - person Stephan; 17.05.2013