Redis: количество каналов, ухудшающих задержку. Как предотвратить деградацию?
pub.py
import redis
import datetime
import time
import json
import sys
import threading
import gevent
from gevent import monkey
monkey.patch_all()
def main(chan):
redis_host = '10.235.13.29'
r = redis.client.StrictRedis(host=redis_host, port=6379)
while True:
def getpkg():
package = {'time': time.time(),
'signature' : 'content'
}
return package
#test 2: complex data
now = json.dumps(getpkg())
# send it
r.publish(chan, now)
print 'Sending {0}'.format(now)
print 'data type is %s' % type(now)
time.sleep(1)
def zerg_rush(n):
for x in range(n):
t = threading.Thread(target=main, args=(x,))
t.setDaemon(True)
t.start()
if __name__ == '__main__':
num_of_chan = 10
zerg_rush(num_of_chan)
cnt = 0
stop_cnt = 21
while True:
print 'Waiting'
cnt += 1
if cnt == stop_cnt:
sys.exit(0)
time.sleep(30)
sub.py
import redis
import threading
import time
import json
import gevent
from gevent import monkey
monkey.patch_all()
def callback(ind):
redis_host = '10.235.13.29'
r = redis.client.StrictRedis(host=redis_host, port=6379)
sub = r.pubsub()
sub.subscribe(str(ind))
start = False
avg = 0
tot = 0
sum = 0
while True:
for m in sub.listen():
if not start:
start = True
continue
got_time = time.time()
decoded = json.loads(m['data'])
sent_time = float(decoded['time'])
dur = got_time - sent_time
tot += 1
sum += dur
avg = sum / tot
print decoded #'Recieved: {0}'.format(m['data'])
file_name = 'logs/sub_%s' % ind
f = open(file_name, 'a')
f.write('processing no. %s' % tot)
f.write('it took %s' % dur)
f.write('current avg: %s\n' % avg)
f.close()
def zerg_rush(n):
for x in range(n):
t = threading.Thread(target=callback, args=(x,))
t.setDaemon(True)
t.start()
def main():
num_of_chan = 10
zerg_rush(num_of_chan)
while True:
print 'Waiting'
time.sleep(30)
if __name__ == '__main__':
main()
Я тестирую redis pubsub, чтобы заменить использование rsh для связи с удаленными устройствами.
Одной из вещей, которые я протестировал, было количество каналов, влияющих на задержку publish и pubsub.listen().
Тест: один издатель и один подписчик на канал (издатель публикуется каждую секунду). Увеличил количество каналов и наблюдал задержку (продолжительность с момента публикации сообщения издателем до момента, когда подписчик получил сообщение через прослушивание)
число чан -------------- средняя задержка в секундах
10:----------------------------------0,004453
50: ---------------------------------- 0,005246
100: --------------------------------- 0,0155
200: --------------------------------- 0,0221
300: --------------------------------- 0,0621
Примечание: проверено на 2 CPU + 4GB RAM + 1 NIC RHEL6.4 VM.
Что я могу сделать, чтобы поддерживать низкую задержку при большом количестве каналов?
Redis является однопоточным, поэтому увеличение числа процессоров не поможет. может быть больше оперативной памяти? если так, сколько еще?
Что-нибудь, что я могу сделать в коде или узкое место в самом Redis?
Может быть, ограничение связано с тем, что мои тестовые коды написаны с использованием потоков?
РЕДАКТИРОВАТЬ: Redis Cluster против ZeroMQ в Pub/Sub, для горизонтально масштабируемых распределенных систем
Принятый ответ говорит: "Вы хотите минимизировать задержку, я думаю. Количество каналов не имеет значения. Ключевыми факторами являются количество издателей и количество подписчиков, размер сообщения, количество сообщений в секунду на издателя, количество сообщений, полученных каждым из них. подписчик, примерно. ZeroMQ может отправлять несколько миллионов небольших сообщений в секунду от одного узла к другому; узким местом будет сеть задолго до того, как это станет программным обеспечением. Поэтому в большинстве высокопроизводительных архитектур pubsub используется нечто вроде многоадресной рассылки PGM, которую поддерживает ZeroMQ ".
Из моих испытаний я не знаю, правда ли это. (Утверждение о том, что количество каналов не имеет значения)
Например, я сделал тестирование.
1) Один канал. 100 издателей публикуют на канале с 1 подписчиком прослушивания. Издатель публикует одну секунду за раз. задержка составила 0,00965 секунд
2) То же тестирование, кроме 1000 издателей. задержка составила 0,00808 секунды
Сейчас во время тестирования моего канала:
300 каналов с 1 пабом - 1 саб с результатом 0,0621, и это только 600 соединений, что меньше, чем при тестировании, но значительно медленнее с задержкой