(IOTS2018)にて、投稿した論文の発表をしてきました。実は、そのときに、来年論文を投稿するぞと意気込んでいました。実際にはそこから2年かかりましたが、この度論文を投稿することができました。異種混合キーバリューストアを用いた自動階層化のための時系列データベースアーキテクチャスライド実務から研究へ今回投稿した論文の内容は、Mackerelで開発した時系列データベースに関するものです。Architecture研究会で発表済みのものになります。4点を記述できていることが求められます。─システム開発・ソフトウェア開発論文編─の文献が参考になります。要素技術の新しさがなければ論文にならないと思いこんでいましたが、こちらの文献を読んだことで、システム開発論文の場合、個別の要素が既知であっても、組み合せが新しく工夫があり、さらに他のシステムに応用可能であり、先行手法と比較して優れていることを主張できていることが重視されるということがわかりました。ある前提条件の中で、他のシステムに応用可能なレベルで記述された要素技術の組み合わせの法則をアーキテクチャと呼び、新規性の観点では、アーキテクチャが新しいことを示し、有効性の観点では,実装が優れているのではなく、アーキテクチャが優れていることを示すことを目指すというのが自分の理解したろことになります。当たり前ですが、あらゆる局面に適用可能な大統一アーキテクチャのようなものをいきなり提案できるわけはありません。サーバモニタリングのための時系列データベースという強い制約条件下においても、あらゆる観点において優位となるアーキテクチャを提案することさえ難しいでしょう。今回の論文では、Mackerelのようなモニタリングサービス向けの時系列データベースという立ち位置をとり、モニタリングサービスを成長させていくための拡張性をもつ時系列データベースがないという問題意識から、書き込みスケールアウト性、高可用性、書き込み処理効率、データ保存効率といった性能要件を満たしつつ、データ構造の拡張性をもたせるという要件を具体的に設定しました。これらの要件に対して、分散KVSを利用することで、書き込みスケールアウト性と高可用性を解決し、書き込み処理効率とデータ保存効率、拡張性については、万能なDBMSはないことから単一のデータベース管理システム(DBMS)で対応するのではなく、異なる特性をもつDBMSを複数組み合わせるという時系列データベースの構成法を考えました。DBMSを複数組み合わせるといっても、どのように組み合わせるのかは自明でないため、組み合わせのための手法として、キーバリューという単純な形式で時系列データ構造をどう表現するのか、DBMS間のデータ移動をどうやるのか、データ構造の拡張をどうやるのかを実装に依存しない手法として落とし込み提案しました。新規性がどこにあるかについては、論文表題にあるHeteroTSDBというアーキテクチャ名に込めています。異種混合(Heterogeneous)のDBMSを組み合わせて、各DBMSの特徴を活かしつつ、欠点は別のDBMSの特徴で補い、ひとつの疎結合な時系列データベースをつくるという考え方です。Applications」での原則になっています。論文では、時系列データベースとして構成するための法則が世の中になかったために、新規性のあるアーキテクチャであると主張しています。今回論文化する上で苦労したことは2点あり、先行手法に対する有用性をいかに示すかということと、分量を研究会指定の8ページに収めることでした。先行手法に対する有用性については、前提として、HeteroTSDBは、単純な性能では、密結合に構成され、処理効率に最適化されたアーキテクチャにはかないません。当初、提案手法はサーバレスプラットフォームの活用により運用しやすいということを主張しようとしましたが、先行手法の一実装であるOpenTSDBやInfluxDBをサーバレスプラットフォームとして実装すればよいだけで、提案手法が有用ということにはならないと結論付けました。なるとどのように有用であることを示すのかということについて、HeteroTSDBが疎結合な構成であることに着目し、一般に密結合なソフトウェアよりも疎結合なソフトウェアのほうが拡張しやすいという性質があるために、拡張性という後付けではあるものの、提案手法が有用となる要素を見出しました。2つ目の分量については、もともとが実務の大きな開発プロジェクトであり、複雑に絡まりあった多くの要素があり、それらをよく知っている分、シンプルに書き上げることが難しく感じました。論文では、いろいろ削った上で5つの要件を設定していますが、それでも読み手には負担のかかる数であるため、書き込みスケールアウト性と高可用性については、当たり前に必要ということで要件から外し、よりシンプルにみせるということができたと思います。ここまで読むと、実務から研究に落とすのは大変なだけなように思います。ソフトウェア開発や運用技術の研究では、実用足りうる実効性をもつことを重視されるようになってきていると聞いています。実効性をもたせることは、実務での成果を直接担うエンジニアが得意とすることであるため、実効性の評価に関しては、記述の仕方について工夫が必要ではあるものの、エンジニアであることが大きなアドバンテージとなると感じました。Learnedという章に、実環境での適用が書かれています。IOTSの質疑応答の場においても、実効性の観点から生まれた質問がいくつもありました。記事を書いたころに、自分が得意なシステム系の分野について、数多くの論文が書かれていることを知りました。このときから、自分が考えたり、作ったりしたものをいつか論文としてアウトプットできるとよいなあと漠然と思っていた気がします。ソフトウェアエンジニアであれば、自分がつくったソフトウェアをOSSとして公開し、あわよくばいろんなところで使われることで世界に1石を投じるということを夢見ることがあるように思います。ブログでのアウトプットに一通り満足してきたあるとき、僕はこれに近いモチベーションで論文を書こうと思い立ちました。近いモチベーションなのであればOSSでいいんじゃないとなるかもしれません。新規性があったり、有用性のあるソフトウェアを作るための明確なステップは存在しないようにみえますし、それができる人は高いセンスと努力により飛び越えていっているようにみえます。そこで、論文として投稿することで、良いものなのかどうなのか客観的に評価を得ることができます。学術の世界では、長い歴史の中で数多くの知見が蓄積されているために、前述したように評価の観点が整理され、査読というプロセスも確立され、国際会議やジャーナルなど場としてのランク付けもあるために、良いものをつくっていくための客観的ハードルが設けられているように思います。これらのハードルを超えていくことで、自分を成長させ、最終的に新しいものを作り続けることができるようになることができるのではないか、と考えています。記事を読むとよいと思います。論文の裏にあるコンセプトHeteroTSDBアーキテクチャでは、クラウド上で基盤ソフトウェアを開発していくための一つの考え方を示そうとしています。基盤技術と一口に言っても、CPUのようにIntelとAMDが大勢を占める層から、Linux、Windows、BSD系などが主に利用されるOS層、その上のミドルウェア層やプログラミング言語処理系の層というように、技術の階層を登れば登るほど、要素技術とその組み合わせの数が多くなっていき、個々の事業固有の層まで達すると、基盤として吸収することは難しくなります。AWSと言えど、これらの組み合わせをサービスとして揃えていくことは難しいのではないかと考えています。実際、AWSの個々のサービスは制約を強くかけることにより、スケーラビリティを確保し、AWS利用者は、各サービスを組み合わせ、やりたいことを実現していけるようにできているようにみえます。次のように分解と再構築の考え方に従い、データベースを新しい要素技術の上に再構築しようと試みています。Systemsにて、データシステムを構築する上で、すべての異なる状況に適した1つのソフトウェアは存在せず、異なるソフトウェアを組み合わせアプリケーションを開発していく必要があるという趣旨の意見が書かれている。Diamondアーキテクチャは、この考え方の延長線上にあり、インデックス、WAL、メモリ上のデータ構造、ディスク上のデータ構造など、古典的なデータベースエンジンの構成要素を、ヘテロジニアス環境で再構築したものになる。サーバレスアーキテクチャにより、分散システム上での複数箇所にまたがるデータの更新、移動を、信頼性のあるビルディングブロックの上に構築しやすくなった。まとめると、クラウド事業者が吸収できる基盤の限界の外では、分解と再構築の考え方に従い、伝統的な要素技術をクラウド上で再構築し、クラウドを前提としたアーキテクチャを築いていくという考え方になります。GeekOutコラムあとがき業務そのものに直接関係しないにも関わらずおつきあいいただいたはてなの共著者のみなさま(astjさん、itchynyさん、Songmuさん)ありがとうございました。論文化するにあたって、matsumotoryさんとhirolovesbeerさんには、お忙しい中、時間をとっていただいて快く指導していただいたこと、指導いただかなければ論文として形にならなかっただろうということと、指導いただいている間に成長を実感できたことに大変感謝しています。発表時の質疑応答では,次のような議論をしました.まず,接続が観測されたホストでも実はトラヒックはほとんど流れていなくて接続しているだけで,実際は利用していないホストであったりすることがある。TSDBこの記事は、第2回ウェブシステムアーキテクチャ研究会の予稿です。ウェブシステムをモニタリングするために、高可用性、高書き込みスケーラビリティ、メトリックの長期保存が可能な時系列データベースが求められている。Store(以下KVS)を組み合わせ、透過的に問い合わせ可能な、ヘテロジニアス時系列データベースであるDiamondを開発した。はじめにクラウドコンピューティング、コンテナ型仮想化、マイクロサービスなどの普及により、ウェブシステムの複雑度が向上した結果、人間が複雑な構造を観測するために、よりよいモニタリングが必要とされている1。モニタリング技術のうち、時系列データモニタリングがあり、時系列データの可視化と時系列データによるアラーティングが一般的である。時系列データモニタリングのために、多数のサーバから複数のメトリックを定期的に時系列データとして収集する必要があり、ストレージとして時系列データに特化した時系列データベースが利用される2。時系列データベースには、様々な要求があるが、ここでは、メトリックの長期保持、高書き込みスケーラビリティ、高信頼性が要求されるユースケースに着目する。Service(SaaS)型のモニタリングサービスにおいて強く求められる。時系列データベースには、大きく分類すると専用DBMS方式と汎用DBMS方式、RDBMS拡張の3種類がある4。RDBMS拡張については、ここでは汎用DBMS方式に含むこととする。専用DBMS方式は、時系列データベースに最適化されたデータベースエンジンを実装しており、汎用DBMS方式は汎用DBMS上に時系列データベースとして動作させるためのアプリケーションを実装している。専用DBMS方式は、性能とデータ保存効率がよいが、分散システムとしての信頼性の観点では、汎用DBMS方式と比較して、成熟度が劣る傾向にあると考える。Graphite5、Gorilla6、BTrDB7などがある。汎用DBMS方式は、汎用であるがゆえに専用DBMS方式と比較して性能は劣りやすいが、分散システムとしての信頼性が高い。OpenTSDB、KairosDBなどがある。このように、長期保存、高書き込みスケーラビリティ、高信頼性を満たす時系列DBはある一方で、特殊なストレージエンジンのため運用コストが高い、または、長期保存かつ高書き込みスループットであってもリソース使用量が高いといういずれかの課題がある。リソース使用量の高さは最終的に費用の高さに結びつく。そこで、低運用コスト、低費用で、メトリックの長期保存、高書き込みスケーラビリティ、高信頼性を実現するために、複数の異なる汎用DBMSを組み合わせ、透過的な問い合わせが可能なヘテロジニアス型時系列データべースとしてDiamondを開発した8。Log(WAL)9として分散メッセージブローカーを利用した。プロビジョニングと故障からの復旧の容易さを低減するために、マネージドサービスを用いたサーバレスアーキテクチャ10を採用した。アーキテクチャアーキテクチャ概要アーキテクチャとしての達成要件は以下の5つである。(b)については、汎用DBMS方式を選択し、Dynamo-styleと呼ばれるようないわゆる分散データベース[2]を利用することにより達成できる。Dynamo-styleのデータベースは、CassandraやDynamoDBのようにKVSの形をとることが多いため、以下ではKVSの利用を前提とする。(c)については、書き込みI/OだけみればインメモリKVSが有利だが、データ保持の観点でみるとHDDベースのKVSが有利である。そこで、複数のKVSを組み合わせたヘテロジニアス構成により、インメモリKVS書き込みI/Oを受け付け、参照頻度の低い古いタイムスタンプをもつデータポイントを低速なディスクに配置する。Kafkaのような分散メッセージブローカーをWALとして利用し、クラッシュリカバリできるようにする。複数のOSSのDBMS実装を用いつつ、(d),(e)を達成することは、困難であると考え、そこで、クラウド事業者が提供するマネージドサービスを用いたサーバレスアーキテクチャを採用する。一方で、専用DBMS方式を選ばない理由として、次のの2点がある。(a),(b),(c)を満たす専用DBMS方式を新規開発することは難易度が高いことと、汎用DBMS方式のほうが分散システムとして成熟した実装である傾向があるためだ。ヘテロジニアス環境においては、一時的な故障の発生により、各KVS間のデータ整合性と耐久性を失いやすくなる。そこで、故障時にリトライ可能にするために、べき等性をもつデータ構造が重要となる。複数の異なる特性をもつKVS実装を利用するため、特殊な機能に依存しないシンプルな機能要件のみで、データ構造を実装できることが重要だ。伝統的なデータベースが備えるACID特性を満たすことは、サーバモニタリング向け時系列データベースのコアな要求ではない。以下では、アーキテクチャの動作フロー、データ構造およびKVSの機能要件を説明する。動作フローDiamondアーキテクチャの動作フローを以下に示す。------------/+-----------------+まず、書き込み経路を説明する。nodeがインメモリ分散KVSに書き込みにおいて、メトリックごとのデータポイント数が所定の個数を超えていれば、SSDベース分散KVSに書き込み書き込み経路とは異なるバックグラウンド処理により、一定期間より前のタイムスタンプをもつデータポイントをSSDベース分散KVSからHDDベース分散KVSへデータを移動させる分散メッセージブローカーは、インメモリKVSのクラッシュリカバリのために利用する。分散メッセージブローカーに残留するログを再適用することにより、インメモリKVS上のロストしたデータを復元できる。次に、読み込み経路を説明する。nodeは、データポイントを取得したのちに、任意の集約操作を適用し、クライアントへデータポイント列を返却するDiamondアーキテクチャでは、複数のKVS間のデータの整合性を保つために、各KVSへの書き込み処理がべき等であることが重要となる。書き込み処理がべき等であれば、既に書き込んだデータを再度書き込んだとしても、データの一貫性が担保される。したがって、クラッシュリカバリの発生またはいずれかのKVSの故障が発生したとしても、リトライによりデータの耐久性を確保できる。書き込み処理をべき等にするためのデータ構造を以下に説明する。データ構造Diamondは、Graphiteプロジェクトの時系列データベースであるWhisper[^14]データ構造に近いモデルを採用している。Diamondでは、Whisperデータ構造の特徴のうち、以下の2点に着目している。書き込み処理がべき等であることクライアントの入力にかかわらずメトリック系列に含まれるデータポイント数の最大値を制御できることまず、KVSに時系列データを格納するための最もシンプルなデータ構造を、以下の図に示す。+-----------------------------------------+図中のnameはメトリック名を表す文字列、timestampはデータポイントのUNIX時間を表すint64型の数値、valueはデータポイントの値を表すfloat64型の数値である。ハッシュマップのバリューを値(value)とする。グラフ表示などの読み込みワークロードを考慮すると、ある系列に含まれるデータポイント列をまとめて効率よく読み出す必要があるため、データポイント列を同じレコード内にまとめて格納する。データポイント列を表すデータ構造が、リストではなくハッシュマップである理由は、同じタイムスタンプをもつデータポイントの上書きを許し、べき等性を確保するためだ。nodeがレンジ外のタイムスタンプをもつデータポイントを間引く必要がある。このデータ構造は、データポイントが追記されるたびに、レコードサイズが増大していく。KVSはレコードサイズに制限をもつことがあり、その場合制限を超えない程度のレコードサイズを維持しなければならない。Bigtable12は256MBのハードリミットをそれぞれ持つ。この問題を解決するために、メトリック系列を固定幅のタイムウィンドウに分割するデータ構造を以下の図に示す。+-----------------------------------------+wtimestampは、タイムウィンドウの開始時刻を表すUNIX時間であり、ウィンドウサイズは固定長とする。1482706020...のように3000ずつ加算される。ウィンドウ内のデータポイント数の最大値が不定であるため、レコードサイズのハードリミットを超える可能性がある。時系列データベースとしてサポートするメトリックの解像度をステップと呼ぶことにすると、クライアントがステップより小さなインターバルでメトリックを書き込む場合、ウィンドウ内のデータポイント数は想定よりも大きな値となる。そこで、データポイント数の最大値を固定するために、ステップの倍数にアラインメントする。解像度を60秒とするならば、元のtimestampが1482700025であれば、60で割った剰余を差し引いた値である1482700020に変更したのちに、KVSに書き込む。ステップよりも小さいインターバルで書き込まれると、アラインメントにより既に書き込まれたtimestampの領域を上書きすることになり、ウィンドウ内のデータポイント数は一定の個数以下となることが保証される。以上により、Diamondデータ構造がべき等性をもちつつ、KVSの制限内で書き込み処理可能であることを示した。次に、Diamondデータ構造を実現するためのKVSの機能要件を説明する。KVSの機能要件Whisperデータ構造をKVS上で実装するには、各KVSへ求める最低限の機能要件として以下を満たす必要がある。キーを入力とし、キーに対応するバリューを出力できるバリューのデータ型としてバイナリが実装されているKVSとしてごく標準的な機能を満たせば実装可能であることが要点である。書き込み処理効率の観点では、バリューのデータ構造としてハッシュマップが実装されていることが望ましい。データポイントをレコードに追記する際に、レコード内に存在する既存のデータポイントをKVSの外へ読み出したのちに、新らたに書き込むデータポイントを結合し、レコードを更新する必要がある。KVSがハッシュマップを実装していれば、KVS内で効率よくデータポイントを追記できる。ACIDのうち隔離性の観点では、read-modify-write操作をatomicに実行できることが望ましい。複数のクライアントが同じレコードを書き込もうとしたときに、クライアントAが既存のレコードを読み取ったあとに、クライアントBがレコードに書き込んだとき、クライアントBの書き込みが失われることがありえる。functionを起動し、S3へ期限切れしたレコードを書き込む。実装の構成図を以下に示す。2017のプレゼンテーション17,18,19にて紹介している。KVS間のデータ移動まず、RedisからDynamoDBへの移動の実装を説明する。バックグラウンドプロセスによるバッチ処理ではなく、writerがRedisへのデータポイント書き込み時に条件を満たした場合のみメトリック系列単位でDynamoDBに移動させる。条件は、Redis上の該当メトリック系列に含まれるデータポイント数がN個以上である。条件を満たすかをチェックしたのちに、Redisのレコードを読み出し、DynamoDBへ書き込み、最後にRedisの該当レコードを削除する。定期的なバッチ処理により、DynamoDBに移動させる。function実行のリトライにより、耐久性とRedisとDynamoDB間のデータ整合性が担保される。次に、DynamoDBからS3への移動の実装を説明する。Functionを起動し、DynamoDBの期限切れレコードをS3に書き込む。encodingにより差分符号化した結果を書き込み、データポイントあたりのバイト数を削減している。function実行のリトライにより、データの耐久性と整合性が保証される。nodeは、受信したメトリック名とタイムスタンプレンジから、各KVSのうち必要なデータが存在するKVSからデータを取得する。データが存在するKVSは、メトリックごとに記録せずに、静的に解決している。