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.

  1. Что я могу сделать, чтобы поддерживать низкую задержку при большом количестве каналов?

  2. Redis является однопоточным, поэтому увеличение числа процессоров не поможет. может быть больше оперативной памяти? если так, сколько еще?

  3. Что-нибудь, что я могу сделать в коде или узкое место в самом Redis?

  4. Может быть, ограничение связано с тем, что мои тестовые коды написаны с использованием потоков?

РЕДАКТИРОВАТЬ: Redis Cluster против ZeroMQ в Pub/Sub, для горизонтально масштабируемых распределенных систем

Принятый ответ говорит: "Вы хотите минимизировать задержку, я думаю. Количество каналов не имеет значения. Ключевыми факторами являются количество издателей и количество подписчиков, размер сообщения, количество сообщений в секунду на издателя, количество сообщений, полученных каждым из них. подписчик, примерно. ZeroMQ может отправлять несколько миллионов небольших сообщений в секунду от одного узла к другому; узким местом будет сеть задолго до того, как это станет программным обеспечением. Поэтому в большинстве высокопроизводительных архитектур pubsub используется нечто вроде многоадресной рассылки PGM, которую поддерживает ZeroMQ ".

Из моих испытаний я не знаю, правда ли это. (Утверждение о том, что количество каналов не имеет значения)
Например, я сделал тестирование.

1) Один канал. 100 издателей публикуют на канале с 1 подписчиком прослушивания. Издатель публикует одну секунду за раз. задержка составила 0,00965 секунд
2) То же тестирование, кроме 1000 издателей. задержка составила 0,00808 секунды

Сейчас во время тестирования моего канала:
300 каналов с 1 пабом - 1 саб с результатом 0,0621, и это только 600 соединений, что меньше, чем при тестировании, но значительно медленнее с задержкой

0 ответов

Другие вопросы по тегам