kuduを調べてみた #dogenzakalt

55
道玄坂LT祭り Kuduを調べてみた 株式会社サイバーエージェント 技術本部 秋葉原ラボ 鈴木俊裕

Upload: toshihiro-suzuki

Post on 16-Apr-2017

1.549 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: Kuduを調べてみた #dogenzakalt

道玄坂LT祭り

Kuduを調べてみた株式会社サイバーエージェント

技術本部 秋葉原ラボ鈴木俊裕

Page 2: Kuduを調べてみた #dogenzakalt

自己紹介

● 鈴木俊裕(すずき としひろ)● ソフトウェアエンジニア

● サイバーエージェント 技術本部 秋葉原ラボ○ Hadoopを用いたログ解析基盤○ HBaseを用いた基盤システム

● 最近の興味:Go, NewSQL● Twitter @brfrn169

● 著書「HBase徹底入門」

Page 3: Kuduを調べてみた #dogenzakalt

今日話すこと

● Kuduを調べてみた

○ Kuduについて

○ デモ(時間があれば)

Page 4: Kuduを調べてみた #dogenzakalt

Kuduについて

Page 5: Kuduを調べてみた #dogenzakalt

Kuduとは

● Clouderaが開発したHadoopのエコシステム

● カラムナ(列指向)ストレージエンジン

● オープンソース(Apache インキュベータプロジェクト)

Page 6: Kuduを調べてみた #dogenzakalt

Kuduの位置づけ

● HDFS + Parquet or ORC○ スキャン ◎○ ランダムアクセス ☓

● HBase, Cassandra○ スキャン ☓ or △○ ランダムアクセス ◎

● Kudu○ スキャン ◯○ ランダムアクセス ◯

Page 7: Kuduを調べてみた #dogenzakalt

Kuduを使うと何が嬉しいのか

● スキャンもランダムアクセスも必要なユースケース

○ Kuduがなかった時には複雑なアーキテクチャになりがち

Page 8: Kuduを調べてみた #dogenzakalt

Kuduを使うと何が嬉しいのか

● スキャンもランダムアクセスも必要なユースケース

○ Kuduを使うとシンプルになる

Page 9: Kuduを調べてみた #dogenzakalt

データモデル

● RDBに似ている

○ Tableを事前定義する必要がある(CREATE TABLE)■ 主キーを必ず定義する

■ 有限個のColumnを定義

● 動的にColumnを追加できない

○ Columnは型を持つ(e.g. INT32, STRING)○ 今のところ、セカンダリインデックスやユニークキー制約な

どは実装されてない

Page 10: Kuduを調べてみた #dogenzakalt

データモデル

● HBase等のように値をbytesにしなかった理由

○ 型に特化したエンコードや圧縮が可能だから

● サポートしているエンコード

○ Bitshffule, Run Length, Dictionary, Prefix● サポートしている圧縮

○ LZ4, snappy, zlib

Page 11: Kuduを調べてみた #dogenzakalt

API

● Java, C++, Python(実験段階)

● 書き込みは Insert, Update, Delete○ 主キーを指定しなければならない

○ (HBase等のように)書き込み時にタイムスタンプを指定で

きない

○ 複数RowのトランザクショナルAPIはない

■ 単一Row内の更新はアトミック

Page 12: Kuduを調べてみた #dogenzakalt

API

● 読み込みは Scan のみ

○ Filterの指定はできる

■ Colmunの値と定数の比較(e.g. col = “aaa”)■ 主キーのレンジ(e.g. key >= 100 AND key <= 200)

○ プロジェクション(射影)を指定できる(e.g. SELECT key, col where ...)■ KuduはカラムナストレージエンジンなのでColumnを絞

るとパフォーマンスがよくなる

○ タイムスタンプを指定して point-in-time クエリが可能

Page 13: Kuduを調べてみた #dogenzakalt

インテグレーション

● Impala○ 将来的にはHive, Drill, Prestoも?

● Spark○ DataSourceとしてKuduのテーブルを指定できる

● MapReduce○ KuduTableInputFormat/KuduTableOutputFormat

Page 14: Kuduを調べてみた #dogenzakalt

アーキテクチャ

● データのパーティショニング

○ TableはTabletと呼ばれる単位に分割される

■ Rowは必ず1つのTabletに配置される

■ どのTabletに所属するかは主キーで決まる

○ パーティショニングの方式は2種類

■ key-range-based■ hash-based■ 組み合わせも可能

Page 15: Kuduを調べてみた #dogenzakalt

アーキテクチャ

● データのパーティショニング

○ key-range-based の例

CREATE TABLE customers ( id STRING, name STRING, age INT)DISTRIBUTE BY RANGE(id)SPLIT ROWS(('a'), ('b'), ('c'), .., ('y'), ('z'))TBLPROPERTIES('storage_handler' = 'com.cloudera.kudu.hive.KuduStorageHandler','kudu.table_name' = 'customers','kudu.master_addresses' = 'kudu-master1:7051','kudu.key_columns' = 'id');

Page 16: Kuduを調べてみた #dogenzakalt

アーキテクチャ

● データのパーティショニング

○ hash-based の例

CREATE TABLE customers ( id STRING, name STRING, age INT)DISTRIBUTE BY HASH(id) INTO 16 BUCKETSTBLPROPERTIES('storage_handler' = 'com.cloudera.kudu.hive.KuduStorageHandler','kudu.table_name' = 'customers','kudu.master_addresses' = 'kudu-master1:7051','kudu.key_columns' = 'id');

Page 17: Kuduを調べてみた #dogenzakalt

アーキテクチャ

● データのレプリケーション

○ Raftを採用している

Client

Tabletサーバ

Tabletサーバ Tabletサーバ

Tablet(LEADER)

Tablet(FOLLOWER)

Tablet(FOLLOWER)

WAL

WAL WAL

Page 18: Kuduを調べてみた #dogenzakalt

アーキテクチャ

● データのレプリケーション

○ Raftを採用している

Client

Tabletサーバ

Tabletサーバ Tabletサーバ

Tablet(LEADER)

Tablet(FOLLOWER)

Tablet(FOLLOWER)

WAL

WAL WAL

Write

Page 19: Kuduを調べてみた #dogenzakalt

アーキテクチャ

● データのレプリケーション

○ Raftを採用している

Client

Tabletサーバ

Tabletサーバ Tabletサーバ

Tablet(LEADER)

Tablet(FOLLOWER)

Tablet(FOLLOWER)

WAL

WAL WAL

WALに書き込む

UpdateConsensus() UpdateConsensus()

Page 20: Kuduを調べてみた #dogenzakalt

アーキテクチャ

● データのレプリケーション

○ Raftを採用している

Client

Tabletサーバ

Tabletサーバ Tabletサーバ

Tablet(LEADER)

Tablet(FOLLOWER)

Tablet(FOLLOWER)

WAL

WAL WAL

WALに書き込むWALに書き込む

Page 21: Kuduを調べてみた #dogenzakalt

アーキテクチャ

● データのレプリケーション

○ Raftを採用している

Client

Tabletサーバ

Tabletサーバ Tabletサーバ

Tablet(LEADER)

Tablet(FOLLOWER)

Tablet(FOLLOWER)

WAL

WAL WAL

Success

過半数が成功したら...

Success

Page 22: Kuduを調べてみた #dogenzakalt

アーキテクチャ

● データのレプリケーション

○ Raftを採用している

Client

Tabletサーバ

Tabletサーバ Tabletサーバ

Tablet(LEADER)

Tablet(FOLLOWER)

Tablet(FOLLOWER)

WAL

WAL WAL

Success

Page 23: Kuduを調べてみた #dogenzakalt

アーキテクチャ

● 2つのコンポーネント

○ Master■ メタデータの管理

● Tabletの場所等

■ Tabletサーバのコーディネーション

● 死活監視・フェイルオーバー

○ Tabletサーバ

■ 担当Tabletの実際のデータのやり取り

Page 24: Kuduを調べてみた #dogenzakalt

アーキテクチャ

● Master と Tabletサーバ

Page 25: Kuduを調べてみた #dogenzakalt

まとめ

● データモデルはRDBに近い

● APIはInsert, Update, Delete, Scan● TableはTabletにパーティショニングされる

● パーティション方式はkey-range-based, hash-based, それら

の組み合わせ

● レプリケーションはRaftで● Master + Tabletサーバ 構成

Page 26: Kuduを調べてみた #dogenzakalt

デモ

Page 27: Kuduを調べてみた #dogenzakalt

インストール

● 詳細は省略

● Cloudera Managerを使えば簡単

○ Kudu■ http://getkudu.io/docs/installation.html

○ Impala_Kudu■ http://getkudu.io/docs/kudu_impala_integration.html

● ただし、CPUがSSE4.2やSSSE3をサポートしていないと起動

しない

Page 28: Kuduを調べてみた #dogenzakalt

デモ

● Cloudera Manager● KuduのWebUI● Impalaで操作してみる

○ テーブルを作ってみる

○ データを入れてみる

○ クエリを投げてみる

○ 更新してみる

Page 29: Kuduを調べてみた #dogenzakalt

終わり

● ご清聴ありがとうございました!

Page 30: Kuduを調べてみた #dogenzakalt

資料は作ったけど話せなかった内容

Page 31: Kuduを調べてみた #dogenzakalt

整合性モデル

● デフォルトではExternal Consistencyの保証を提供してない

○ 2つのRowへの書き込みがあった時にクライアント間でど

ちらの更新が先に見えるかわからない

● 2つのConsistency Mode○ CLIENT_PROPEGATED○ COMMIT_WAIT

Page 32: Kuduを調べてみた #dogenzakalt

整合性モデル

● CLIENT_PROPEGATED○ AsyncKuduClient#getLastPropagatedTimestamp()○ AsyncKuduClient#setLastPropagatedTimestamp()

○ 更新した後に propagetedTimestamp を取得して、別クラ

イアントでそれを指定して取得する

Page 33: Kuduを調べてみた #dogenzakalt

整合性モデル

● COMMIT_WAIT○ KuduSession#setExternalConsistencyMode()で

COMMIT_WAITを指定

○ Spannerと同じ手法

○ 確実にcommitが終わっている時間まで待つイメージ

○ ただし、現状だと結構遅い(100-1000ms)■ NTPベースのため?

Page 34: Kuduを調べてみた #dogenzakalt

フェイルオーバ

● Raft○ TabletのレプリカのLEADERがダウンしたらリーダエレク

ションされて、新しいリーダーが選出される

○ FOLLOWERが落ちても問題ない((N-1)/2 まで)○ MasterもメタデータをTableとして管理してるので同様。

TabletのレプリカのLEADERがActive Masterとなる

Page 35: Kuduを調べてみた #dogenzakalt

Tabletストレージ

● Tabletは更にRowSetと呼ばれる単位に分割される

● RowSetは2種類ある

○ MemRowSet○ DiskRowSet

Page 36: Kuduを調べてみた #dogenzakalt

Tabletストレージ

● MemRowSet○ メモリー上にある

○ 各Tabletに1つだけある

○ Insertされたデータはまずここに入る

○ 主キーでソートされた状態で格納される

○ 定期的にディスクにフラッシュされてDiskRowSetになる

Page 37: Kuduを調べてみた #dogenzakalt

Tabletストレージ

● DiskRowSet○ ディスクに配置される

○ 各Column毎に別ファイルとしてディスクに書かれる

○ MemRowSetが主キーでソートされているので、必然的に

DiskRowSetも主キーでソートされる

○ 主キーのインデックスや、Bloom Filterも書き出される

Page 38: Kuduを調べてみた #dogenzakalt

Tabletストレージ

● INSERT時

ClientINSERT

MemRowSet

Tablet

Page 39: Kuduを調べてみた #dogenzakalt

Tabletストレージ

● INSERT時

ClientINSERT

MemRowSet

Tablet

flush

DiskRowSet1

col1 col2 col3

Page 40: Kuduを調べてみた #dogenzakalt

Tabletストレージ

● INSERT時

ClientINSERT

MemRowSet

Tablet

flush

DiskRowSet2

col1 col2 col3

DiskRowSet1

col1 col2 col3

Page 41: Kuduを調べてみた #dogenzakalt

Tabletストレージ

● UPDATE, DELETE時には、更新情報がRowSet毎にある delta store に置かれる

● delta store も2種類ある

○ DeltaMemStore■ メモリ上

■ 更新されたらまずここに更新情報を書く

○ DeltaFile■ DeltaMemStoreがフラッシュされてDeltaFileになる

Page 42: Kuduを調べてみた #dogenzakalt

Tabletストレージ

● UPDATE・DELETE時

MemRowSet

DiskRowSet2

col2 col3

DiskRowSet1

col2 col3

col1

col1

Tablet

Page 43: Kuduを調べてみた #dogenzakalt

Tabletストレージ

● UPDATE・DELETE時

MemRowSet

DiskRowSet2

col2 col3

DiskRowSet1

col2 col3

col1

col1

BloomFilterや主キーのインデックスを使って更新するRowを保持しているRowSetを探す

Tablet

Page 44: Kuduを調べてみた #dogenzakalt

Tabletストレージ

● UPDATE・DELETE時

MemRowSet

DiskRowSet2

col2 col3

DiskRowSet1

col2 col3

col1

col1DeltaMemStore

Rowが見つかったら更新情報を該当RowSetのDeltaMemStoreに入れる

Tablet

Page 45: Kuduを調べてみた #dogenzakalt

Tabletストレージ

● Scan時○ 指定されたColumn毎にScan

■ 主キーのレンジが指定されていたら、RowSetをスキャ

ンする範囲を減らせるか決める

■ RowSetを読みだしながら結果を作っていく

■ 最後にdelta storeに更新情報があるかどうか

Page 46: Kuduを調べてみた #dogenzakalt

Tabletストレージ

● Scan時

MemRowSet

DiskRowSet2

DiskRowSet1

DeltaMemStore

Tablet

col2 col3

col2 col3

col1

col1

Page 47: Kuduを調べてみた #dogenzakalt

Tabletストレージ

● Scan時

MemRowSet

DiskRowSet2

DiskRowSet1

DeltaMemStore

Tablet

col2 col3

col2 col3

col1

col1

指定されたColumnをScan

Page 48: Kuduを調べてみた #dogenzakalt

Tabletストレージ

● Scan時

MemRowSet

DiskRowSet2

DiskRowSet1

DeltaMemStore

Tablet

col2 col3

col2 col3

col1

col1

delta storeと突き合わせる

Page 49: Kuduを調べてみた #dogenzakalt

Tabletストレージ

● Kuduのスキャンとランダムアクセスとのトレードオフ

○ 更新時に既にRowが存在するかを確認する必要があるの

で遅くなる

○ Scan時にRowSet間のマージが必要ないので高速

Page 50: Kuduを調べてみた #dogenzakalt

Tabletストレージ

● Delta Compaction○ delta store が多くなってくると、TabletのScanのが遅くなっ

ていく

○ 定期的にbase dataとdelta sotreをマージする

Page 51: Kuduを調べてみた #dogenzakalt

Tabletストレージ

● Delta CompactionDiskRowSet

col2 col3col1 DeltaMemStoreDeltaFileDeltaFileDeltaFile

Base Data Base Dataからの差分

Page 52: Kuduを調べてみた #dogenzakalt

Tabletストレージ

● Delta CompactionDiskRowSet

col2 col3col1 DeltaMemStoreDeltaFileDeltaFileDeltaFile

DiskRowSet

col2 col3col1 DeltaMemStoreDeltaFile(REDO)

DeltaFile(UNDO)

新しいBase Data

マージされなかったDeltaFile

Base Dataより過去の差分(point-in-timeクエリ用)

Page 53: Kuduを調べてみた #dogenzakalt

Tabletストレージ

● RowSet Compaction○ 削除されたデータの物理削除

○ Key RangeがオーバラップしたDiskRowSetを減らす

■ Rowが含まれてるかもしれないDiskRowSetを減らす

ことができるで効率が上がる

Page 54: Kuduを調べてみた #dogenzakalt

Tabletストレージ

● RowSet Compaction

DiskRowSet1PK=alice PK=joe PK=linda PK=linda

DiskRowSet2PK=bob PK=jon PK=mary PK=zeke

DiskRowSet3PK=carl PK=julie PK=omar PK=zoe

Page 55: Kuduを調べてみた #dogenzakalt

Tabletストレージ

● RowSet Compaction

DiskRowSet1PK=alice PK=joe PK=linda PK=linda

DiskRowSet2PK=bob PK=jon PK=mary PK=zeke

DiskRowSet3PK=carl PK=julie PK=omar PK=zoe

DiskRowSet4PK=alice PK=bob PK=carl PK=joe

DiskRowSet5PK=jon PK=julie PK=linda PK=mary

DiskRowSet6PK=omar PK=zach PK=zeka PK=zoe