Unison を使って実現する大量データの双方向同期
1. 実現したい事
数百 GB から数 TB に及ぶ大量のデータを、複数の計算機環境で Dropbox のように同期したい。しかも無料で、かつ Dropbox よりは転送速度の速いものが良い。
実験データとか計算データとか解析データとか、職業柄いっぱいデータを扱う日常でして、しかもそれが手元の MacBook Pro の中にあったり、どっかの研究所の計算機 server にあったり、果ては昔の所属機関の RAID に詰まったりしているわけです。遠隔地にデータがあったとしても、計算させるだけだったら SSH で job を投げるだけで済みます。しかし X を飛ばしてちょっと解析したくなってくると、どうにも SSH じゃやっていられません。
そんな中、512 GB の SSD も値段がこなれてきて、また 1 TB の 2.5" HDD なんかも出てきました。僕の仕事用の MacBook Pro は OWC の Data Doubler というのを載せているため、SSD と HDD の二台載せが可能です。合計で 1.5 TB もあれば各地に散らばったデータを収容する能力があるわけで、是非ともこれらを集約したくなります。
2. rsync の問題点
しかし rsync で同期しちゃえば済むじゃないか、と単純には行きません。なぜなら rsync の同期は一方通行だからです。MacBook Pro 側でデータを部分的に変更して、遠隔地側でも変更してなんて作業をしてしまうと、両者の整合性を取るのが面倒になります。
また、不要な file を片方で消去した時に、rsync で同期してしまうとそれが復活するなんてことも発生します。.log を消したり、*~ を消したりした場合、こういうものは同期先 (or 同期元) でも同時に消えてもらいたいものです。
3. Dropbox の問題点
じゃあ、もっと便利な Dropbox を使えば良いじゃないか、となるわけです。rsync が古くから Un*x で使われてきたのにも関わらず、Un*x 使いの中でも Dropbox が人気なのは、双方向同期を気軽に、しかも background でやってくれるからでしょう。
しかし、最大の問題が発生する料金です。僕の場合は「Dropbox の容量を無料で 20GB まで増やす方法」などを使って、無料で 24.9 GB まで使えるようになっています。しかし、100 GB を Dropbox で確保するには年間 $40 が発生し、また 1 TB を使うには年間 $795 も必要です。これはちょっと研究費で賄う気にはなりません。
さらに、Dropbox は転送速度が遅いため、即座に大量のデータを同期させたい場合には向かないらしいと聞きます。
4. Unison を使おう
ということで、色々と悩んで Twitter で助言をいくつか頂いた結果、Unison を使うことにしました。先に Unison の長所と短所を書いておきます。
4.1 Unison の長所
5. Unison の導入
5.1 Mac の場合
MacPorts なりを使って簡単に導入しましょう。僕の Lion 環境では ver. 2.40.63 が入りました。
$ sudo port install unison $ unison -v unison version 2.40.63
5.2 Linux の場合
これは使っている環境にもよると思いますが、僕の場合は管理者権限のない計算機に導入したため、自分で build しました。prefix は $HOME/opt です。環境は RHEL 5 (64 bit) です。
まずは OCaml を落としてきて build します。3.12.1 を使いました。これがないと Unison の build ができません*1。
$ tar zxvf ocaml-3.12.1.tar.gz $ cd ocaml-3.12.1 $ ./configure -prefix $HOME/opt $ make world $ make opt $ make opt.opt $ make install
次に、Unison の build ですが、version 番号を全ての環境で統一する必要があります。Mac で導入した 2.40.63 を入れます。
$ tar zxvf unison-2.40.63.tar.gz $ cd unison-2.40.63 $ emacs Makefile #ここで$(HOME)/bin を $(HOME)/opt/bin に書き換えた (好みで) $ make $ make install
これだけです。unison -v で、Mac のものと同じ version 番号かを確認しましょう。
5.3 遊んでみる
この後は、Unison の基本的な使い方を学ぶために、manual を読んで動作確認をしてみましょう。英語の公式か、有志の方の日本語訳を参照して下さい。「Tutorial」のところを読んで基本的な動作を身に付けましょう。
5.4 自分が使っている引数
- -owner 所有者の情報を維持します。これをつけないと、UID が同一になるようになるのかな? login name が違う環境同士でやるとどうなるんでしょうね。試していません。
- -prefer newer 更新日時の新しいものを優先します。同時編集している場合などには注意してください。
- -times これをつけないと、file の time stamp がメチャクチャになるそうです。
- -batch 変更が衝突した場合に、"-prefer newer" に従って自動的に衝突を解決します。勝手にやられるのが嫌な場合は、-batch は外して手動で解決しましょう (衝突した file ごとに、ちゃんと確認が出ます)。
- -path 特定の下の階層だけを同期したい時に使います。
実際には、以下のような使い方をしています。
$ unison . ssh://YOUR_REMOTE_SERVER/THE_DIRECTORY_WHICH_YOU_SYNC -owner -prefer newer -times -batch
今のところ、名古屋で使用している MacBook Pro、アメリカ西海岸にある SLAC の計算機環境 (100 CPU 使える)、千葉県にある宇宙線研究所の計算機環境 (これも 100 CPU 使える) の三箇所で同期しています。同時に 200 CPU を使いきりたいときには、両方の計算機で並行して job を投入するため、両者の出力結果を同期させ、さらに手元の MacBook Pro に持ってくるという用途には、Unison は最善の解決方法だなと実感しています。
5.5 注意点
Unison は background で更新を調べてくれたりはしません。ユーザが unison を実行するたびに、同期元、同期先の directory 階層を調べに行って更新箇所を調べます。そのため、数十万や数百万の file を同期しようとすると時間がかかります。特に、接続先が NFS などを使っている場合は負荷がかかります。可能な限り、データを少ない数の file にまとめるようにしましょう。
海や大陸を跨いだ同期をする場合、「遅延時間」のせいで scp や rsync と同様に非常に時間がかかります。特に初回同期時には何十時間もかかってしまうでしょう。これを解決するためには、Unison でいきなり同期するのではなく、あらかじめ rsync や scp などで同期できる部分は同期しておきましょう。その際には「scp の複数同時接続」のような手法を使うことで、長距離でも 100 Mbps を超えるデータ転送が可能になります。Unison を使って同期するのは、初回同期が済んで、両者で更新をするようになってからでも問題ないでしょう。
Unison は実行時に、SSH を使って同期先の unison の version を調べます。僕は .zshrc の設定で login 時に色々と標準出力へ吐き出すようにしているのですが、これがあると version 番号が正しく出力されなかったと見なされてしまいます。unison への PATH を通すだけの .zshenv などを用意してやると、これを解決できます (参照)。