我有一个很大的日志文件(大约 600 MB),我试图通过蜂窝网络传输它。因为它是一个日志文件,所以它只是附加到(虽然它实际上是在一个 SQLite 数据库中,只执行了 INSERT,所以它并不那么简单,但除了最后 4k 页(或者可能是一个很少)文件每次都是相同的。重要的是只有更改(以及需要传输的任何校验和)实际发送,因为数据连接是计量的。
然而,当我通过未计量的连接(例如免费 wifi 热点)执行测试时,我没有看到观察到或报告的数据传输加速或减少。通过慢速 WiFi 连接,我看到大约 1MB/s 或更少,报告传输将需要近 20 分钟。通过快速的 WiFi 连接,我看到了统一的更快速度,但没有关于加速的报告,第二次尝试传输(现在应该更快,因为两个文件相同)现在确实显示出任何差异。
我正在使用的(经过消毒以删除敏感信息)命令是:
rsync 'ssh -p 9999' --progress LogFile michael@my.host.zzz:/home/michael/logs/LogFile
Run Code Online (Sandbox Code Playgroud)
我最后得到的输出如下所示:
LogFile
640,856,064 100% 21.25MB/s 0:00:28 (xfr$1, to-chk=0/1)
Run Code Online (Sandbox Code Playgroud)
没有提到任何类型的加速。
我怀疑问题可能是以下之一:
我排除了以下情况:
der*_*ert 28
数据库往往会保存大量元数据、组织数据等。插入不太可能是简单的附加,就像文本文件一样。测试 SQLite 表明它在 WAL 和非 WAL 模式下都是这样的。这导致 rsync 必须同步比您预期的更多的数据。您可以通过使用低--block-size
(以更多开销计算和传输校验和为代价)来减少这种开销。
更好的方法可能是将新记录转储为 SQL 转储、压缩并传输它。或者,似乎有多种 SQLite 复制解决方案,您可以使用其中之一。
roaima建议至少你可以做一个完整的 SQL 转储,使用 压缩它gzip --rsyncable
,然后 rsync 。我想值得一试,看看这是否是一个足够小的增量。
你正在尝试的应该有效。我个人会添加--partial
到您的 rsync 选项中,以防万一它以某种方式将不断增长的文件检测为部分传输。您还可以使用 获得更好的转会统计数据--stats
。
要检查的第二件事是 SQLite 是否真的只涉及几页——老实说,如果它在整个文件中写入页面,我不会感到惊讶。检查的一种快速方法是cmp -l
在两个版本上使用- 查看除最后几个之外的页面是否有更改。请记住,rsync
“页面”/块的概念与 SQLite 的不同;您可以通过 .rsync 更改 rsync --block-size
。减少它可能会有所帮助。
编辑:我用 SQLite 做了一个快速测试。即使有 32k 页,在每一页上添加一堆乱写的日志条目。详情如下。
编辑 2:在 WAL 模式下似乎更好,尽管您仍然需要大量开销,可能来自检查点。
编辑 3:每次传输添加的数据越多越好 - 我猜它可能一遍又一遍地涂抹某些块。因此,无论是向它们写入一次还是一百次,您都在传输同一组块。
顺便说一句:为了最小化传输,您可能比 rsync 做得更好。例如,自上次传输运行xz --best
(或什至gzip
)以来新记录的 SQL 转储可能会小一些。
架构:
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);
Run Code Online (Sandbox Code Playgroud)
Perl程序:
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)
?
Run Code Online (Sandbox Code Playgroud)
还有更多示例日志消息 (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) }'
Run Code Online (Sandbox Code Playgroud)