Skip to content

Instantly share code, notes, and snippets.

@rimms
Last active December 11, 2015 17:18
Show Gist options
  • Save rimms/4633358 to your computer and use it in GitHub Desktop.
Save rimms/4633358 to your computer and use it in GitHub Desktop.
save/load まとめ

これまでの議論と 進め方 などのまとめ

Jubatus において状態書出/読込機能が必要となるユースケース

save/load という既存機能に関わらず、状態書出/読込機能が必要とされるケースを列挙する。必ずしも、状態書出/読込で実現する必要はない。

  1. 「誤ったデータを学習させた」などのオペレーションミスへの対策
  • チェックポイントの作成/チェックポイントへの復旧
  1. バックアップ/リカバリー(Jubatusの利用用途によって、粒度(要件)は様々ある)
  • チェックポイントの作成/チェックポイントへの復旧(ある程度のデータ損失を許容出来るケース)
  • 最新版の状態の保存、障害発生時点の状態への復旧(データ損失の範囲を最小限にする必要があるケース)
  • 保存したファイルの集約、集約したファイルの配布
  1. 「あるシステムで学習させたデータを他のシステムへコピー」するなどの学習状態の再現
  • システム環境、構成(クラスタ構成、IPアドレスなど)が異なる環境へのインポート

現状での実現範囲 と 問題点

  • チェックポイントの作成、チェックポイントへの復旧 が可能
    • save/load 機能である程度実現
      • 問題点1) システム状態を復元するための情報が揃っているか確認が必要
      • 問題点2) 運用を考慮した機能になっているか確認が必要
        • 異なる config でも load 可能になっている
        • バージョンの異なる Jubatus でも load 可能になっている
        • 異なる システム構成 でも load 可能となっている
        • ファイルのタイムスタンプ か ログ でのみ取得時間を判別できない など...
      • 問題点3) ノード間で一貫性が保たれていない save となる可能性がある(別途 一貫性/整合性について にてまとめる)
        • ノード間で save の開始時間に時間差が生じた場合、ノードA での save 開始 から ノードB の save 開始までに ノードB update が行われると、ノードA と ノードB の状態には一貫性がない
  • 最新版のデータのバックアップ、発生時点の状態への復旧 が可能
    • 未対応 : リバランシング機能 の実現を優先すべき、また、実現方法、実現範囲の検討 も必要
      • スタンドアロン環境では、プロセス停止とともに最新のチェックポイントからの情報は失われる(Jubatus の外でクラスタ構成を形成している場合は、save/load で復旧が可能かもしれない)
      • 分散環境でも、単体のノードで見た場合は、スタンドアロンと同じであるが、データ多重化、モデル情報の共有を行なっている
        • モデルの状態は mix で共有しているが、mix は定期的な実行なので、Eventually Consistent な関係性
        • cht によるデータ格納ノードの多重化を行なっているが、離脱したノードへ対する cht のリバランシング、多重化数の選択ができないなどの問題がある
  • システム環境、構成(クラスタ構成、IPアドレスなど)が異なる環境へのインポート
    • 未対応 : リバランシング機能 の実現を優先すべき
      • classifier や regression など、cht を利用していないアルゴリズムは、save したデータを load することできる
      • IPアドレスを元にした cht であるため、cht を利用しているアルゴリズムでは、IPアドレスが異なる環境へ load することは不可能
      • 異なるクラスタ構成への load も同様に、cht を利用している場合は、リバランシングが問題となるため、不可能
  • 保存したファイルの集約、集約したファイルの配布
    • 未対応 : OSコマンドで代替可能なため、優先度は低い

一貫性/整合性について

update の頻度によらず、クラスタ全体で一貫性を保った状態書出を行うためには、クラスタ全体で書き込み(update, mix) がない状態で各ノードが save を開始しないと不可能である。

save を非同期で実行する場合であれ、クラスタ全体の update を瞬間的に止める必要があるが、Jubatus の場合、可用性を犠牲にした手段は許容されないと考える。

一般的に、分散システムでは 一貫性 と 可用性 はトレード・オフの関係にある言われる。可用性を維持しつつ、一貫性の欠落を最小限にする方法での状態書出が望まれる。

また、Jubatus では、mix の際に update された情報を破棄するような仕組みであり、コンセプトでもあるので、一貫性は保証していない。

この観点での実現は、より多くの利用ケースや要望を収集した後に、方向性の検討と実現をしていくこととする。

可用性を保ったまま一貫性のある状態書出の実現方法(案)

  1. バージョン付与によるノンブロッキングな方式
  1. 全ノードに get_version() を投げてモデルのバージョン番号取得
  2. 全ノードからバージョン番号を受け取ったら get_version_and_model() を投げてバージョン番号とモデルデータのペア取得
  3. 1回目 と 2回のバージョン の比較
  • バージョンが全て一致したら一貫性のとれた状態
  • バージョン番号の差の合計が許容範囲内に収まるか、特定の回数になるまで 2 と 3 を繰り返す
  • update が少ないケースでは、一貫性のとれた状態の書出が可能
  • update が多いケースでは、一貫性のある状態にならないが、利用用途に合わせて許容範囲を設定として提供する事が可能
  1. mix のタイミング

各ノードの mix完了 のタイミングで モデル を出力する

  • liner_mixer では有効な手段
  • Jubatus のコンセプトに従った一貫性であると言える
  • liner_mixer 以外の mix戦略 では有効ではない可能性がある (要確認)

現状の save/load のへ対する議論

各々のノードで save させるのが得策なのかどうか

各々のノードで save する場合の問題点

  • load する際に、クラスタ構成を意識する必要がある
  • ノード間で重複データ (レプリカ))が生じるのでディスク容量が無駄
  • ディスク起因で save に失敗するケースの考慮が必要

管理ノードを用意し、各ノードからモデルを集約し、管理ノードに単一ファイルを save するという案

  • 台数を意識せずにloadできる
  • 重複データは生じないので省ディスク容量
  • サーバのローカルディスクの状態について考慮しなくてよい
  • モデルファイルのハンドリングが容易
  • NW 帯域のコストは高い
  • 学習モデルデータ、本気出すとギガ級になる

実装コストを度外視するならHDFSのような抽象的な分散ストレージ層を作って共有するという案

  • 実装コストが高い

本件は、Jubatus の方向性、コンセプト としてどうかという議論が必要であり、一旦ペンディング。

将来的な方向性について [TBD]

今後の開発方針、開発項目へ影響するため、将来的にどこを目指すかは決めておく必要がある

例)

  • save/load 時には keeper で update をとめる。その間の update は keeper でキューイングする。
  • 一貫性は保証しない。ノンブロッキングな方式を採用し、許容可能なバージョン差、リトライ数を設定可能とする。
  • レプリケーションノードを用意し、レプリケーションノードから save させる。
  • ジャーナル機能をもたせる。

進め方について

状態書出/読込機能 が必要となるケースで、分散システム や Jubatus として不足している点からフォローできないケースが多い。

そういった不足している点を優先的に実現する必要がある。

問題になるのは、classifier, regression 以外のアルゴリズムで、storage に生データを保存しているようなアルゴリズム。

現状の機能としての save/load は「チェックポイントの作成、チェックポイントへの復旧」という点で、必要な機能であり、現状存在する問題は早期に解決しないと運用で問題が発生する可能性がある。

まずは、以下の 2点 について取り組むこととする。

  • 問題点1) システム状態を復元するための情報が揃っているか確認が必要
  • 問題点2) 運用を考慮した機能になっているか確認が必要

参考

既存のsave/load機能

  • 実行方法
    • RPC リクエスト
    • RPC メソッドには nameid を指定する
    • 最も簡単な実行方法は、クライアントの利用する方法
    • keeper で受け付けた場合は、broadcast する
  • 保存先
    • ローカルファイルシステム
    • -d, --datadir で指定されたディレクトリ
  • 保存ファイル名
    • ADDR_PORT_jubatus_ID.js
      • ID は、メソッドの引数
  • 保存対象
    • mixable_holder へ登録された mixable0 を継承したクラスの状態
  • 保存方法
    • pficommon の archiver
    • スレッドで write lock を取得する

save/load 保存対象 [TBD]

システム状態を復元するための情報

確認中

状態を持つものはひと通り保存する必要がある。

対象 備考
学習モデル 学習の状態
ストレージ 学習の状態
fv_converter 将来的に必要になるかも
その他 状態を持つもの(global_id とか)

運用を考慮した情報

選定中

load時の チェックエラーは ERROR として、load 失敗扱いにする。ものによっては WARINIG で良いかも。

対象 備考
config
load時にサーバープロセスが保持しているものと異なっていないかチェックする
string での比較ではなく、意味が同じことをチェックしなくてはいけない
クラスタ構成
load時にzk上のmembership情報と異なっていないかチェックする
構成台数のみのチェックにしておいたほうが良い
Jubatusのバージョン load時に互換性があるバージョンであるかチェックする
ID
RPC実行時に指定されたもの
クラスタ内で一意性を持つ名前である必要がある
UUID を keeper (スタンドアロン時はserver) が払い出すというのもあり
プロセス名 付加情報) jubaclassifier とか
アルゴリズム 付加情報) classifier, recommender
name 付加情報) クラスタ名
タイムスタンプ 付加情報) save時のタイムスタンプ
status情報 付加情報) save時のstauts

save/load方法

TBD: rdbms のバックアップファイル名/構成を調査したうえで、運用を考慮した方針へしたいと思います。

保存先

  • -d, --datadir で指定されたディレクトリ
    • 指定されたディレクトリに読み込み/書き込み権限があるかは起動時にチェックすべき

保存構成 [TBD]

以下を考慮して検討する。

  • 「運用を考慮した情報」がエディタで確認/編集することが必要か? 必要であれば、人間が読める形式とする必要が有るため、ディレクトリを作成して出力する
/datadir/snapshot-ADDR_PORT_NAME_ID
  + 運用を考慮した情報
  + システム状態を復元するための情報

良い点

  • ディレクトリ名、ファイル名 で分からない場合、ファイルを開くだけで load 対象としたいものかどうか分かる
    • わざわざ人間が読める形式でなくとも、タイムスタンプ または ログを見れば分かる場合もある
    • 変換ツールを用意する、OSコマンド可視化できる場合もある

悪い点

  • 一箇所に集める、配布するという運用まで考えると、ディレクトリを作成せず、1ファイルで実現したほうが良い
/datadir
  + snapshot-ADDR_PORT_NAME_ID

保存形式

  • システム状態を復元するための情報: pficommon の archiver を利用する(既存踏襲)
  • 運用を考慮した情報:
    • 読めるものとする場合: ネスト可能なデータ形式、list や map を容易に表現可能な形式 (要検討)
      • JSON は 数値型のビットサイズを規定しておらず実装依存になる(64ビット整数を扱えなかったりする)から避ける
      • msgpack 形式は string のところは読める
      • yaml や xml のような新たな形式を導入するのも...
    • 読めなくても良い場合: システム状態を復元するための情報 に含める

運用を考慮した情報のsave/load実現方法

  1. summary とか適当な名前の構造体を定義し、値を詰め込む
  2. 変換をかけて出力する

エラーハンドリング [TBD]

save時

  • すでに同じ名前のディレクトリ or ファイルが存在する場合:
    • ERROR とする
    • 正常に出力できたノードのゴミ掃除は促す?
  • ディスクフル等で出力失敗:
    • ERROR とする
    • 正常に出力できたノードのゴミ掃除は促す?

load時

  • 対象のディレクトリ or ファイルがない場合:
    • ERROR とする
    • 正常にloadできたノードはどうなる?
      • 存在チェックと2段階が必要かも

DBスナップショットメモ

NoSQL系

mongoDB

  • dump/restore
    • mongodump/mongorestore コマンド。
    • BSON形式(バイナリ)でテーブルの中身を出力。
  • Import/Export
    • mongoimport/mongoexport コマンド。
    • JSON形式でテーブルの中身を出力。
  • ジャーナルファイル
    • データの格納域(dbpath)に jounal ディレクトリを作成、出力される。
    • ファイル名は j._ を接頭辞に持つ。 ex) j._1
    • 形式はバイナリ。

redis

  • Snapshotting (ゆるい永続化)
    • redis.conf で設定したディレクトリ/ファイル名。
    • バイナリ形式。
  • save/bgsave
    • Snapshotting を即時に実行する。
    • lastsave で 最後のsave実行時間 を取得できる。unixtime。
  • 追記専用モード (redoログ)
    • redis.conf で設定したディレクトリ/ファイル名。
    • redis の プロトコル の生データが出力される。編集可能。

Riak

  • tar でファイルを固める
    • ノード間の矛盾はリストア時に回復される(?)

RDBMS系

MySQL

  • mysqldump
    • SQLをテキスト形式で出力。
  • mysqlsnapshot
    • tarで保存。内部的な形式は未調査。
  • mysqlhotcopy
    • 形式未調査

PostgreSQL [未調査]

  • pgdump

Oracle [未調査]

  • rman
  • export/import
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment