나는 이것을 본 적이 있다질문그리고이 문제, 그러나 제가 보고 있는 증상을 해결하지 못하는 것 같습니다.
셀룰러 네트워크를 통해 전송하려는 대용량 로그 파일(약 600MB)이 있습니다. 로그 파일이기 때문에 그냥 추가됩니다. (실제로는 INSERT만 수행하는 SQLite 데이터베이스에 있으므로 그렇지 않습니다.상당히그렇게 간단하지만 마지막 4k 페이지(혹은 몇 페이지)를 제외하면 파일은 매번 동일합니다. 중요한 점은 데이터 연결이 측정되므로 변경 사항(및 전송해야 하는 모든 체크섬)만 실제로 전송된다는 것입니다.
그러나 무제한 연결(예: 무료 Wi-Fi 핫스팟)을 통해 테스트를 수행했을 때 데이터 전송 속도 향상이나 감소가 관찰되거나 보고되지 않았습니다. 느린 WiFi 연결을 통해 전송 속도가 약 1MB/s 이하인 것으로 확인되었으며 전송에 거의 20분이 소요된다는 보고가 있었습니다. 빠른 WiFi 연결을 통해 균일하게 더 빠른 속도를 보았지만 가속이 보고되지 않았으며 두 번째 전송 시도(두 파일이 동일하므로 이제 더 빨라야 함)에서는 이제 어떤 차이도 나타나지 않습니다.
내가 사용하는 명령(민감한 정보를 제거하기 위해 삭제됨)은 다음과 같습니다.
rsync 'ssh -p 9999' --progress LogFile [email protected]:/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 연결과 느린 Wi-Fi 연결 모두에서 이 동작을 본 적이 있으며 전송 속도는 계산상 제한되지 않는 것 같습니다.
답변1
일반화하다
데이터베이스는 많은 메타데이터, 조직 데이터 등을 보관하는 경향이 있습니다. 삽입은 텍스트 파일과 마찬가지로 단순한 추가가 아닐 가능성이 높습니다. SQLite 테스트에서는 WAL 모드와 비WAL 모드 모두에서 이 동작을 보여줍니다. 이로 인해 rsync는 예상보다 더 많은 데이터를 동기화해야 합니다. 낮은 값을 사용하면 이 오버헤드를 약간 줄일 수 있습니다 --block-size
(체크섬을 계산하고 전송하는 데 더 많은 오버헤드가 발생함).
더 나은 접근 방식은 새 레코드를 SQL 덤프로 덤프하고 압축한 후 전송하는 것입니다. 또는 여러 SQLite 복제 솔루션이 있는 것으로 보이며 그 중 하나를 사용할 수 있습니다.
로에마gzip --rsyncable
최소한 전체 SQL 덤프를 수행하고 압축을 사용한 다음 rsync를 사용하는 것이 좋습니다 . 증분이 충분히 작은지 테스트해 볼 가치가 있다고 생각합니다.
세부 사항
당신은 무엇을 노력하고 있습니까?~해야 한다일하다. 개인적 --partial
으로 증가하는 파일을 부분 전송으로 감지하는 경우를 대비해 rsync 옵션을 추가하겠습니다 . 그렇게 하면 더 나은 전송 통계를 얻을 수도 있습니다 --stats
.
두 번째로 확인해야 할 것은 SQLite가 실제로 몇 페이지만 만지고 있는지 여부입니다. 솔직히 전체 파일에 페이지를 쓰는 경우에는 놀라지 않을 것입니다. 확인하는 빠른 방법은 두 버전 모두에서 작업하는 것입니다 cmp -l
. 마지막 몇 페이지를 제외하고 변경된 페이지가 있는지 확인하세요. rsync
"페이지"/청크의 개념은 SQLite의 개념과 다르다는 점을 명심하세요 . rsync를 통해 이를 변경할 수 있습니다 --block-size
. 줄이는 것이 도움이 될 수 있습니다.
편집하다:SQLite를 사용하여 빠른 테스트를 수행했습니다. 32,000페이지라도 휘갈겨 쓴 로그 항목을 잔뜩 추가하세요모든페이지. 자세한 내용은 다음과 같습니다.
편집 2: 여전히 많은 오버헤드가 필요하지만(아마도 체크포인팅으로 인해) WAL 모드가 더 나은 것 같습니다.
편집 3: 전송당 더 많은 데이터를 추가할수록 더 좋습니다. 특정 덩어리를 계속해서 뒤섞을 수 있다고 생각합니다. 따라서 한 번 쓰든 백 번 쓰든 동일한 청크를 전송합니다.
그런데: 전송을 최소화하려면 rsync보다 더 나은 결과를 얻을 수 있습니다. 예를 들어 마지막 전송 실행 이후 새 레코드의 SQL 덤프 xz --best
(심지어 gzip
)는 더 작을 수 있습니다.
빠른 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 ([email protected]) (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) }'