потоковая передача быстро меняющихся данных между серверами

У меня есть сервер 1, который генерирует большой объем данных, например, есть файлы, которые постоянно обновляются в миллисекундах.

Я хотел бы получить эти файлы на другой сервер, используя C++ или стандартные методы Linux.

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

Тем не менее, задержка этого очень высока, и я не могу сломать сабвуфер на 1 секунду.

Может ли кто-нибудь предложить методы, которые я могу использовать для перемещения данных с меньшей задержкой?


person user788171    schedule 21.07.2011    source источник
comment
О каком порядке размеров идет речь? Кбит/с, Мбит/с, Гбит/с. Возможно ли дифференцирование, ...? Честно говоря, слишком мало спецификаций, чтобы ответить.   -  person KillianDS    schedule 21.07.2011
comment
Почему С++? какой-нибудь язык сценариев, такой как Perl или Python, был бы здесь гораздо продуктивнее.   -  person salva    schedule 22.07.2011
comment
Это в диапазоне нескольких Мбит/с и несколько тысяч файлов, которые нужно обновлять одновременно (каждый менее чем за секунду).   -  person user788171    schedule 24.07.2011


Ответы (3)


Просто идея, я не знаю, сработает ли она для вашей конкретной ситуации: Напишите две программы. Тот, который работает на сервере, на котором обновляются ваши файлы, и отслеживает изменения с помощью inotify. . Другая программа работает на втором сервере и поддерживает TCP-соединение с первым. Всякий раз, когда первая программа обнаруживает изменение, она отправляет измененную часть файла второй программе, которая может применить изменение к своей собственной копии файла.

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

person Community    schedule 21.07.2011
comment
Как в C++ можно поддерживать tcp-соединение между двумя программами и как именно вы отправляете данные по tcp? Это кажется хорошей идеей, но дьявол, вероятно, кроется в деталях. Спасибо. - person user788171; 22.07.2011
comment
Просто используйте сокеты. Вот хороший учебник для начала: linuxhowtos.org/C_C++/socket.htm - person ; 22.07.2011
comment
AFAIK, inotify сообщает вам, что какой-то файл изменился, но не говорит, что на самом деле изменилось внутри файла, поэтому его нельзя использовать отдельно для создания дельт. - person salva; 22.07.2011

В Linux вы можете использовать DRBD и кластерную файловую систему, например GFS2, для прозрачной репликации некоторых разделов между двумя серверами.

Другой вариант - использовать rsync.

person salva    schedule 22.07.2011

Сценарий Perl, который использует inotify для обнаружения изменений в файловой системе и rsync через SSH для повторной синхронизации удаленных копий:

#!/usr/bin/perl

use strict;
use warnings;

use Net::OpenSSH;
use Linux::Inotify2;
use Time::HiRes qw(sleep);

my $usage = "Usage:\n  $0 local_dir [user\@]host remote_dir\n\n";

@ARGV == 3 or die $usage;
my ($local, $host, $remote) = @ARGV;

-d $local or die $usage;

my $ssh = Net::OpenSSH->new($host);
$ssh->error and die "unable to connect to remote host: " . $ssh->error;

my $inotify = Linux::Inotify2->new;
$inotify->watch ($local, IN_MODIFY|IN_MOVED_TO);

$ssh->rsync_put({verbose => 1, glob => 1}, "$local/*", $remote);

while (1) {
    my @events = $inotify->read or die "read error: $!";
    my %changed;
    $changed{"$local/$_->{name}"} = 1 for @events;
    $ssh->rsync_put({verbose => 1}, keys %changed, $remote);
    sleep 0.1;
}

обновление: @user788171: в ответ на ваш вопрос:

Может быть, а может и нет, слишком много неизвестного:

  • сколько файлов на самом деле меняется
  • их размер
  • насколько велики изменения относительно полного размера файла
  • пропускная способность сети и задержка
  • доступная мощность ЦП с обеих сторон
  • и т.п.

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

Например, rsync — это разговорный протокол, очень чувствительный к сетевым задержкам, поэтому, если ваши файлы небольшие, scp может дать лучшие результаты. Или вы можете сохранить локальную копию последней версии, переданной локально для каждого файла, и отправлять только дельты. Если процессор является узким местом, перепишите его на C++, уберите SSH и т. д.

А если все равно такой подход окажется тупиковым, то можно еще...

  • Сделайте это на уровне ОС, используя DRDB или какой-либо другой механизм прозрачной репликации. Вы даже можете попробовать реализовать это самостоятельно с помощью FUSE.

  • Измените свое основное приложение, чтобы вести журнал изменений, который можно легко передать на другую сторону.

person salva    schedule 22.07.2011
comment
это интересное решение, но действительно ли rsync достаточно быстр, чтобы обновлять файлы менее чем за секунду? будет ли это решение жизнеспособным, если я захочу сделать это с тысячами файлов одновременно? - person user788171; 24.07.2011
comment
@user788171: ответ добавлен к сообщению - person salva; 26.07.2011