転送量に制限をかけてバックアップをとりたい

1. 転送量多いとISPから怒られちゃうよ!

現在、インターネットを通じてファイルのバックアップを行っている。夜中などのトラフィックが比較的すいている時間帯を選んでバックアップを行っている。

バックアップの内容はいろいろなもので、そしてそこそこ大きい。バックアップするデータ量は日によってまちまち。で、このバックアップデータが結構でかいので、バックアップにちょっと頭を悩ませている。というのも、利用しているISPが一日の転送量に制限をかけているからだ。

制限といっても一定量に達したら自動的に帯域を絞る、というものではなく、なんと警告メールがくる。あなた帯域使いすぎですよ、って。正直怖いッス。

で、なにかよいバックアップ方法がないだろうかと考えてみた。

まず、バックアップの特性について考える。

  • バックアップデータは大きい。結構大きい。数GB単位。
  • ファイルは分割されている。一つのファイルはおおよそ数MB ~ 1GB。
  • 転送量は一日ごとに上限値が決まっている。そしてそれはユーザが意識して制限量以下に抑える必要がある。
  • 転送量制限が一日ごとなので一日ごとにバックアップをとりたい
  • バックアップしたいデータ、例えば1日目に1日目の増分の50%、二日目には一日目の増分の残り50%と二日目の増分100%、のように、遅れてバックアップを取っても良い。ただし増分が一日の転送量を超えてしまうと終わりなきキューになるのでダメだけれどね。

上記の条件の内、とくに一日目、二日目という風にバックアップを分けてもよい、という条件があるので、コレを利用したrsyncを使ったバックアップ方法を考えてみた。

2. rsyncは転送量制限できない!

もう、さっくりと、rsyncで転送量のしていすればイイジャナーイ、って思った。で、manを見たけどそんな項目無し。残念。

代わりにbwlimitという転送幅(帯域)を指定する項目がある。なのでコレを利用して転送量制限をやってみようと思う。

どのようにして転送量を指定するか、だけれど、転送幅を決めれるのであれば総量はコントロールできるはず。

というのも、転送幅 * 時間 が転送量になるので、一定の転送幅でファイルを送信した後、rsyncをkillすればよい。

以下にスクリプト。

shell> more backup.sh

rsync -av --size-only --bwlimit=1500 /path/from otherhost:/path/to &
PID1=$!

echo kill $PID1 | at 'now+60minutes'


まず、rsyncをbwlimit付きで実行する。アンパサンドを付けて実行することでバックグラウンドで走らせる。

その後、このrsyncをkillするようなatjobを登録する。sleepした後killでもいいかな、と思ったんだけれど、バックグラウンドで動作させてるので親元になるプロセスが死んじゃったときに走り続ける可能性があるのでatでjobを登録した。

ここでは ‘now + 60 minutes’ というキーワードで、60分間rsyncをするようになった。 bwlimitが1500(KB。bwlimitは単位がKB)なので、

1500 KB * 60 * 60 = 5400 MB

およそ5.4GBの転送を行った後、killされることになる。これぐらいならISPから怒られないはず!

あとはコレをcronに登録しておけばおけ。

3. 注意点他

このやり方だと、一日、一回の転送量を決めてファイルのバックアップ、転送ができる。きっと便利なはず。

でも注意することもある。

  1. killで終了になるので、最後に転送中だったファイルは次回再度はじめから転送を始めなければならない。
  2. 増分が一日の転送量より多いとどんどん増えていく。
  3. 厳密に転送量でコントロールできない
  4. それでもプロセスがうまく終了されなかったときの安全策を講じておいたほうが良い。

まず1について。

今回のバックアップは転送量(正確には時間)で終了させるやりかたである。これはファイル単位で行われるのではなく、ファイルの送信中、受信中でも遠慮無く終了されてしまう。そうすると、次回バックアップが行われるとき、この尻切れトンボになったファイルをもう一度最初から送信し直す必要がある。

ファイルが壊れるか、という心配もあるかもしれないけど、それはきっとrsyncがファイルの差分を検出して最初からだけど作り直してくれるはず。

そしてコレはキケンをはらんでいる。これは一日の転送量ほど大きなファイルサイズのファイル、もしくは一日の転送量より大きなファイルを転送しようとしたとき、いつまでたっても一つもファイルの転送が行われないキケンがある。

今回のケースだとファイルは一日の転送量に比べて十分に分割されているという前提なのでこの問題は大丈夫。でも一つの大きなファイルを小さく分割して送りたい、という用途には向かない、と思う。

また尻切れトンボになる分、転送効率が落ちてしまう。一回一回は10GBずつやりとりをしてるのに、この最初からやり直すファイルのせいで1GBぐらい無駄になっちゃった!って事にもなり得るかも。

次に2について。これはバックアップの前提条件にもなるのだけれど、日々とかの増分がバックアップで許される転送量より多いとき、どんどんキューばかり増えて行ってしまって終わらない。先の1、次の3の問題と組み合わせて、基本的には転送効率が悪いのでそこも加味しておく必要がある。

3について。転送幅*時間としている分、理論上は転送量がコントロール出来ているように見える。でも実際は難しいだろう。というのも、転送幅なんて条件によって複雑に上下するものだから、だ。上に溢れることは小さな誤差として起こりうるだろう。下に下がりすぎることはトラフィックの混雑によって簡単に、大きい振れ幅で起きるだろう。だから一日の転送量が思っていたよりもずっと少なくなるかもしれない。でもこれは想定の範囲内としておかなければならないかもね。

最後に4について。万が一、何が起こるかわからないのだから、cronなどでこのスクリプトを回すとき、転送を行うであろう時間帯以外の時間帯に、rsyncをkillするようなスクリプトをかましておいた方が安全だろう。これはISPから警告のメールを受け取るリスクをきっと減らしてくれるはず。

またこのcronはこんな感じ。

0 2 * * * hogetan copy.sh

0 4-23 * * * hogetan killall –9 rsync

これで4時から23時には走っているrsyncはすべてキケンとみなして自動的に消えちゃうだろうね。デモ注意すべき事は、バックアップ送信用の専門のサーバでないとき、意図しない、例えばユーザが任意に走らせているrsyncもkillされちゃうだろう、ってこと。コレには注意。

以上、注意点を述べてみたけれど、ともかくうまい具合に総量でのバックアップ規制を入れる事が出来そう。

便利便利!

「転送量に制限をかけてバックアップをとりたい」への2件のフィードバック

  1. killするのは何とも心もとないので、1日の転送量(ここでの例では5400 MB)を24時間で割った転送幅に設定すればよいのでは?
    5400 * 1024 / 24 / 60 / 60 = 64 KB/s (512 kbps)
    ただ、毎日更新ファイルのサイズが大きいといつまで経ってもバックアップが終わらなくなるので、アップロード制限の緩いプロバイダ(例えばOCNでは30GB/日なので、最大で347.2KB/s、2.77Mbpsまでいける)、もしくは制限のないプロバイダやレンタルサーバーを利用するのがよろしいかと。

  2. inshinさん
    なるほどそうですね!bwlimitの幅を一日の転送量から算出する、というのはアリですね。
    バックアップが終わらなくなると次の日のcronと重複して走ってしまいそうですね(笑)

    プロバイダのアップロード制限に関しては、実は記事に書かなかったんですが、僕じゃないメンバーでのお話しだったんですね。そこのお手伝いをした際の出来事でした。彼はお察しの通りOCNを使って30GB/day制限があるのでその回避策としてこのような方法をとっていました。

コメントを残す