• Like
HBaseを用いたグラフDB「Hornet」の設計と運用
Upcoming SlideShare
Loading in...5
×

HBaseを用いたグラフDB「Hornet」の設計と運用

  • 2,586 views
Uploaded on

Hadoop Conference Japan 2014で発表した資料。

Hadoop Conference Japan 2014で発表した資料。

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
2,586
On Slideshare
0
From Embeds
0
Number of Embeds
6

Actions

Shares
Downloads
56
Comments
0
Likes
12

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. HBaseを用いた   グラフDB「Hornet」の設計と運用 株式会社サイバーエージェント   Ameba  Technology  Laboratory   鈴木 俊裕   梅田 永介
  • 2. 2 株式会社サイバーエージェント 自己紹介 •  鈴木俊裕(すずき  としひろ) •  ソフトウェアエンジニア •  Ameba  Technology  Laboratory •  Hadoopログ解析基盤 •  HBaseを用いた基盤システム •  最近の興味:Scala,  Go,  NewSQL •  Twitter  @brfrn169
  • 3. 3 株式会社サイバーエージェント 自己紹介 •  梅田永介(うめだ  えいすけ) •  ソフトウェアエンジニア •  Ameba  Technology  Laboratory •  HBaseを用いた基盤システム •  趣味:料理
  • 4. 4 株式会社サイバーエージェント 今日話すこと •  前半(鈴木) •  Hornetについて •  HBaseについて •  HBaseアプリケーション設計のセオリー •  Hornetの設計 •  後半(梅田) •  Hornetの運用 •  Zookeeperを用いたロック
  • 5. Hornetについて
  • 6. 6 株式会社サイバーエージェント Hornetとは •  HBaseをバックエンドDBとしたグラフ構造を格納するデータベース •  弊社のHBaseチームで開発 •  現在、公開はしていないが、OSS化に向けて動いているところ
  • 7. 7 Hornetのデータモデル 株式会社サイバーエージェント •  プロパティグラフ A B C ノード リレーションシップ (方向がある) follow follow name Toshihiro age 30 ノードの プロパティ name Ichiro age 30 name Masahiro age 28 date 2014-07-08 favorite true date 2013-11-10 favorite false リレーションシップの プロパティ ノードID リレーションシップのtype
  • 8. 8 株式会社サイバーエージェント なぜHBaseを選択したか •  弊社では、MySQL  +  Sharding  (+  MHA)の構成がスタンダード •  シャードの管理が大変 •  最初から分散を考慮したデータベース •  既にログ解析基盤にHadoop/HBaseを使っていた •  可用性や、パフォーマンスの検証をしてみて十分な性能を示した
  • 9. 9 株式会社サイバーエージェント 現在のHornet •  「Ameba」のスマートフォン向けプラットフォーム内のグラフ構造を保持し ている
  • 10. 10 株式会社サイバーエージェント 現在のHornetの規模感 •  データ規模 •  約100億  ノード •  約600億  リレーションシップ •  アクセス規模 •  ピーク帯で分間6Mアクセス •  平均レイテンシは10ms以下
  • 11. HBaseについて
  • 12. 12 株式会社サイバーエージェント HBaseとは •  Googleの分散データストアである「Bigtable」のオープンソースクローン •  HDFS(Hadoop  Distributed  File  System)上で動作 •  高可用性 •  高パフォーマンス(特に書き込み) •  スケーラブル
  • 13. 13 株式会社サイバーエージェント HBaseのシステム構成 •  マスタ型(<=>  P2P型) •  MasterとRegionServerの2種類のプロセスが存在する •  Master •  RegionServerの管理やRegionのアサインなど •  RegionServer •  クライアントと実際にデータのやり取り •  障害検知や各プロセス間のコーディネーションをZookeeper Master RegionServer RegionServer Zookeeper HDFS ・・・RegionServer
  • 14. 14 株式会社サイバーエージェント HBaseのシステム構成 •  HDFS(Hadoop  Distributed  File  System)上に構築されている •  (デフォルトで)レプリカを3つ持つので信頼性が高い •  HBaseの信頼性はHDFSに依存している Master RegionServer RegionServer Zookeeper HDFS ・・・RegionServer
  • 15. 15 •  部分的にRDBに似ている 株式会社サイバーエージェント HBaseのデータモデル ColumnFamily1 ColumnFamily2 Column1 Column2 Column3 Column4 Column5 row1 row2 row3 row4 row5 aaa bbb NULL ccc ddd row6 row7 row8 RowKey (主キー、辞書順で ソートされている) Column Value Table
  • 16. 16 •  でも、ちょっと違う 株式会社サイバーエージェント HBaseのデータモデル ColumnFamily1 ColumnFamily2 Column1 Column2 Column3 Column4 Column5 row1 row2 row3 row4 row5 aaa bbb NULL ccc ddd row6 row7 row8 ColumnはColumnFamily によってグルーピング ▼ ▼ ▼ ▼ fff ggg hhh iii jjj Valueは 複数バージョンを持つ
  • 17. 17 •  でも、ちょっと違う 株式会社サイバーエージェント HBaseのデータモデル ColumnFamily1 ColumnFamily2 Column1 Column2 Column3 Column4 Column5 row1 row2 row3 row4 row5 aaa bbb ccc ddd eee row6 row7 row8 ColumnFamilyは 定義する必要がある
  • 18. 18 •  でも、ちょっと違う 株式会社サイバーエージェント HBaseのデータモデル ColumnFamily1 ColumnFamily2 Column1 Column2 Column3 Column4 Column5 row1 row2 row3 row4 row5 aaa bbb ccc ddd eee row6 row7 row8
  • 19. 19 •  でも、ちょっと違う 株式会社サイバーエージェント HBaseのデータモデル ColumnFamily1 ColumnFamily2 Column1 Column2 Column3 Column4 Column5 Column6 row1 row2 row3 row4 row5 aaa bbb ccc ddd eee fff row6 row7 row8 Columnは後からいくらでも 増やすことができる
  • 20. 20 •  でも、ちょっと違う 株式会社サイバーエージェント HBaseのデータモデル ColumnFamily1 ColumnFamily2 Column1 Column2 Column3 Column4 Column5 Column6 Column7 row1 row2 row3 row4 row5 aaa bbb ccc ddd eee fff ggg row6 row7 row8 Columnは後からいくらでも 増やすことができる
  • 21. 21 •  データの分割について 株式会社サイバーエージェント HBaseのデータモデル ColumnFamily1 ColumnFamily2 Column1 Column2 Column3 Column4 Column5 row1 row2 row3 row4 row5 row6 row7 row8
  • 22. 22 •  データの分割について 株式会社サイバーエージェント HBaseのデータモデル ColumnFamily1 ColumnFamily2 Column1 Column2 Column3 Column4 Column5 row1 row2 row3 row4 row5 row6 row7 row8 RowKeyの範囲で Regionに分割される Region1 Region2
  • 23. 23 •  Regionは各RegionServerに配置される •  1つのRegionが複数のRegionServerに配置されることはない •  Regionをデータ量や負荷が均等になるようにRegionServerに配置すること で、ロードバランスが可能 •  Rowの更新処理はアトミックに行われる •  ColumnFamily間の処理もアトミックになる •  CASやIncrementが可能 株式会社サイバーエージェント HBaseのデータモデル RegionServer 1 RegionServer 2 Region  1 Region  3 Region  5Region  6 RegionServer 3 Region  2 Region  8 Region  4 Region  7
  • 24. 24 •  ColumunFamilyとデータファイル 株式会社サイバーエージェント HBaseのデータモデル ColumnFamily1 Column1 Column2 row1 row2 row3 row4 ColumnFamily2 Column3 Column4 Column5
  • 25. 25 •  ColumunFamilyとデータファイル 株式会社サイバーエージェント HBaseのデータモデル ColumnFamily1 Column1 Column2 row1 row2 row3 row4 ColumnFamily2 Column3 Column4 Column5 ファイル1 ファイル2 ColumnFamily毎に データファイルが分かれる Column(ColumnFamily)指向 データフォーマット
  • 26. 26 株式会社サイバーエージェント HBaseのデータモデル •  各データファイルの実際の構造 row1 ColumnFamily1 Column1 100 aaa RowKey ColumnFamily Column Timestamp value row1 ColumnFamily1 Column2 200 bbb row2 ColumnFamily1 Column1 140 111 row2 ColumnFamily1 Column2 300 rrr row3 ColumnFamily1 Column1 400 fff row5 ColumnFamily1 Column1 500 333 row5 ColumnFamily1 Column1 130 uuu row5 ColumnFamily1 Column2 300 555 RowKey  +  ColumnFamily  +  Column  +  Timestamp(降順) でソートされている 1つのエントリを KeyValueと呼ぶ
  • 27. 27 株式会社サイバーエージェント HBaseのデータモデル •  各データファイルの実際の構造 row1 ColumnFamily1 Column1 100 aaa RowKey ColumnFamily Column Timestamp value row1 ColumnFamily1 Column2 200 bbb row2 ColumnFamily1 Column1 140 111 row2 ColumnFamily1 Column2 300 rrr row3 ColumnFamily1 Column1 400 fff row5 ColumnFamily1 Column1 500 333 row5 ColumnFamily1 Column1 130 uuu row5 ColumnFamily1 Column2 300 555 複数Columnを持っているRowは、 複数KeyValueになる
  • 28. 28 株式会社サイバーエージェント HBaseのデータモデル •  各データファイルの実際の構造 row1 ColumnFamily1 Column1 100 aaa RowKey ColumnFamily Column Timestamp value row1 ColumnFamily1 Column2 200 bbb row2 ColumnFamily1 Column1 140 111 row2 ColumnFamily1 Column2 300 rrr row3 ColumnFamily1 Column1 400 fff row5 ColumnFamily1 Column1 500 333 row5 ColumnFamily1 Column1 130 uuu row5 ColumnFamily1 Column2 300 555 ValueがNULLの場合は、 KeyValueが保存されない
  • 29. 29 株式会社サイバーエージェント HBaseのデータモデル •  各データファイルの実際の構造 row1 ColumnFamily1 Column1 100 aaa RowKey ColumnFamily Column Timestamp value row1 ColumnFamily1 Column2 200 bbb row2 ColumnFamily1 Column1 140 111 row2 ColumnFamily1 Column2 300 rrr row3 ColumnFamily1 Column1 400 fff row5 ColumnFamily1 Column1 500 333 row5 ColumnFamily1 Column1 130 uuu row5 ColumnFamily1 Column2 300 555 複数バージョンを持っている場合は、 Timestampが違うKeyValueになる
  • 30. 30 株式会社サイバーエージェント HBaseのAPI •  更新系 •  Put •  Row、Columnの追加・更新 •  バージョン(Timestamp)を指定してPutすることもできる •  Delete •  Row全体、指定のColumn、バージョンを削除 •  Increment •  Valueをインクリメント •  Append •  Valueに末尾にデータを追加する •  Row内に閉じた更新系の処理はアトミックに処理することができる
  • 31. 31 株式会社サイバーエージェント HBaseのAPI •  参照系 •  Get •  単一のRowを取得 •  Scan •  複数RowをRowKeyの範囲を指定してスキャン •  取得するColumnFamilyやColumnの指定やバージョンの指定ができる •  より細かい条件を指定するためのフィルタも指定することができる
  • 32. 32 株式会社サイバーエージェント HBaseのAPI •  その他 •  CAS(Compare  And  Swap)系 •  期待する現在のValueを指定し、その値と一致した場合にPut,  Delete •  Row内に閉じたもののみ •  Batch •  複数のGetやPut、DeleteやIncrementなどを一度に投げることができる
  • 33. HBaseアプリケーション設計のセオリー
  • 34. 34 株式会社サイバーエージェント HBaseアプリケーション設計の考え方 •  RDBの設計は、対象世界を分析してER図を書いて(概念設計)、それ をもとにリレーショナルモデルを作成し(論理設計)、クエリなどを考慮し てインデックスを定義したりモデルを修正する(物理設計) •  HBaseの設計においても、論理設計まではほぼ同じ •  物理設計をどうするかっていうところが、かなり違う
  • 35. 35 株式会社サイバーエージェント HBaseアプリケーション設計の考え方 •  HBaseの場合、インデックスが限られている •  RowKey,  ColumnFamily+Column,  Timestamp(降順)でソート •  スキーマの工夫が必要 •  検索条件にしたい •  ソートしたい •  Joinもない •  非正規化を前提に考えないといけない •  RDBが自動的にやってくれていたことを、マニュアルにやる必要がある イメージ •  すこし手間がかかるが、スケーラビリティとのトレードオフ ⇒  クエリを中心に設計する必要がある
  • 36. 36 株式会社サイバーエージェント HBaseアプリケーション設計の考え方 •  クエリを中心にデータを設計する •  同じデータでも、検索条件によってスキーマが変わる •  クエリを設計当初にちゃんと考えることが重要 •  同じデータでも、検索条件がいくつかある場合、別のスキーマで重複して持 つ必要がある場合がある •  インデックスをマニュアルに •  データ不整合に気をつけなければならない •  クエリによって非正規化を考えていく •  非正規化は前提 •  データ不整合に気をつけなければならない
  • 37. 37 株式会社サイバーエージェント HBaseのデータモデリング •  Tall-narrow  Table  と  Flat-wide  Table •  Tall-narrow  Table •  Rowが多く、Columnが少ないテーブル •  Scanで取得 •  Flat-wide  Table •  Rowが少なく、Columnが多いテーブル •  Getで取得 Tall-narrow Flat-wide
  • 38. 38 株式会社サイバーエージェント HBaseのデータモデリング •  Tall-narrow  Table  と  Flat-wide  Table •  例)  メールボックス RowKey fam: user1-message1 aaa user1-message2 bbb user1-message3 ccc user1-message4 ddd RowKey fam:message1 fam:message2 fam:message3 fam:message4 user1 aaa bbb ccc ddd Tall-narrow Flat-wide
  • 39. 39 株式会社サイバーエージェント HBaseのデータモデリング •  どこにどのデータをマッピングしても、データ量は変わらない •  例)下のどちらもデータ量が変わらない •  Rowkey=user1-message1,  CoumunFamily=fam,  Column=,  value=aaa •  Rowkey=user1,  CoumunFamily=fam,  Column=message1,  value=aaa user1 fam message1 100 aaa user1-message1 fam 100 aaa KeyValueのイメージ Tall-narrow Table Flat-wide Table データ量は変わらない
  • 40. 40 株式会社サイバーエージェント HBaseのデータモデリング •  Tall-narrow  Table  と  Flat-wide  Table  はどちらのほうが良いのか? •  基本的には  Tall-narrow  Table  が良い •  Regionの分割はRowKeyの範囲で行われるので、Rowが巨大になったら分割する ことができなくなってしまう •  Flat-wide  Tableはいつ使うのか? •  Row内の処理はアトミックに行われるので、それを利用したい場合(簡単なトラン ザクション)
  • 41. 41 株式会社サイバーエージェント その他 •  ロードバランスという視点 •  RowKeyの設計によっては、データや負荷がかたよる可能性がある •  例えば、RowKeyにシーケンシャルIDをマッピングして、順に書き込んでいくと、1つ のRegionに書き込みが集中してしまう可能性がある •  ランダムIDにするか、RowKeyの頭にハッシュを付与するというテクニックもある •  ColumnFamilyをどう使えば良いのか •  ColumnFamily毎にデータファイルが分かれる •  同時に参照されないColumnを別のColumnFamilyに入れておくことで、無駄 なI/Oやフィルタリング処理を削減することができる
  • 42. 42 株式会社サイバーエージェント HBaseアプリケーション設計のセオリー •  時間が限られているのでここまで、、 •  参考までに •  Codezine  連載「初めてのHBase」 •  http://codezine.jp/article/corner/473 •  馬本(オライリージャパン「HBase」)
  • 43. Hornetの設計
  • 44. 44 株式会社サイバーエージェント Hornetの機能(簡略版) •  ノードの作成 •  ノードのプロパティの追加 •  リレーションシップの作成 •  リレーションシップのプロパティの追加 •  隣接ノードの取得 •  2種類のクエリ •  Outgoing •  Incoming •  セカンダリインデックス •  隣接ノードをプロパティの値でソートして取得する A B C follow follow follow name Taro age 30 time 100
  • 45. 45 株式会社サイバーエージェント Hornetのスキーマ(ノード) •  RowKey •  hash(nodeId)  +  nodeId •  ColumnFamily •  “h” •  Column •  “”(空のバイト配列) •  Value •  シリアライズされたプロパティ
  • 46. 46 株式会社サイバーエージェント Hornetのスキーマ(ノード) •  ポイント •  RowKeyの先頭にノードIDのハッシュ値をつけることで、データや負荷の偏り を防ぐことができる •  Valueにはシリアライズしたプロパティを入れている •  Columnにプロパティ名、Valueにプロパティ値を入れる設計も考えられる •  KeyValue数を減らすことでデータ容量を節約している •  このケースでは特に、ColumnFamilyを使う必要がないので、固定で”h”にし ている
  • 47. 47 株式会社サイバーエージェント Hornetのスキーマ(ノード) •  例)  ノードの作成 •  API •  グラフ g.addNode("A");   g.addNode("B"); g.addNode("C"); A B C
  • 48. 48 株式会社サイバーエージェント Hornetのスキーマ(ノード) •  例)  ノードの作成 RowKey ColumnFamily Column value
  • 49. 49 株式会社サイバーエージェント Hornetのスキーマ(ノード) •  例)  ノードの作成 RowKey ColumnFamily Column value hash(“A”)  +  “A” “h” {} hash(“B”)  +  “B” “h” {} hash(“C”)  +  “C” “h” {} ノードIDのハッシュ値 ノードID
  • 50. 50 株式会社サイバーエージェント Hornetのスキーマ(ノード) •  例)  ノードのプロパティ •  API •  グラフ g.node("A").setProperty("name",  "Taro");   g.node("A").setProperty("age",  "30"); A B C name Taro age 30
  • 51. 51 株式会社サイバーエージェント Hornetのスキーマ(ノード) •  例)  ノードのプロパティ RowKey ColumnFamily Column value hash(“A”)  +  “A” “h” {} hash(“B”)  +  “B” “h” {} hash(“C”)  +  “C” “h” {}
  • 52. 52 株式会社サイバーエージェント Hornetのスキーマ(ノード) •  例)  ノードのプロパティ RowKey ColumnFamily Column value hash(“A”)  +  “A” “h” {name:Taro,  age:30} hash(“B”)  +  “B” “h” {} hash(“C”)  +  “C” “h” {} シリアライズされた プロパティ
  • 53. 53 株式会社サイバーエージェント Hornetのスキーマ(リレーションシップ) •  RowKey •  hash(inNodeId)  +  inNodeId  +  “out”+  type  +  outNodeId •  hash(outNodeId)  +  outNodeId  +  “in”+  type  +  inNodeId •  ColumnFamily •  “h” •  Column •  “”(空のバイト配列) •  Value •  シリアライズされたプロパティ
  • 54. 54 株式会社サイバーエージェント Hornetのスキーマ(リレーションシップ) •  ポイント •  Outgoing,  Incomingの2種類の検索条件があるので、1つのリレーションシッ プにつき2本のRowを持つ(非正規化) •  それぞれにシリアライズされたプロパティを入れる •  Tall-narrow  Table
  • 55. 55 株式会社サイバーエージェント Hornetのスキーマ(リレーションシップ) •  例)  リレーションシップの作成 •  API •  グラフ g.node("A").addRelationship("follow",  "B");   g.node("A").addRelationship("follow",  "C");   g.node("B").addRelationship("follow",  "C"); A B C follow follow follow
  • 56. 56 株式会社サイバーエージェント Hornetのスキーマ(リレーションシップ) •  例)  リレーションシップのプロパティ •  AがBをフォロー RowKey Column Family Column value
  • 57. 57 株式会社サイバーエージェント Hornetのスキーマ(リレーションシップ) •  例)  リレーションシップのプロパティ •  AがBをフォロー RowKey Column Family Column value hash(“A”)  +  “A”  +  “follow”  +  “out”  +  “B”   “h” {} hash(“B”)  +  “B”  +  “follow”  +  “in”  +  “A”   “h” {} ノードIDの ハッシュ値 始点ノード ID タイプ 方向 終点ノード ID
  • 58. 58 株式会社サイバーエージェント Hornetのスキーマ(リレーションシップ) •  例)  リレーションシップのプロパティ •  AがCをフォロー RowKey Column Family Column value hash(“A”)  +  “A”  +  “follow”  +  “out”  +  “B”   “h” {} hash(“B”)  +  “B”  +  “follow”  +  “in”  +  “A”   “h” {}
  • 59. 59 株式会社サイバーエージェント Hornetのスキーマ(リレーションシップ) •  例)  リレーションシップのプロパティ •  AがCをフォロー RowKey Column Family Column value hash(“A”)  +  “A”  +  “follow”  +  “out”  +  “B”   “h” {} hash(“A”)  +  “A”  +  “follow”  +  “out”  +  “C”   “h” {} hash(“B”)  +  “B”  +  “follow”  +  “in”  +  “A”   “h” {} hash(“C”)  +  “C”  +  “follow”  +  “in”  +  “A”   “h” {}
  • 60. 60 株式会社サイバーエージェント Hornetのスキーマ(リレーションシップ) •  例)  リレーションシップのプロパティ •  BがCをフォロー RowKey Column Family Column value hash(“A”)  +  “A”  +  “follow”  +  “out”  +  “B”   “h” {} hash(“A”)  +  “A”  +  “follow”  +  “out”  +  “C”   “h” {} hash(“B”)  +  “B”  +  “follow”  +  “in”  +  “A”   “h” {} hash(“C”)  +  “C”  +  “follow”  +  “in”  +  “A”   “h” {}
  • 61. 61 株式会社サイバーエージェント Hornetのスキーマ(リレーションシップ) •  例)  リレーションシップのプロパティ •  BがCをフォロー RowKey Column Family Column value hash(“A”)  +  “A”  +  “follow”  +  “out”  +  “B”   “h” {} hash(“A”)  +  “A”  +  “follow”  +  “out”  +  “C”   “h” {} hash(“B”)  +  “B”  +  “follow”  +  “in”  +  “A”   “h” {} hash(“B”)  +  “B”  +  “follow”  +  “out”  +  “C”   “h” {} hash(“C”)  +  “C”  +  “follow”  +  “in”  +  “A”   “h” {} hash(“C”)  +  “C”  +  “follow”  +  “in”  +  “B”   “h” {}
  • 62. 62 株式会社サイバーエージェント Hornetのスキーマ(リレーションシップ) •  例)  隣接ノードの取得 •  API •  グラフ g.node("A").out("follow");   g.node("C").in("follow");   A B C follow follow follow
  • 63. 63 株式会社サイバーエージェント Hornetのスキーマ(リレーションシップ) •  例)隣接ノードの取得 •  Aのフォロー RowKey Column Family Column value hash(“A”)  +  “A”  +  “follow”  +  “out”  +  “B”   “h” {} hash(“A”)  +  “A”  +  “follow”  +  “out”  +  “C”   “h” {} hash(“B”)  +  “B”  +  “follow”  +  “in”  +  “A”   “h” {} hash(“B”)  +  “B”  +  “follow”  +  “out”  +  “C”   “h” {} hash(“C”)  +  “C”  +  “follow”  +  “in”  +  “A”   “h” {} hash(“C”)  +  “C”  +  “follow”  +  “in”  +  “B”   “h” {}
  • 64. 64 株式会社サイバーエージェント Hornetのスキーマ(リレーションシップ) •  例)隣接ノードの取得 •  Aのフォロー RowKey Column Family Column value hash(“A”)  +  “A”  +  “follow”  +  “out”  +  “B”   “h” {} hash(“A”)  +  “A”  +  “follow”  +  “out”  +  “C”   “h” {} hash(“B”)  +  “B”  +  “follow”  +  “in”  +  “A”   “h” {} hash(“B”)  +  “B”  +  “follow”  +  “out”  +  “C”   “h” {} hash(“C”)  +  “C”  +  “follow”  +  “in”  +  “A”   “h” {} hash(“C”)  +  “C”  +  “follow”  +  “in”  +  “B”   “h” {} 「hash(“A”)  +  “A”  +  “follow”  +  “out”」で プレフィックススキャン フォローの”B”と”C”が取れる
  • 65. 65 株式会社サイバーエージェント Hornetのスキーマ(リレーションシップ) •  例)隣接ノードの取得 •  Cのフォロワー RowKey Column Family Column value hash(“A”)  +  “A”  +  “follow”  +  “out”  +  “B”   “h” {} hash(“A”)  +  “A”  +  “follow”  +  “out”  +  “C”   “h” {} hash(“B”)  +  “B”  +  “follow”  +  “in”  +  “A”   “h” {} hash(“B”)  +  “B”  +  “follow”  +  “out”  +  “C”   “h” {} hash(“C”)  +  “C”  +  “follow”  +  “in”  +  “A”   “h” {} hash(“C”)  +  “C”  +  “follow”  +  “in”  +  “B”   “h” {}
  • 66. 66 株式会社サイバーエージェント Hornetのスキーマ(リレーションシップ) •  例)隣接ノードの取得 •  Cのフォロワー RowKey Column Family Column value hash(“A”)  +  “A”  +  “follow”  +  “out”  +  “B”   “h” {} hash(“A”)  +  “A”  +  “follow”  +  “out”  +  “C”   “h” {} hash(“B”)  +  “B”  +  “follow”  +  “in”  +  “A”   “h” {} hash(“B”)  +  “B”  +  “follow”  +  “out”  +  “C”   “h” {} hash(“C”)  +  “C”  +  “follow”  +  “in”  +  “A”   “h” {} hash(“C”)  +  “C”  +  “follow”  +  “in”  +  “B”   “h” {} 「hash(“C”)  +  “C”  +  “follow”  +  “in”」で プレフィックススキャン フォロワーの”A”と”B”が取れる
  • 67. 67 株式会社サイバーエージェント Hornetのスキーマ(セカンダリインデックス) •  RowKey •  hash(inNodeId)  +  inNodeId  +  “out”+  type  +  <indexed  property  value>  +   outNodeId •  hash(outNodeId)  +  outNodeId  +  “in”+  type  +  <indexed  property  value>   +  inNodeId •  ColumnFamily •  “h” •  Column •  “”(空のバイト配列) •  Value •  シリアライズされたプロパティ
  • 68. 68 株式会社サイバーエージェント Hornetのスキーマ(セカンダリインデックス) •  ポイント •  リレーションシップの作成時に、リレーションシップのRowとは別にセカンダリ インデックスRowを作成する(非正規化) •  基本的にはリレーションシップのスキーマと同じだが、RowKeyの一部にプロ パティの値を入れることで、そのプロパティ値でソートされた状態で格納され る
  • 69. 69 株式会社サイバーエージェント Hornetのスキーマ(セカンダリインデックス) •  例)  隣接ノードの取得(ソート) •  API •  グラフ g.node("A").out("follow")          .sort(asc("time"));   A B C follow follow follow time 200 time 100 time 300
  • 70. 70 株式会社サイバーエージェント Hornetのスキーマ(セカンダリインデックス) •  例)隣接ノードの取得(ソート) RowKey Column Family Column value hash(“A”)  +  “A”  +  “follow”  +  “out”  +  100  +  “C”   “h” {time:100} hash(“A”)  +  “A”  +  “follow”  +  “out”  +  200  +  “B”   “h” {time:200} hash(“B”)  +  “B”  +  “follow”  +  “in”  +  100  +  “A”   “h” {time:200} hash(“B”)  +  “B”  +  “follow”  +  “out”  +  300  +    “C”   “h” {time:300} hash(“C”)  +  “C”  +  “follow”  +  “in”  +  200  +  “A”   “h” {time:100} hash(“C”)  +  “C”  +  “follow”  +  “in”  +  300  +  “B”   “h” {time:300} セカンダリインデックスの プロパティの値
  • 71. 71 株式会社サイバーエージェント Hornetのスキーマ(セカンダリインデックス) •  例)隣接ノードの取得(ソート) •  Aのフォローをtimeの昇順でソート RowKey Column Family Column value hash(“A”)  +  “A”  +  “follow”  +  “out”  +  100  +  “C”   “h” {time:100} hash(“A”)  +  “A”  +  “follow”  +  “out”  +  200  +  “B”   “h” {time:200} hash(“B”)  +  “B”  +  “follow”  +  “in”  +  100  +  “A”   “h” {time:200} hash(“B”)  +  “B”  +  “follow”  +  “out”  +  300  +    “C”   “h” {time:300} hash(“C”)  +  “C”  +  “follow”  +  “in”  +  200  +  “A”   “h” {time:100} hash(“C”)  +  “C”  +  “follow”  +  “in”  +  300  +  “B”   “h” {time:300}
  • 72. 72 株式会社サイバーエージェント Hornetのスキーマ(セカンダリインデックス) •  例)隣接ノードの取得(ソート) •  Aのフォローをtimeの昇順でソート RowKey Column Family Column value hash(“A”)  +  “A”  +  “follow”  +  “out”  +  100  +  “C”   “h” {time:100} hash(“A”)  +  “A”  +  “follow”  +  “out”  +  200  +  “B”   “h” {time:200} hash(“B”)  +  “B”  +  “follow”  +  “in”  +  100  +  “A”   “h” {time:200} hash(“B”)  +  “B”  +  “follow”  +  “out”  +  300  +    “C”   “h” {time:300} hash(“C”)  +  “C”  +  “follow”  +  “in”  +  200  +  “A”   “h” {time:100} hash(“C”)  +  “C”  +  “follow”  +  “in”  +  300  +  “B”   “h” {time:300} 「hash(“A”)  +  “A”  +  “follow”  +  “out”」で プレフィックススキャン フォローの”C”と”B”が取れる (ソートされている)
  • 73. Hornetの運用
  • 74. 74 Hornetの運用 •  システム構成 •  クラスタの管理 •  バックアップ •  障害事例
  • 75. 75 •  HBase  Cluster システム構成 NameNode 8Core  CPU 50GB  RAM hornet Zookeeper 24Core  CPU 64GB  RAM Zookeeper Master JobTracker 24Core  CPU 64GB  RAM DataNode,  TaskTracker,   RegionServer 12Core  CPU Zookeeper Master 24Core  CPU 64GB  RAM Cluster構築当時 はHAがなかったた め、FTサーバを 使っている
  • 76. 76 •  HBase  Cluster システム構成 NameNode hornet ×25台 Zookeeper Zookeeper Master JobTracker DataNode,  TaskTracker,   RegionServer ×約50台 Zookeeper Master
  • 77. 77 •  HBase  Cluster NameNode hornet DataNode,  TaskTracker,   RegionServer Zookeeper Zookeeper Master JobTracker Zookeeper Master CDH4b1 ※HBase0.92.0 システム構成 性能が出ない!
  • 78. 78 •  HBase  Cluster NameNode hornet DataNode,  TaskTracker,   RegionServer Zookeeper Zookeeper Master JobTracker Zookeeper Master CDH4b1 ※HBase0.92.0 CDH3u3 システム構成 Hadoopのコン ポーネントを CDH3u3に差し替 えたところ、性能 が改善
  • 79. 79 •  HBase  Cluster NameNode hornet DataNode,  TaskTracker,   RegionServer Zookeeper Zookeeper Master JobTracker Zookeeper HMaster CDH4b1 ※HBase0.92.0 CDH3u3 システム構成 Master,  RegionServerについては、 そのままでは動かなかったのでリコ ンパイルしている
  • 80. 80 クラスタの管理 •  メジャーコンパクションの管理 •  Regionサイズの管理 •  バランシングの管理 •  ノードの管理 •  モニタリング
  • 81. 81 メジャーコンパクションの管理 •  メジャーコンパクションの概要 •  HBaseは書き込み処理を繰り返すとKeyValueが溜まっていく(データファイルが増え ていく) •  Scan時にKeyValueを大量に読み込むことになり、Scan性能が劣化する •  HBaseでは、メジャーコンパクションと呼ばれる処理を行うことでRegionの全ての データファイルをマージすることができる。 •  データファイルをマージすることにより、読み込み対象のKeyValueが減るため、読 み込み性能が回復する •  24h+20%毎に実行される(デフォルト) •  ただし、高負荷な処理であり、処理中はレスポンスタイムが悪化する
  • 82. 82 メジャーコンパクションの管理 •  メジャーコンパクションの自動実行を無効にし、オフピーク帯にメジャー コンパクションを定期実行 •  HBaseの設定 •  hbase.hregion.majorcompaction  =  false
  • 83. 83 Regionサイズの管理 •  特定のRegionのデータ量が増えていくと、Region間でのデータ量やア クセスの偏りが発生する可能性がある •  この偏りを防ぐために、HBaseはRegionの最大ファイルサイズより大き くなったRegionの分割(※)を自動で行う •  HBaseの設定値 •  hbase.hregion.max.filesize  (デフォルト:1GB  ※0.94では10GB) •  ただし、Regionを分割するとメジャーコンパクションが実行されるため、 計画的に分割しないとピーク帯にメジャーコンパクションが動いてしま う恐れがある ※0.94からはIncreasingToUpperBoundRegionSplitPolicyがデフォルトとなった
  • 84. 84 Regionサイズの管理 •  自動分割を無効にし、オフピーク帯に一定のサイズをこえたRegionを 分割 •  HBaseの設定 •  hbase.hregion.max.filesize  =  107374182400  (100GB)
  • 85. 85 バランシングの管理 •  HBaseでは特定のRegionにアクセスが集中してしまう状態を「Hot   Region(Hot  Spot)」と呼ぶ •  Hot  Regionが発生すると、そのRegionが配置されているRegionServer の負荷が増大するため、同じRegionServerに同居しているRegionにも 悪影響を与える
  • 86. 86 バランシングの管理 •  通常のバランサだと各Regionに均等に分散される(※) ※0.96以降では、StochasticLoadBalancerがデフォルトになっており、負荷に応じて分散されるようになった。 TableA TableA TableB TableB TableB TableC TableC TableC TableA RegionServerA RegionServerB RegionServerC
  • 87. 87 バランシングの管理 •  Hot  Regionができてしまった場合、Hot  Regionと同居するRegionにも 影響が出てしまう RegionServerA RegionServerB RegionServerC TableA TableA TableB TableB TableB TableC TableC TableC TableA 同居している TableBと TableCへのア クセスにも影 響が出てしま う Hot  Region
  • 88. 88 バランシングの管理 •  重要なテーブルのRegionについては、ほかのテーブルのRegionの影響 を避けるため、別のRegionServerに割り当てている TableA TableA TableB TableB TableB TableC TableC TableC TableA RegionServerA RegionServerB RegionServerC
  • 89. 89 バランシングの管理 •  Hot  Regionができてしまった場合、Hot  Regionと同居するRegionが限 定されるので、影響を最小限にすることができる RegionServerA RegionServerB RegionServerC TableA TableA TableB TableB TableB TableC TableC TableC TableA Hot  Region TableBに影響 が出る TableCには影 響が出ない
  • 90. 90 ノードの管理 •  ノードのデコミッション •  デコミッション対象のノードが持っているブロックのコピーがクラスタ全体で発生する ため、ディスクIOやNWリソースがコピー作業に多く使われて本来のリクエストの処理 がスローダウンする可能性がある •  デコミッションの影響を最小限にするには、以下の設定値を適切に設定する必要が ある •  CDH3u3の場合 •  dfs.max-repl-streams(デフォルト:2) replicationで転送する最大のブロック数 •  dfs.replication.interval(デフォルト:3) replication間隔(sec)
  • 91. 91 ノードの管理 • ノードのデコミッション •  CDH4以降の場合 •  dfs.namenode.replication.work.multiplier.per.iteration(デフォルト:2) replicatoinの並列転送数 •  dfs.namenode.replication.max-streams(デフォルト:2)  ) replicationで転送する最大のブロック数(replicationの優先度が) •  dfs.namenode.replication.max-streams-hard-limit(デフォルト:4) replicationで転送する最大のブロック数 •  dfs.namenode.replication.interval(デフォルト:3) replication間隔(sec)
  • 92. 92 ノードの管理 dfs.replication.interval  =  3  (デフォルト)でデコミッションした場合 1.9GByte/sec
  • 93. 93 ノードの管理 dfs.replication.interval  =  6  でデコミッションした場合 1.1GByte/sec
  • 94. 94 モニタリング • Ganglia •  cpu_report CPU使用率、IOWAITの確認。                          Hot  Regionが発生するとCPU使用率が跳ね上がる •  network_report NW  I/Oの確認
  • 95. 95 モニタリング • Ganglia •  rpc.metrics.RpcProcessingTime_avg_time サーバサイドでRPCの処理に要した時間 •  rpc.metrics.RpcQueueTime_avg_time RPC呼び出しがキューイングされている時間
  • 96. 96 モニタリング • Ganglia •  hbase.regionserver.fsReadLatency_avg_time ストレージファイルからデータをロードするのに要した平均時間 •  hbase.regionserver.fsWriteLatency_avg_time ストレージファイルにデータを書き込むのに要した平均時間
  • 97. 97 モニタリング • Ganglia •  hbase.regionserver.fsSyncLatency_avg_time WALのレコードをファイルシステムに同期する際の平均時間 •  hbase.regionserver.requests リクエスト数
  • 98. 98 モニタリング • Ganglia •  hbase.regionserver.blockCacheHitRatio ブロックキャッシュのヒット率の確認 •  hbase.regionserver.blockCacheHitCachingRatio ブロックキャッシュのヒット率(setCacheBlocks指定の場合)の確認
  • 99. 99 モニタリング • Ganglia •  hbase.regionserver.flushQueueSize 普段は低い。I/O負荷が高くなると増大する •  hbase.regionserver.compactionQueueSize 普段は低い。I/O負荷が高くなると増大する
  • 100. 100 モニタリング •  zabbix •  ログ監視 •  Hot  Regionを早期に発見するため、RegionServerのログ監視を実施 以下のログがRegionServerのログに出力されたら通知 •  responseTooSlow •  responseTooLarge •  operationTooSlow
  • 101. 101 モニタリング •  Regionに対するヘルスチェック •  すべてのRegionに対して15秒に1回Scanを実行 •  応答を返さない、または何れかのRegionでエラーになった場合異常を通知する hornet RegionServerA RegionServerB TableA TableA TableB TableB TableB TableC TableC TableC TableA RegionServerC
  • 102. 102 モニタリング •  各種ログの収集 •  flumeで以下のログをオペレーション用サーバに集約 RegionServerのログ DataNodeのログ gcログ syslog HBase  Cluster オペレーション用サーバ flumeによる転送
  • 103. 103 バックアップ •  HBase0.92.0のレプリケーション機能にはバグが有るため、使えない •  1時間ごとのバックアップ •  1日ごとのスナップショット取得
  • 104. 104 バックアップ 1時間ごとのバックアップ 1.  HBase  ClusterからBackup  ClusterにWAL(Write  Ahead  Log)を転送 HBase  Cluster Backup  Cluster WAL WAL転送 WAL WAL WAL ストレージ
  • 105. 105 バックアップ 1時間ごとのバックアップ 1.  HBase  ClusterからBackup  ClusterにWAL(Write  Ahead  Log)を転送 2.  Backup  ClusterにWALの内容を反映 HBase  Cluster Backup  Cluster WAL WAL転送 WAL WAL反映 WAL WAL WAL ストレージ
  • 106. 106 バックアップ 1時間ごとのバックアップ 1.  HBase  ClusterからBackup  ClusterにWAL(Write  Ahead  Log)を転送 2.  Backup  ClusterにWALの内容を反映 3.  ストレージにWALを転送 HBase  Cluster Backup  Cluster WAL WAL WAL WAL WAL転送 WAL WAL反映 WAL転送 ストレージ
  • 107. 107 バックアップ 1日ごとのスナップショット取得 •  1日1回、Backup  ClusterのHBaseのデータファイルをスナップショット としてストレージにコピー Backup  Cluster スナップショット スナップショット転送 ストレージ
  • 108. 108 障害事例 •  FullGCによるRegionServerダウン •  アプリケーションバグによるHot  Regionの発生 •  Deleteを入れたことによるHot  Regionの発生
  • 109. 109 FullGCによるRegionServerダウン •  事象 •  RegionServerで数十秒のFullGCが発生し、Zookeeperとのセッションがタイムアウ トになってしまったためRegionServerがダウン •  一部サービスがスローダウン •  原因 •  GC(CMS)でpromotion  failedとconcurrent  mode  failureが発生 •  old領域でフラグメンテーションが発生し、old領域にオブジェクトが移動できず、GC のコンパクションにより数十秒のFullGCとなった •  対応 •  自動的なfailoverにより回復。 •  FullGCが発生したRegionServerプロセスの再起動 •  G1GCを検討中
  • 110. 110 アプリケーションバグによるHot  Regionの発生 •  事象 •  特定のRegionServerに対するアクセスがスローダウン •  原因 •  アプリケーション側のバグにより、特定のRowに書き込み・読み込みが集中 •  KeyValueが増え過ぎたため、ScanのCPU負荷が上がった •  対応 •  緊急対応としてメジャーコンパクションを実施したところ、CPU負荷が低下 •  アプリケーションのバグフィックスを実施
  • 111. 111 Deleteを入れたことによるHot  Regionの発生 •  事象 •  Columnの多いRowをDeleteしたところ、複数のRegionServerが応答しなくなった •  原因 •  Columnの多いRowを削除した結果、削除したRowを含むScanに時間がかかるよう になっていた
  • 112. 112 Deleteを入れたことによるHot  Regionの発生 RowKey ColumnFamiy Column KeyType Timestamp value key1 family col Put 100 1 key2 family col1 Put 100 1 key2 family col2 Put 300 2 key2 family col3 Put 200 3 key2 family colxxxxx Put 400 xxxxx 数十億件の Column RegionServer
  • 113. 113 Deleteを入れたことによるHot  Regionの発生 Delete RowKey ColumnFamiy Column KeyType Timestamp value key1 family col Put 100 1 key2 family DeleteFamily 1000 key2 family col1 Put 100 1 key2 family col2 Put 300 2 key2 family col3 Put 200 3 key2 family colxxxxx Put 400 xxxxx RegionServer
  • 114. 114 Deleteを入れたことによるHot  Regionの発生 削除された Rowを含む Scan RowKey ColumnFamiy Column KeyType Timestamp value key1 family col Put 100 1 key2 family DeleteFamily 1000 key2 family col1 Put 100 1 key2 family col2 Put 300 2 key2 family col3 Put 200 3 key2 family colxxxxx Put 400 xxxxx RegionServer
  • 115. 115 Deleteを入れたことによるHot  Regionの発生 削除された Rowを含む Scan 数十億件の Columnに対 して削除さ れているか の判定が必 要となる RowKey ColumnFamiy Column KeyType Timestamp value key1 family col Put 100 1 key2 family DeleteFamily 1000 key2 family col1 Put 100 1 key2 family col2 Put 300 2 key2 family col3 Put 200 3 key2 family colxxxxx Put 400 xxxxx RegionServer
  • 116. 116 Deleteを入れたことによるHot  Regionの発生 •  対応 •  メジャーコンパクションを実施 •  Columnの多いRowを作る場合は注意する(なるべく作らない) RowKey ColumnFamiy Column KeyType Timestamp value key1 family col Put 100 1 数十億件のColumnを参照す る必要がなくなったので Scan速度が改善 RegionServer
  • 117. Zookeeperを用いたロック機能
  • 118. 118 Zookeeperとは 分散アプリケーションのためのコーディネーションサービス 一般的な用途としては以下が挙げられる •  ロック •  バリア •  キュー •  2相コミット •  リーダー選挙
  • 119. 119 Zookeeperについて アンサンブル •  アンサンブルと呼ばれるクラスタ上で動作する •  アンサンブルの過半数が動作している限り、サービスは利用可能 •  データはレプリケートされる •  アンサンブル中のメンバからリーダーと呼ばれるメンバを選出する •  リーダーはメンバ間の協調動作をコントロールする Server Server Server Server Server リーダー
  • 120. 120 Zookeeperについて データモデル UNIXのファイルシステムと同様に/でパスを区切る / /app1 /app1/p_1 /app2 /app1/p_2 /app1/p_3
  • 121. 121 Hornetにおけるロック機能について HBaseにはトランザクションがないため、代替機能としてロック機能が必 要となった。HornetではZookeeperを用いてロック機能を実現している
  • 122. 122 システム構成 hornet Zookeeper ×7台
  • 123. 123 ロックの規模 •  4万件/分(ピーク時)
  • 124. 124 Zookeeperの運用トピック •  Gangliaでモニタリング •  主にcpu_report、network_reportを確認。 •  定期的なトランザクションログとスナップショットの削除 •  Zookeeperに付属しているzkCleanup.shをオフピーク帯に実行。
  • 125. 125 障害事例 • サーバ増設の手順ミス • リーダが決まらない • リーダのプロセスでFullGC発生
  • 126. 126 サーバ増設の手順ミス •  事象 サーバ3台でアンサンブルを組んでいたZookeeperクラスタ(01,02,03)に、サーバ2台 (04,05)を次の手順で追加しようとしたところ、Zookeeperがサービス不能になった 1.  すべてのサーバの設定ファイルを更新(5台でアンサンブルを組む設定) 2.  03がリーダーの状態で、01,  02,  03を一台ずつ再起動。 3.  04,  05を起動 •  原因 02の再起動時にアンサンブルが過半数割れを起こしたと見なされ、Zookeeperがサー ビス不能状態になった •  対応 3台構成だとオンラインでは増設できないので、最初から5台構成にしておくべき
  • 127. 127 リーダが決まらない •  事象 •  ZookeeperのJVMのメモリの設定を変更するために、Zookeeperを一台ずつ再起 動を実施 •  リーダーの再起動時にZookeeperがサービス不能になり、ロック機能がダウン •  原因 •  ログを確認したところ、リーダーを停止時に、リーダーエレクションが何度も繰り返さ れていた •  スナップショットの容量が大きく、各メンバに転送されるのに時間がかかったためタ イムアウトが起こり、リーダーエレクションが何度も繰り返されていたと思われる。 •  対応 •  データを削除して、全Zookeeperプロセスの再起動
  • 128. 128 リーダのプロセスでFullGC発生 •  事象 Zookeeperへのアクセスが一時的にスローダウン。 一部のZookeeperプロセスでエラーが出続ける。 •  原因 ZookeeperのトランザクションIDがあふれてしまっていた。 (ZOOKEEPER-1277,  Fixバージョン:3.3.3,  3.4.4,  3.5.0,  の事象に酷似) リーダーエレクションがおこり、別のサーバがリーダになるが、ヒープをどんどん食いつぶ していき、やがてFullGCが発生する。 •  対応 リーダーになっているZookeeperプロセスを定期的に再起動し、トランザクションIDをリ セットする必要がある。
  • 129. 129 まとめ •  前半 •  HBaseの概要・モデリングやアプリケーション設計のセオリーについて •  Hornetではどのように設計していったか •  後半 •  HBaesを運用し、得られたノウハウや知見について •  Zookeeperを用いたロック機能を運用し、得られたノウハウや知見について
  • 130. 130 今後の展望 •  HornetのOSS化 •  現在HornetはCDH4b1で運用しているが、CDH5へのアップ グレードを検討中
  • 131. 131 余談ですが •  弊社HBaseチームで、HBaseの書籍を執筆中です。 •  タイトルは「HBase徹底入門(仮)」 •  翔泳社から出版予定 •  乞うご期待!!!!!
  • 132. 132 最後に •  Ameba  Technology  Lab  ではエンジニアを     募集しています! http://www.cyberagent.co.jp/recruit/career/ •  Hadoop  /  HBase/  データマイニング  /  機械学習/  検索   などに  興味がある人はお声がけください。  
  • 133. ご清聴ありがとうございました。