[unix] 네트워크에서 단일 파일에 대해 델타 전송을 사용하지 않는 이유는 무엇입니까?

나는이 살펴 보았다 질문이 질문에 ,하지만 그들은 내가보고하고 증상을 해결하지 못하는 것 같습니다.

셀룰러 네트워크를 통해 전송하려는 큰 로그 파일 (약 600MB)이 있습니다. 그것은 단지에 추가되는 로그 파일이기 때문에 그것은 단지 INSERT과 SQLite는 데이터베이스에 실제로 있지만 (이되지 않도록, 수행되는 과 간단하지만 마지막 4K 페이지를 제외하고 (또는 어쩌면 적은 수의 파일이 매번 동일합니다. 데이터 연결이 측정되므로 변경 사항 (및 체크섬을 전송해야하는 모든 항목) 만 실제로 전송하는 것이 중요합니다.

그러나 미터링되지 않은 연결 (예 : 무료 Wi-Fi 핫스팟)을 통해 테스트를 수행 할 때 속도가 향상되거나 데이터 전송이 줄어들지 않습니다. WiFi 연결 속도가 느린 경우 1MB / s 이하로 전송하는데 거의 20 분이 소요될 것이라고보고했습니다. 빠른 WiFi 연결을 통해 속도는 균일하지만 속도는보고되지 않았으며 두 번째 전송 시도 (두 파일이 동일하므로 더 빨라야 함)에 차이가 있습니다.

사용중인 (민감한 정보를 제거하기 위해 위생 처리) 명령은 다음과 같습니다.

rsync 'ssh -p 9999' --progress LogFile michael@my.host.zzz:/home/michael/logs/LogFile

마지막에 얻는 출력은 다음과 같습니다.

LogFile
    640,856,064 100%   21.25MB/s   0:00:28 (xfr$1, to-chk=0/1)

어떤 종류의 속도 향상에 대한 언급이 없습니다.

문제가 다음 중 하나 일 수 있습니다.

  • 명령 행 옵션이 없습니다. 그러나 매뉴얼 페이지를 다시 읽으면 델타 전송이 기본적으로 활성화되어있는 것으로 보입니다. 비활성화 할 수있는 옵션 만 표시됩니다.
  • 서버가 ssh 만 허용하는 방화벽 뒤에 있기 때문에 ssh (비표준 포트에서도)를 통해 rsync를 사용하고 있습니다. rsync 데몬이 실행되고 있지 않으면 델타 전송이 작동하지 않는다는 것을 명시 적으로 보지 못했습니다. “:”대신 “::”표기법을 사용하려고했지만 매뉴얼 페이지에서 “모듈”이 무엇인지 명확하지 않으며 잘못된 모듈을 지정하기 위해 명령이 거부되었습니다.

나는 다음을 배제했다.

  • 로컬 네트워크에서는 델타 전송이 수행되지 않습니다. 인터넷을 통해 전송을 시도하고 있기 때문에 배제
  • 체크섬 계산으로 인한 오버 헤드 고속 및 느린 Wi-Fi 연결 에서이 동작을 보았으며 전송 속도가 계산 범위에없는 것으로 보입니다.


답변

요약

데이터베이스는 많은 메타 데이터, 조직 데이터 등을 유지하는 경향이 있습니다. 삽입은 텍스트 파일과 같이 단순한 추가 일 가능성이 거의 없습니다. SQLite를 테스트하면 WAL 및 비 WAL 모드에서 모두 작동합니다. 이로 인해 rsync는 예상보다 훨씬 많은 데이터를 동기화해야합니다. --block-size더 많은 오버 헤드 컴퓨팅 및 체크섬 전송 비용으로 낮은 비용을 사용하여이 오버 헤드를 다소 줄일 수 있습니다 .

더 나은 방법은 새 레코드를 SQL 덤프로 덤프하고 압축하여 전송하는 것입니다. 또는 SQLite에 대한 여러 가지 복제 솔루션이있는 것으로 보이며 그 중 하나를 사용할 수 있습니다.

roaima 는 최소한 전체 SQL 덤프를 수행하고를 사용하여 압축 gzip --rsyncable한 다음 재 동기화 할 수 있다고 제안 합니다. 그것이 델타가 충분히 작은 지 테스트 할 가치가 있다고 생각합니다.

세부

당신이 시도하는 것이 작동 해야 합니다. --partial어떻게 든 증가하는 파일을 부분 전송으로 감지하는 경우를 대비하여 개인적으로 rsync 옵션에 추가하고 싶습니다 . 로 더 나은 이전 통계를 얻을 수도 있습니다 --stats.

두 번째로 확인해야 할 것은 SQLite가 실제로 몇 페이지 만 터치하는지 여부입니다. 솔직히 파일 전체에 페이지를 작성하는 경우 놀라지 않을 것입니다. 확인하는 한 가지 빠른 방법 cmp -l은 두 가지 버전 에서 사용 하는 것입니다. 마지막 몇 페이지 이외의 페이지가 변경되었는지 확인하십시오. 기억 rsync은 “페이지”의의 생각은 / 블록 SQLite는의 다릅니다; 를 통해 rsync를 변경할 수 있습니다 --block-size. 그것을 줄이는 것이 도움이 될 수 있습니다.

편집 : SQLite로 빠른 테스트를 수행했습니다. 32k 페이지에서도 모든 페이지 에 많은 로그 항목이 추가 됩니다. 자세한 내용은 아래를 참조하십시오.

편집 2 : WAL 모드에서 더 나은 것처럼 보이지만 검사 점에서 여전히 많은 오버 헤드가 발생합니다.

편집 3 : 전송마다 추가하는 데이터가 많을수록 좋습니다. 특정 블록을 반복해서 낙서하는 것 같습니다. 따라서 블록에 한 번 또는 백 번 쓴지 여부에 관계없이 동일한 블록 세트를 전송합니다.

BTW : 전송을 최소화하기 위해 아마도 rsync보다 훨씬 더 낫습니다. 예를 들어, 마지막 전송 실행 이후 xz --best(또는 심지어 gzip) 이후에 새 레코드의 SQL 덤프는 약간 더 작을 수 있습니다.

빠른 SQLite 테스트

개요:

CREATE TABLE log (id integer primary key not null, ts integer not null, app text not null, message text not null);
CREATE INDEX log_ts_idx on log(ts);
CREATE INDEX log_app_idx on log(app);

펄 프로그램 :

use 5.022;
use DBI;

my $DBH = DBI->connect('dbi:SQLite:test.db', '', '', {RaiseError => 1, AutoCommit => 0})
    or die "connect...";

my @apps = (
    '[kthreadd]',        '[ksoftirqd/0]',
     # there were 191 of these
    '[kworker/5:0H]',
);

my @messages = <DATA>;

(my $curr_time) = $DBH->selectrow_array(<<QUERY);
    SELECT COALESCE(MAX(ts),978307200) FROM log
QUERY

my $n_apps = @apps;
my $n_msgs = @messages;
say "Apps: $n_apps";
say "Messages: $n_msgs";
say 'Start time: ', scalar gmtime($curr_time), ' UTC';

my $sth = $DBH->prepare(<<QUERY);
    INSERT INTO log(ts, app, message) VALUES (?, ?, ?)
QUERY

for (my $i = 0; $i < 10_000; ++$i) {
    $sth->execute(int($curr_time), $apps[int rand $n_apps], $messages[int rand $n_msgs]);
    $curr_time += rand 0.1;
}
$DBH->commit;

__DATA__
microcode: CPU0 microcode updated early to revision 0x19, date = 2013-06-21
Linux version 4.5.0-2-amd64 (debian-kernel@lists.debian.org) (gcc version 5.3.1 20160528 (Debian 5.3.1-21) ) #1 SMP Debian 4.5.5-1 (2016-05-29)

더 많은 예제 로그 메시지가있었습니다 (2076).

변경된 페이지 확인 :

cp test.db test.db.old
perl test.pl
cmp -l test.db.old test.db | perl -n -E '/^\s*(\d+) / or die "wtf"; $bucket{int $1/32768} = 1; END { say join "\n", sort( { $a <=> $b } keys %bucket) }'


답변