Redis — що швидше, UNIX-сокет або TCP? Що стабільніше? + pconnect

image

Ми в PushAll обробляємо кілька тисяч запитів в секунду для отримання статистики доставки і відкриття сповіщень для передачі контенту сповіщень. Звичайна БД начебто MySQL не справляється з таким потоком запитів і не може так швидко відповідати.

Намагаючись все більше операцій перенести на швидкі NoSQL сховища начебто Redis, ми хочемо знати як ефективніше його використовувати і не буде у нас проблем з великою кількістю з'єднань.
Також для роботи ми використовуємо форки PHP і нам було цікаво, а як поведе себе Redis, якщо ми будемо робити кілька тисяч з'єднань одночасно в декількох потоках. Ми вирішили поділитися з співтовариством нашими тестами.

Залізо
Ми тестуємо на одному з VPS PushAll:

CPU: Intel Xeon E5-1650v2 3.5 Ghz — 2 ядра.
RAM: 3 Gb DDR3 1866Mhz

PHP7.
Redis 3.0.7

Умови тестування
Ми написали багатопотокового бота PHP, що:

  • Робить форки в циклі — 100 форков без будь-яких затримок
  • Кожен форк у своєму циклі, 1000 разів створює з'єднання з Redis і виробляє інкремент
  • Батьківський процес чекає 3 секунди і бере значення, якщо не чекати — Redis поверне не повне значення инкеремента


Також ми протестували варіант з 1000 форками і як будуть відрізнятися результати при використанні UNIX-сокету і TCP.

100 форков, 1000 з'єднань в кожному, TCP

# time php benchmark.php 
End:100000

real 0m8.666s
user 0m0.063s
sys 0m0.073s


100 форков, 1000 з'єднань в кожному, UNIX-сокет

# time php benchmark.php 
End:100000

real 0m6.021s
user 0m0.023s
sys 0m0.067s


TCP-сокет в середньому на 30% повільніше. (нагадаю, тут випробовується більше не продуктивність роботи самого Redis, а те, як він обробляє з'єднання)

1000 форков, 1000 з'єднань в кожному, TCP+UNIX

Підвищуємо ставки

TCP:
# time php benchmark.php 
End:903505

real 1m7.659s
user 0m0.073s
sys 0m0.753s

За 3 секунди Redis не встиг їх у себе до кінця обробити — це одна з деталей, яку треба враховувати. Якщо занадто швидко зчитувати значення, можна зловити момент, коли вони ще старі.

Що найцікавіше, при проведенні того ж самого тесту, але для unix-сокету, ми отримуємо помилки:
Fatal error: Uncaught RedisException: Redis server went away in ....

Тобто, unix-сокет не дивлячись на те, що він швидше, може обробляти декілька меншу кількість запитів. Або як варіант — можливо, що із за того що він такий швидкий не справляється вже сам сервер Redis'а.

Ми проводили подібні тести і для php-fpm — там також TCP-сокет давав менше помилок зі зв'язкою з NGINX ніж UNIX-сокет. Різниця в швидкості була там незначна.

Прикладаю скрипт:
<?php
declare(ticks = 1);
for($i=0; $i < 1000; $i++){
$pid = pcntl_fork();
if ($pid == -1) {
die('could not fork');
} else if ($pid) {
//parent
} else {
//child
for ($a=0; $a < 1000; $a++) { 
$redis = new Redis();
//$redis->connect('127.0.0.1:6379');
$redis->connect('/run/redis/redis.sock');
$redis->incr('pushall:benchmark');
$redis->close();
}
exit;

}
}
pcntl_wait($status); //wait
sleep(3);
$redis = new Redis();
$redis->connect('/run/redis/redis.sock');
echo 'End:'.$redis->get('pushall:benchmark')."\r\n";
$redis->setTimeout('pushall:benchmark', 1);
$redis->close();


UPD pconnect
Виявляється pconnect працює в форках (дивно)

Взяв випадок 100 процесів TCP:
pconnect
# time php benchmark.php 
End:100000

real 0m4.679s
user 0m0.023s
sys 0m0.080s


connect
# time php benchmark.php 
End:100000

real 0m9.100s
user 0m0.037s
sys 0m0.103s


Для порівняння UNIX-сокет на 100 форках:
pconnect
# time php benchmark.php 
End:100000

real 0m4.393s
user 0m0.023s
sys 0m0.073s


connect
# time php benchmark.php 
End:100000

real 0m6.002s
user 0m0.027s
sys 0m0.057s


Причому, що цікаво, при використанні pconnect — різниця між TCP і UNIX сокетом не така вже й велика 5-10%. При цьому навіть зробивши все, що мені пропонували в коментарях — мені не вдалося змусити працювати unix сокети при 1000 форках.

UPD 2 Pconnect + 1000 форков

UNIX Socket
pconnect
# time php benchmark.php 
End:1000000

real 0m35.445s
user 0m0.050s
sys 0m0.637s

connect — падає в Fatal error: Uncaught RedisException: Redis server went away in…

TCP
pconnect
# time php benchmark.php 
End:989596

real 0m43.711s
user 0m0.050s
sys 0m0.623s


# time php benchmark.php 
End:903505

real 1m7.659s
user 0m0.073s
sys 0m0.753s

Різниця в 20%.

PS. Хабр, а чому хаб MongoDB і MySQL є, а Redis немає?

Який метод ви використовуєте, чи використовували б?

/>
/>


<input type=«radio» id=«vv72280»
class=«radio js-field-data»
name=«variant[]»
value=«72280» />
TCP (т. к. він стабільніше, чи ні? опишіть в коментарі)
<input type=«radio» id=«vv72282»
class=«radio js-field-data»
name=«variant[]»
value=«72282» />
UNIX socket (т. к. він швидше)

Проголосувало 142 людини. Утримався 101 людина.


Тільки зареєстровані користувачі можуть брати участь в опитуванні. Увійдіть, будь ласка.


Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.