The Overall Architecture of ROMA

2,593 views
2,532 views

Published on

We present the overall architecture of ROMA, which is a distributed key-value store in Ruby.

Published in: Technology
0 Comments
8 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,593
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
7
Comments
0
Likes
8
Embeds 0
No embeds

No notes for slide
  • ROMA は P2P で自律的に複数のノードを管理。さらに、環状にノードを並べて管理している。 各ノードはユニークなハッシュ値をもつ
  • ROMA ではデータの探索をクライアントが行う。 クライアントが ROMA に初めてアクセスした際、 ROMA から環情報を取得する。 この環の情報を利用して、 key の担当ノードを探索する。 このようなことができるのは、 ROMA を構成するノード数が、高々 1,000 台程度だからです。
  • ROMA ではデータの探索をクライアントが行う。 クライアントが ROMA に初めてアクセスした際、 ROMA から環情報を取得する。 この環の情報を利用して、 key の担当ノードを探索する。 このようなことができるのは、 ROMA を構成するノード数が、高々 1,000 台程度だからです。
  • その ROMA のハッシュテーブル(というか key-value store) 上のデータへアクセスする API を提供している。 アプリケーション開発者はこの ROMA クライアント API を利用することで、分散を意識せずに済む。 ROMA へデータを格納すると、実際には複数マシンのメモリ上にデータが格納される。
  • ROMA ではデータが格納されるノードの両隣のノードにそのデータの複製が格納される。 この左右のノードはハッシュ値こそ近いが、物理的には近い場所というわけではない。 現時点ではそこまで考慮した実装ではないが、 DC にまたがっていることも考えられる。
  • 同じデータの複製がある中で、基本的に単一のノードのみが、そのデータの PUT/GET を引き受ける
  • 先ほどの例では、マスターのダウンをクライアントのアクセスがある前に ROMA が気づけた場合の規則 しかし、運悪く ROMA がノードのダウンに気づく前に、クライアントがそのノードにアクセスしてくる場合がある そのような場合は、ROMA はとりあえずダーティフラグ付きのデータをクライアントに返す
  • The Overall Architecture of ROMA

    1. 1. ROMA R akuten O n- M emory A rchitecture 楽天株式会社 楽天技術研究所 西澤無我| 2009年2月20日
    2. 2. ROMA について <ul><li>複数マシンから構成される P2P を利用した </li></ul><ul><li>Ruby 実装の key-value store </li></ul>ROMA (key-value store)
    3. 3. ROMA の特徴 ROMA <ul><li>社内クラウド </li></ul><ul><ul><li>高負荷な状況であっても、十分高速なデータアクセス </li></ul></ul><ul><ul><li>部分障害が起きても、データを喪失しづらい </li></ul></ul>エンドユーザ Web ( アプリケーション ) サーバ GET GET PUT
    4. 4. Consistent Hashing <ul><li>Pure P2P で自律的にノードを管理 </li></ul><ul><li>環状 (Consistent Hashing) </li></ul><ul><ul><li>各ノードはユニークなハッシュ値 (SHA-1) をもつ </li></ul></ul><ul><ul><li>その範囲は 0 ~ 2^64 の整数 </li></ul></ul>ROMA
    5. 5. Zero-hop でのデータ探索 (1/2) <ul><li>各ノードが環全体のノード情報を保持 </li></ul><ul><ul><li>1,000 台程度のノード情報であるため </li></ul></ul><ul><li>クライアントが環情報を保持することも可能 </li></ul><ul><ul><li>ROMA に初めてアクセスした際、クライアントは環情報を取得 </li></ul></ul>ROMA 担当ノード ① データを GET/PUT ③ 担当ノードから 値を GET/PUT ② 担当ノードを計算 コーディネータ クライアント
    6. 6. Zero-hop でのデータ探索 (2/2) <ul><li>各ノードが環全体のノード情報を保持 </li></ul><ul><ul><li>1,000 台程度のノード情報であるため </li></ul></ul><ul><li>クライアントが環情報を保持することも可能 </li></ul><ul><ul><li>ROMA に初めてアクセスした際、クライアントは環情報を取得 </li></ul></ul>ROMA 担当ノード ③ 担当ノードから値を GET/PUT ② 担当ノードを計算 ① データを GET/PUT クライアント
    7. 7. ROMA Client <ul><li>クライアントと ROMA 間は独自プロトコルを用意 </li></ul><ul><ul><li>現在、 Ruby, Java によるクライアント実装 </li></ul></ul><ul><li>開発者に分散を意識させない </li></ul><ul><ul><li>どのマシンにデータが格納されているのか、開発者は意識する必要なし </li></ul></ul>#!/usr/local/bin/ruby require ‘RClient’ rc = ROMA::Client.new rc.open(“roma0”, 3300) # 任意の ROMA プロセスを指定 rc[“muga”] = “data” # ROMA にデータを PUT data = rc[“muga”] # ROMA からデータを GET rc[“muga”] = nil # ROMA からデータを DELETE ※ Ruby 実装のクライアント API の例
    8. 8. Replication (1/2) <ul><li>データが PUT されたとき、 担当ノードはその左右のノードにレプリカを PUT </li></ul><ul><ul><li>プライマリが左右にデータのバックアップを配置 </li></ul></ul><ul><ul><li>ROMA が自動的に行う </li></ul></ul><ul><ul><li>デフォルトでデータの冗長度 ( 多重度 ) は 3 </li></ul></ul>ROMA 担当ノード ① 担当ノードに 値が PUT ② 左右のノードにレプリカを PUT
    9. 9. Replication (2/2) <ul><li>基本的に、単一の担当ノードが PUT/GET を引き受ける </li></ul><ul><ul><li>※ 左右のノードに PUT/GET があると、それは別の意味になる(後述) </li></ul></ul><ul><li>左右のノードにデータが PUT されるまで、クライアントは待つ </li></ul><ul><ul><li>プライマリによるロック </li></ul></ul><ul><ul><li>レプリカの一貫性を保ちやすい(アプリ開発者が楽になる) </li></ul></ul><ul><ul><li>プライマリのノードが性能のボトルネック </li></ul></ul>ROMA 担当ノード ① 担当ノードに 値が PUT ② 左右のノードにレプリカを PUT
    10. 10. Replica Synchronization (1/2) <ul><li>障害時でなくとも、 replication に失敗するケース </li></ul><ul><ul><li>例:忙しすぎて左隣のノードはレスポンスを返せない </li></ul></ul><ul><li>担当ノードは replication に失敗しても、 自身さえ更新できれば成功のレスポンスを返す </li></ul><ul><ul><li>ただし、担当ノードのそのデータにダーティフラグが立つ </li></ul></ul><ul><ul><li>本当はデータの PUT 失敗 </li></ul></ul>ROMA 担当ノード ① 担当ノードに 値が PUT ② 左右のノードにレプリカを PUT
    11. 11. Replica Synchronization (2/2) <ul><li>ダーティーフラグはいずれ解消される </li></ul><ul><li>そのデータは非同期に synchronization </li></ul><ul><ul><li>担当ノードは、ダーティーフラグが立っているデータを検索 </li></ul></ul><ul><ul><li>左右のノードから、異なる値を持つデータを更新 </li></ul></ul><ul><ul><ul><li>シンクロ前にマスター、右ノードが停止してしまうと一貫性は保たれない </li></ul></ul></ul><ul><ul><ul><li>マスターのみ停止したら、キーの更新の時刻を比較 </li></ul></ul></ul>ROMA 担当ノード ① 担当ノードに 値が PUT ② 左右のノードにレプリカを PUT
    12. 12. ノードの Join (1/3) <ul><li>新規のノードの ROMA への参加 </li></ul><ul><ul><li>起動直後、自分のノードのハッシュ値を計算 </li></ul></ul><ul><ul><li>ネットワーク上の全てのマシンに対し、そのハッシュ値をブロードキャスト </li></ul></ul><ul><ul><li>ROMA のノードが応答 </li></ul></ul><ul><ul><li>その隣に新規ノードは入る </li></ul></ul>ROMA 新規ノード ① ブロードキャスト ② ROMA ノードが応答
    13. 13. 各ノードのデータ領域 LS P RS LS P RS LS P RS LS P RS <ul><li>各ノードは 3 つのデータ領域をもつ </li></ul><ul><ul><li>P: 自分が担当しているデータを格納する領域 </li></ul></ul><ul><ul><li>LS: 左のノードが担当しているデータの複製を格納する領域 </li></ul></ul><ul><ul><li>RS: 右のノードが担当しているデータの複製を格納する領域 </li></ul></ul>冗長度 3 冗長度 3 ROMA
    14. 14. ノードの Join (2/3) <ul><li>新規ノードに、左右のノードからデータがコピーされる </li></ul>LS P RS LS P RS LS P RS LS P RS LS P RS ROMA
    15. 15. ノードの Join (3/3) LS P <ul><li>リハッシュ後に、新規ノードはサービス開始 </li></ul>LS P RS LS P RS P RS LS P RS LS RS ROMA
    16. 16. 環情報の更新 ROMA <ul><li>ノード参加の事実を ROMA 全体に通知 </li></ul><ul><ul><li>新しく参加したノードが主導で、環情報を更新 </li></ul></ul><ul><ul><li>環全体にじわじわと情報が伝わっていく </li></ul></ul>
    17. 17. 障害ノードの切り離し <ul><li>どのようにノードの障害を検知するか? </li></ul><ul><li>ノード障害が検知できれば、そのノードを切り離して環情報の更新をすればよい </li></ul>ROMA 障害ノード
    18. 18. ノードの障害検知 (1/2) <ul><li>ハートビートを左右のノードに飛ばして、生存確認 </li></ul><ul><ul><li>( デフォルトで ) 3 秒間隔 </li></ul></ul><ul><ul><li>左右のノードのみ </li></ul></ul><ul><ul><ul><li>左右のノードとは、コネクションを張りっぱなし </li></ul></ul></ul><ul><li>左右が障害と判断したら、真ん中のノードは障害ノード </li></ul><ul><ul><li>現在、ノードの負荷状況によっては誤検知がある </li></ul></ul><ul><ul><ul><li>例 : GC が動作しており、定期的なハートビートが送れない </li></ul></ul></ul>ROMA
    19. 19. ノードの障害検知 (2/2) <ul><li>左右のノードへのデータの PUT/GET による障害検知 </li></ul><ul><ul><li>① ダウンした担当ノードにデータの PUT を依頼 </li></ul></ul><ul><ul><li>② データの PUT に失敗 </li></ul></ul><ul><ul><li>③ 右隣がマスターとなっていると考え、右隣にデータに PUT を依頼 </li></ul></ul><ul><ul><li>しかし、右隣のノードがセカンダリーのままだと、 </li></ul></ul><ul><ul><li>④ 右セカンダリーはクライアントに ダーティフラグ付き のデータを返し、ダウン検知開始 </li></ul></ul>セカンダリー 担当ノード セカンダリー ① ② ③
    20. 20. 障害ノードの切り離し <ul><li>切り離しを行った後は、データの冗長度 2 </li></ul>LS P LS P RS LS P RS P RS LS P RS LS RS 離脱ノード 離脱ノード 冗長度 2 冗長度 2 ROMA
    21. 21. 永続化 <ul><li>デフォルトでは、 redo log と snapshot の構成 </li></ul><ul><ul><li>クエリを redo log ファイルに書き込む </li></ul></ul><ul><ul><li>定期的に redo log を snapshot へ </li></ul></ul><ul><li>Tokyo Cabinet に格納できたら </li></ul><ul><ul><li>Tokyo Cabinet は速いから </li></ul></ul>ROMA (key-value store) データ データ データ データ データ データ
    22. 22. まとめ <ul><li>ROMA </li></ul><ul><ul><li>複数マシンから構成されるオンメモリストレージ </li></ul></ul><ul><ul><li>P2P を利用した key-value store の Ruby 実装 </li></ul></ul><ul><li>アーキテクチャ </li></ul><ul><ul><li>P2P の環状モデル </li></ul></ul><ul><ul><li>レプリカの一貫性をある程度意識したモデル </li></ul></ul><ul><li>今後の展開 </li></ul><ul><ul><li>拡張ライブラリによるパフォーマンス・チューニング </li></ul></ul><ul><ul><li>モデルを改変しやすくできるフレームワーク化 </li></ul></ul>

    ×