KEMBAR78
Distributed data stores in Hadoop ecosystem | PDF
© 2017 NTT DATA Corporation
10/30/2017
NTT DATA
Masatake Iwasaki
分散データストアとそのビルディングブロック
© 2017 NTT DATA Corporation 2
今回とりあげる分散データストア
HDFS
HBase
Kudu
共通点
⼤量のデータを格納
多数の(汎⽤)サーバでクラスタを構成
マスタースレーブ
効率的なデータアクセスを提供
データ保全性と可⽤性
分散処理FWから使われることを想定
Hadoopエコシステムの分散データストア
© 2017 NTT DATA Corporation 3
I.  HDFSの概要
II.  HBaseの概要
III.  Kuduの概要
IV.  データフォーマット
V.  データの冗⻑化
VI.  ノード間協調とZooKeeper
VII.  Javaとネイティブコード
VIII. まとめ
ToC
© 2017 NTT DATA Corporation 4
HDFSの概要
© 2017 NTT DATA Corporation 5
Hadoopの構成
Hadoop 2
分散ファイルシステム
HDFS
MapReduce
YARN
データを格納
リソース(CPU/メモリ)制御
リソースを利⽤して
様々な処理系を実⾏
データを処理
...
© 2017 NTT DATA Corporation 6
Hadoopは集中管理型の分散処理システム
データを保存する場所(スレーブノード)でデータを処理する
Hadoopの構成
マスターノード
スレーブノード群
実データを格納
分散処理タスクを実⾏
メタデータ, ノード, ジョブ
を管理
© 2017 NTT DATA Corporation 7
Hadoop Distributed File System
ファイルシステムな機能/APIを提供
階層的な名前空間(mkdir, ls)
ファイルの読み書き(open, read, write)
パーミッション等によるアクセス制御
quota
# シンボリックリンクは未サポート
⼀度追加されたが⾊々問題がありdisabledに
ネイティブFS(ext4, xfs, ...)の上に実装
⼤きなファイル(100+MB)の格納に最適化
ファイルを128MBのブロックに分けて管理
HDFSとは何か
© 2017 NTT DATA Corporation 8
NameNode:
メタデータを管理するマスター
どのファイルどのブロックから成るか
どのブロックをどのDataNodeが持つか
DataNode:
データブロック(レプリカ)を保持するスレーブ
NameNodeに対して定期/不定期でレポート送信
クライアント:
まずNameNodeにリクエスト送信
指定されたDataNodeに接続して読み書き
HDFSのアーキテクチャ
© 2017 NTT DATA Corporation 9
データ保全性
データは書き込み時に冗⻑化
ノード故障で冗⻑度が下がったら⾃動回復
ラックを跨ぐようなデータの配置戦略
可⽤性
スレーブ故障は別ノードを使ってリトライ
マスターはactive/standbyなHA構成をサポート
⼀貫性
メタデータを1箇所(NameNode)で管理するため
NameNodeがスケーラビリティのボトルネック
とはいえスレーブ数千台くらいはいける
データローカリティ
データを持ってるノードに処理させる
HDFSの特徴
© 2017 NTT DATA Corporation 10
⾼スループットな読み書き
特にスレーブ上でデータ処理する場合
ランダム書き込みできない
ファイル末尾へのwriteのみ
ランダムreadはできる
HDFSの特徴
© 2017 NTT DATA Corporation 11
HBaseの概要
© 2017 NTT DATA Corporation 12
分散KVS
テーブルを⽔平分割してserve
プリミティブなAPI(put, get, scan)を提供
HDFS上に実装
データファイルとWALをHDFSに置く
Log-Structured Mergeな仕組みで更新に対応
writeはWALとメモリ上(MemStore)にまず反映
溜まったらデータファイル(HFile)に書き出し
readはMemStoreとHFileの両⽅を⾒てmerge
ファイルはときどきcompactionで整理
HBaseとはなにか
© 2017 NTT DATA Corporation 13
Master:
Regionの割り当てを管理する
Region: テーブルを⽔平分割したもの
割り当てはmeta regionに格納
RegionServer:
Regionに対する読み書きを処理
クライアント:
ZooKeeper(後述)からmasterのアドレス取得
MasterからRegionの割り当て情報を取得
必要なRegionServerに接続して読み書き
HBaseのアーキテクチャ
© 2017 NTT DATA Corporation 14
ランダムwrite/readが得意
HDFSの機能を補完
⼀貫性重視
あるregionを担当するRSは(基本的には)1台だけ
落ちたらfailover完了までアクセス不可
サーバサイドの処理フック(coprocessor)が多様
ワークロードに合わせて魔改造可能
運⽤にHadoopのツールセットを使える
例: snapshotをMRジョブで別の場所にコピー
HBaseの特徴
© 2017 NTT DATA Corporation 15
Kuduの概要
© 2017 NTT DATA Corporation 16
分散データストア
テーブルを⽔平分割してserve
プリミティブなAPI(insert, update, scan)を提供
データ型の概念あり: schema on write
Kuduとはなにか
http://kudu.apache.org/overview.htmlhttp://kudu.apache.org/overview.html
© 2017 NTT DATA Corporation 17
Master server:
Tabletの割り当てを管理する
Tablet: テーブルを⽔平分割したもの
割り当てはmaster tabletに格納
Masterがmaster tabletをserve
Tablet server:
Tabletに対する読み書きを処理
Kuduのアーキテクチャ
© 2017 NTT DATA Corporation 18
OLAPなワークロードに最適化
Columnarフォーマット(後述)による効率的なIO
Log-Structured Mergeな仕組みで更新をサポート
writeはWALとメモリ上(MemRowSet)に反映
溜まったらデータファイル(DiskRowSet)に書く
readはMemRowSetとDiskRowSetの両⽅をみる
ファイルはときどきcompactionで整理
Kuduの特徴
© 2017 NTT DATA Corporation 19
SQLエンジンは提供しない
Impala(等)と組みあわえて使う想定
HDFSやZooKeeperに⾮依存
データは(Raftを使って)⾃前で冗⻑化
(Javaではなく)C++で実装
Linux前提
JavaのクライアントAPIはある
HDFS: GFS、HBase: Bigtable
Kudu: Spanner(のデータストア部分)
Kuduの特徴
© 2017 NTT DATA Corporation 20
データフォーマット
© 2017 NTT DATA Corporation 21
フォーマットはない
ブロックファイルの集まりとして管理
チェックサムを⼀緒に(.metaに)保存
512バイト毎にCRC32を計算
HDFSのファイルのチェックサム=
.metaのMD5をまとめたもののMD5
HDFSのデータファイル
$ ls -l data/current/BP-.../current/finalized/subdir0/subdir1
total 254752
-rw-r--r-- 1 test test 134217728 Aug 20 09:35 blk_1073742171
-rw-r--r-- 1 test test 1048583 Aug 20 09:35 blk_1073742171_1347.meta
-rw-r--r-- 1 test test 124620800 Aug 20 09:35 blk_1073742172
-rw-r--r-- 1 test test 973607 Aug 20 09:35 blk_1073742172_1348.meta
© 2017 NTT DATA Corporation 22
データ型の概念なし(Keyもvalueもバイト列)
データはKey順にソートして格納
同じRowを持つ複数のKeyValueをatomicに処理可能
KeyValueのKey: Row + ColumnFamily + Quolifier +α
Rowが同じなら同じregion
MVCC
更新はTimeStampが⼤きいKeyValueの追加
削除はKeyTypeがDELETEなKeyValueの追加
ときどきCompactionで整理
HBaseのKeyValue
http://hbase.apache.org/book.html
© 2017 NTT DATA Corporation 23
ソートされたKeyValue
アクセスを効率化する機能
Index:どのキーがどの辺あるか
Bloom filter: ある値がその領域に含まれるか
HBaseのデータファイル(HFile)
http://hbase.apache.org/book.html
© 2017 NTT DATA Corporation 24
Columnarフォーマット
I/Oの局所化
圧縮効率
Parquetプラスαという趣の専⽤フォーマット
⾼速なlookupのためのインデックス
UPDATE/DELETEを実現するためのdelta store
Kuduのデータファイル
© 2017 NTT DATA Corporation 25
OSSのColumnarフォーマット
Hadoopエコシステム向けのツール群を提供
利⽤例: MapReduceでファイルを作ってHiveで読む
ただし更新するためにはファイルの作り直しが必要
Kuduはそこを補完
Apache Parquet
https://github.com/apache/parquet-format
© 2017 NTT DATA Corporation 26
オンメモリの効率を重視したColumnarフォーマット
プロダクト間での効率よいデータ交換を⽬指す
Apache Arrow
https://blog.cloudera.com/blog/2016/02/introducing-apache-arrow-a-fast-interoperable-in-memory-columnar-data-
structure-standard/
© 2017 NTT DATA Corporation 27
データの冗⻑化
© 2017 NTT DATA Corporation 28
クライアントからNameNodeにブロック割り当てリクエスト
指定されたDataNodeに対して書き込みパイプライン構築
DataNodeからNameNodeにブロック情報を報告
IBR: Incremental Block Report
ブロック書き込み開始時/書き込み完了時/sync要求受信時
レポートを受けてNameNode上のブロック情報が状態遷移
ファイルのcloseが成功した時点で末尾までreadできることを担保
HDFSのデータ冗⻑化
DataNode
NameNode
DataNode
Client
DataNode
write
ack
write
report
1. addBlock
LocatedBlock
2. writeBlock
ack
ack
© 2017 NTT DATA Corporation 29
ブロックを保存するスレーブノードの選び⽅
1つ⽬:
クライアント on スレーブ ならそのノード
そうでなければランダム
2つ⽬:
1つ⽬と別のサーバラックにあるノード
3つ⽬
:2つ⽬と同⼀サーバラックにあるノード
4つ⽬以降:
ランダム(偏り過ぎないように調整)
HDFSのrack awareness
© 2017 NTT DATA Corporation 30
HDFSにおまかせ: データファイルもWALも
WALを書くときはこまめにsyncが必要
HDFSのhflush/hsyncを利⽤
RegionServerはDataNodeと同居が基本
⾃分が書いたファイルはlocalityがある
region割当直後はlocalityがないのが⽋点
HBaseのデータ冗⻑化
slave
RegionServer
DataNode
slave
RegionServer
DataNode
slave
RegionServer
DataNode
© 2017 NTT DATA Corporation 31
Raftアルゴリズムを利⽤
Kuduのデータ冗⻑化
http://kudu.apache.org/overview.html
© 2017 NTT DATA Corporation 32
ノード間協調とZooKeeper
© 2017 NTT DATA Corporation 33
分散AP/MWのための分散データストア
⼩さいデータを冗⻑化して格納
⼀貫性を担保
Zab(ZooKeeper Atomic Broadcast)
ファイルシステム的な名前階層を持つznodeを管理
znodeには⼦ノードを作れる
znodeにはバイト列(~数KB)を格納できる
サーバはznodeのツリー全体をメモリ上に保持
⼤量のデータ(例:WAL)の複製には向かない
Apache ZooKeeper
QuorumPeer
(Follower)
QuorumPeer
(Follower)
QuorumPeer
(Leader)
/apps/app1/p_1
/p_2
/app2/...
© 2017 NTT DATA Corporation 34
クライアントはTCPでつなぎっぱなし
znodeをwatch:
変化があったらcallbackしてもらう
ephemeralノード:
作者のコネクション切断で消えるznode
どのサーバにつなぎにいくかはランダム
エラーなら別ノードにリトライ
同じイベントが同じ順番で発⽣
ZooKeeperのクライアントとAPI
© 2017 NTT DATA Corporation 35
設定/状態の格納
ロック
カウンタ
シーケンス
待ち合わせ
リーダー選出
メンバー管理
ZooKeeperでできること
© 2017 NTT DATA Corporation 36
NameNode HAのautomatic failoverの制御
Activeになるときのロック
Activeなノードがいるかどうかの監視
HDFSがZooKeeperを使うところ
ZKFC
ZK
NameNode
transition
get lock
/hadoop-ha/ActiveStandbyElectorLock
ZKFC
NameNode
ZKFC
NameNode
© 2017 NTT DATA Corporation 37
スレーブの管理
スレーブは⾃⾝のアドレスを登録
znodeが消えたことでダウンを検知
マスターはregionを別ノードに割当
HBaseがZooKeeperを使うところ1
HRegionServer
ZK /hbase/rs/node1,...
/node2,...
/node3,...
HRegionServer HRegionServer
HMaster
© 2017 NTT DATA Corporation 38
マスターの管理
Activeなマスターの排他制御
クライアントがマスターのアドレスを取得
マスターの動的追加/削除にも対応可能
でも、全クライアントがZooKeeperにつなぎにくるのは微妙
現実的な運⽤でマスターを動的追加/削除する必要ないかも
HBaseがZooKeeperを使うところ2
HMaster
ZK
/hbase/master
HMaster HMaster
Client
© 2017 NTT DATA Corporation 39
使い⽅によっては
ZooKeeperがボトルネックになる
逆に複雑になる
バックアップとリカバリ
ZKクラスタダウン => サービスダウン
これは意外と問題ではないかも
ZooKeeperを使っていたけど、やめた例
Kafkaのサーバアドレス取得とoffset管理
Stormのtask heartbeat
HBaseのリージョン割り当て
ZooKeeperの落とし⽳
© 2017 NTT DATA Corporation 40
メタデータの更新ログ(edits)を冗⻑化するサービス
Active NN: JNのquorumにeditsを送信
Standby NN: editsを受信してreplay
ZooKeeperはlog replicationに向かない
HDFSに特化した実装を⾃前で作った
受けとったeditsをメモリ上で管理不要
writerはactive NNだけ: leader election不要
データを複製する部分のアルゴリズムはRaftとだいたい同じ
この仕組みの開発者 = Kuduの開発者
JournalNode in NameNode HA
JournalNode
NameNode
(Active)
JournalNode
NameNode
(Standby)
JournalNode
journal getJournal
© 2017 NTT DATA Corporation 41
ログを冗⻑化するためのプロダクト
元々はHDFSのedits⽤を想定して開発
結果的にHDFSでは(あまり)使われず3.0.0でremoved
Apache Pulsar(incubating)のバックエンドになった
Apache BookKeeper
https://bookkeeper.apache.org/distributedlog/technical-review/2016/09/19/kafka-vs-distributedlog.html
© 2017 NTT DATA Corporation 42
ない
スレーブの管理: マスターにRPCでheartbeat
マスターのアドレス: 静的な設定
マスターの排他制御: Raftのleader election
WALの複製のために作ったRaft実装を活⽤
KuduがZooKeeperを使うところ
http://kudu.apache.org/overview.html
© 2017 NTT DATA Corporation 43
Javaとネイティブコード
© 2017 NTT DATA Corporation 44
開発や運⽤のためのツールが豊富
技術者が多い
安定した実⾏環境(JVM)
いろいろな環境で動く
メモリ管理してくれる
Javaのよいところ
© 2017 NTT DATA Corporation 45
逆に特定PFのみの機能は提供しない
データストアなので性能の追求も必要
=> Cで書いてJNIで呼び出せばよい
いろいろな環境で動くけど
public class DomainSocket implements Closeable {
static {
if (SystemUtils.IS_OS_WINDOWS) {
loadingFailureReason = "UNIX Domain sockets are not available on Windows.";
} else if (!NativeCodeLoader.isNativeCodeLoaded()) {
loadingFailureReason = "libhadoop cannot be loaded.";
} else {
JNIEXPORT void JNICALL
Java_org_apache_hadoop_io_nativeio_NativeIO_00024POSIX_posix_1fadvise(
JNIEnv *env, jclass clazz,
jobject fd_object, jlong offset, jlong len, jint flags)
{
#ifndef HAVE_POSIX_FADVISE
THROW(env, "java/lang/UnsupportedOperationException",
"fadvise support not available");
#else
...
if ((err = posix_fadvise(fd, (off_t)offset, (off_t)len, flags))) {
#ifdef __FreeBSD__
throw_ioe(env, errno);
#else
throw_ioe(env, err);
#endif
© 2017 NTT DATA Corporation 46
mmap, munmap, mlock
特定のブロックデータをキャッシュにキープ
posix_fadvise
キャッシュ上にいなくてよいファイル/領域を指定
もうすぐ必要な領域を先読み
sync_file_range
こまめなsync: writeレイテンシのスパイクを消す
sendmsg, recevmsg
clientがDNからopen済みfdをもらって直接read
結局⼀番おすすめなのはLinux
初めからLinux前提でよいという気持ちは分かる
HDFSのネイティブコード利⽤例
© 2017 NTT DATA Corporation 47
CRC32Cの計算
HDFSのネイティブコード利⽤例
while (likely(counter)) {
__asm__ __volatile__(
"crc32q (%7), %0;nt"
"crc32q (%7,%6,1), %1;nt"
"crc32q (%7,%6,2), %2;nt"
: "=r"(c1), "=r"(c2), "=r"(c3)
: "0"(c1), "1"(c2), "2"(c3), "r"(block_size), "r"(data)
);
data++;
counter--;
}
...
bdata = (uint8_t*)data;
while (likely(remainder)) {
__asm__ __volatile__(
"crc32b (%7), %0;nt"
"crc32b (%7,%6,1), %1;nt"
"crc32b (%7,%6,2), %2;nt"
: "=r"(c1), "=r"(c2), "=r"(c3)
: "0"(c1), "1"(c2), "2"(c3), "r"(block_size), "r"(bdata)
);
bdata++;
remainder--;
© 2017 NTT DATA Corporation 48
Cで実装している部分はほぼない
I/OはHDFSにお任せなため
メモリ管理は課題
GCのオーバーヘッド
ヒープサイズの上限
オフヒープ: ByteBuffer#allocateDirect
⾃分でメモリ管理するなら初めからC++で書く
という気持ちは分かる気がしなくもない
HBaseの場合
© 2017 NTT DATA Corporation 49
まとめ
© 2017 NTT DATA Corporation 50
APIとRPC
ProtocolBuffers
タイムアウトとリトライ
REST API
セキュリティ
Kerberos
SASL
Delegation token
運⽤ツール
CLI, shell
Web UI, REST API
logging, metrics
Dependency management
今回とりあげなかった話題
© 2017 NTT DATA Corporation 51
現実的な運⽤に耐えるソフトウェア
多くのパーツが必要
安定するまで時間がかかる
HDFSやHBaseはそれなりの時間をかけてきた
Kuduもそこで得た知⾒を活かしている
HDFS, HBase, Kudu
異なるワークロードに最適化
GFS, Bigtable, Spanner
NoSQLの勃興とSQLへの回帰
アーキテクチャの試⾏錯誤
OSSで中が⾒えるとうれしい
まとめ
© 2017 NTT DATA Corporation

Distributed data stores in Hadoop ecosystem

  • 1.
    © 2017 NTTDATA Corporation 10/30/2017 NTT DATA Masatake Iwasaki 分散データストアとそのビルディングブロック
  • 2.
    © 2017 NTTDATA Corporation 2 今回とりあげる分散データストア HDFS HBase Kudu 共通点 ⼤量のデータを格納 多数の(汎⽤)サーバでクラスタを構成 マスタースレーブ 効率的なデータアクセスを提供 データ保全性と可⽤性 分散処理FWから使われることを想定 Hadoopエコシステムの分散データストア
  • 3.
    © 2017 NTTDATA Corporation 3 I.  HDFSの概要 II.  HBaseの概要 III.  Kuduの概要 IV.  データフォーマット V.  データの冗⻑化 VI.  ノード間協調とZooKeeper VII.  Javaとネイティブコード VIII. まとめ ToC
  • 4.
    © 2017 NTTDATA Corporation 4 HDFSの概要
  • 5.
    © 2017 NTTDATA Corporation 5 Hadoopの構成 Hadoop 2 分散ファイルシステム HDFS MapReduce YARN データを格納 リソース(CPU/メモリ)制御 リソースを利⽤して 様々な処理系を実⾏ データを処理 ...
  • 6.
    © 2017 NTTDATA Corporation 6 Hadoopは集中管理型の分散処理システム データを保存する場所(スレーブノード)でデータを処理する Hadoopの構成 マスターノード スレーブノード群 実データを格納 分散処理タスクを実⾏ メタデータ, ノード, ジョブ を管理
  • 7.
    © 2017 NTTDATA Corporation 7 Hadoop Distributed File System ファイルシステムな機能/APIを提供 階層的な名前空間(mkdir, ls) ファイルの読み書き(open, read, write) パーミッション等によるアクセス制御 quota # シンボリックリンクは未サポート ⼀度追加されたが⾊々問題がありdisabledに ネイティブFS(ext4, xfs, ...)の上に実装 ⼤きなファイル(100+MB)の格納に最適化 ファイルを128MBのブロックに分けて管理 HDFSとは何か
  • 8.
    © 2017 NTTDATA Corporation 8 NameNode: メタデータを管理するマスター どのファイルどのブロックから成るか どのブロックをどのDataNodeが持つか DataNode: データブロック(レプリカ)を保持するスレーブ NameNodeに対して定期/不定期でレポート送信 クライアント: まずNameNodeにリクエスト送信 指定されたDataNodeに接続して読み書き HDFSのアーキテクチャ
  • 9.
    © 2017 NTTDATA Corporation 9 データ保全性 データは書き込み時に冗⻑化 ノード故障で冗⻑度が下がったら⾃動回復 ラックを跨ぐようなデータの配置戦略 可⽤性 スレーブ故障は別ノードを使ってリトライ マスターはactive/standbyなHA構成をサポート ⼀貫性 メタデータを1箇所(NameNode)で管理するため NameNodeがスケーラビリティのボトルネック とはいえスレーブ数千台くらいはいける データローカリティ データを持ってるノードに処理させる HDFSの特徴
  • 10.
    © 2017 NTTDATA Corporation 10 ⾼スループットな読み書き 特にスレーブ上でデータ処理する場合 ランダム書き込みできない ファイル末尾へのwriteのみ ランダムreadはできる HDFSの特徴
  • 11.
    © 2017 NTTDATA Corporation 11 HBaseの概要
  • 12.
    © 2017 NTTDATA Corporation 12 分散KVS テーブルを⽔平分割してserve プリミティブなAPI(put, get, scan)を提供 HDFS上に実装 データファイルとWALをHDFSに置く Log-Structured Mergeな仕組みで更新に対応 writeはWALとメモリ上(MemStore)にまず反映 溜まったらデータファイル(HFile)に書き出し readはMemStoreとHFileの両⽅を⾒てmerge ファイルはときどきcompactionで整理 HBaseとはなにか
  • 13.
    © 2017 NTTDATA Corporation 13 Master: Regionの割り当てを管理する Region: テーブルを⽔平分割したもの 割り当てはmeta regionに格納 RegionServer: Regionに対する読み書きを処理 クライアント: ZooKeeper(後述)からmasterのアドレス取得 MasterからRegionの割り当て情報を取得 必要なRegionServerに接続して読み書き HBaseのアーキテクチャ
  • 14.
    © 2017 NTTDATA Corporation 14 ランダムwrite/readが得意 HDFSの機能を補完 ⼀貫性重視 あるregionを担当するRSは(基本的には)1台だけ 落ちたらfailover完了までアクセス不可 サーバサイドの処理フック(coprocessor)が多様 ワークロードに合わせて魔改造可能 運⽤にHadoopのツールセットを使える 例: snapshotをMRジョブで別の場所にコピー HBaseの特徴
  • 15.
    © 2017 NTTDATA Corporation 15 Kuduの概要
  • 16.
    © 2017 NTTDATA Corporation 16 分散データストア テーブルを⽔平分割してserve プリミティブなAPI(insert, update, scan)を提供 データ型の概念あり: schema on write Kuduとはなにか http://kudu.apache.org/overview.htmlhttp://kudu.apache.org/overview.html
  • 17.
    © 2017 NTTDATA Corporation 17 Master server: Tabletの割り当てを管理する Tablet: テーブルを⽔平分割したもの 割り当てはmaster tabletに格納 Masterがmaster tabletをserve Tablet server: Tabletに対する読み書きを処理 Kuduのアーキテクチャ
  • 18.
    © 2017 NTTDATA Corporation 18 OLAPなワークロードに最適化 Columnarフォーマット(後述)による効率的なIO Log-Structured Mergeな仕組みで更新をサポート writeはWALとメモリ上(MemRowSet)に反映 溜まったらデータファイル(DiskRowSet)に書く readはMemRowSetとDiskRowSetの両⽅をみる ファイルはときどきcompactionで整理 Kuduの特徴
  • 19.
    © 2017 NTTDATA Corporation 19 SQLエンジンは提供しない Impala(等)と組みあわえて使う想定 HDFSやZooKeeperに⾮依存 データは(Raftを使って)⾃前で冗⻑化 (Javaではなく)C++で実装 Linux前提 JavaのクライアントAPIはある HDFS: GFS、HBase: Bigtable Kudu: Spanner(のデータストア部分) Kuduの特徴
  • 20.
    © 2017 NTTDATA Corporation 20 データフォーマット
  • 21.
    © 2017 NTTDATA Corporation 21 フォーマットはない ブロックファイルの集まりとして管理 チェックサムを⼀緒に(.metaに)保存 512バイト毎にCRC32を計算 HDFSのファイルのチェックサム= .metaのMD5をまとめたもののMD5 HDFSのデータファイル $ ls -l data/current/BP-.../current/finalized/subdir0/subdir1 total 254752 -rw-r--r-- 1 test test 134217728 Aug 20 09:35 blk_1073742171 -rw-r--r-- 1 test test 1048583 Aug 20 09:35 blk_1073742171_1347.meta -rw-r--r-- 1 test test 124620800 Aug 20 09:35 blk_1073742172 -rw-r--r-- 1 test test 973607 Aug 20 09:35 blk_1073742172_1348.meta
  • 22.
    © 2017 NTTDATA Corporation 22 データ型の概念なし(Keyもvalueもバイト列) データはKey順にソートして格納 同じRowを持つ複数のKeyValueをatomicに処理可能 KeyValueのKey: Row + ColumnFamily + Quolifier +α Rowが同じなら同じregion MVCC 更新はTimeStampが⼤きいKeyValueの追加 削除はKeyTypeがDELETEなKeyValueの追加 ときどきCompactionで整理 HBaseのKeyValue http://hbase.apache.org/book.html
  • 23.
    © 2017 NTTDATA Corporation 23 ソートされたKeyValue アクセスを効率化する機能 Index:どのキーがどの辺あるか Bloom filter: ある値がその領域に含まれるか HBaseのデータファイル(HFile) http://hbase.apache.org/book.html
  • 24.
    © 2017 NTTDATA Corporation 24 Columnarフォーマット I/Oの局所化 圧縮効率 Parquetプラスαという趣の専⽤フォーマット ⾼速なlookupのためのインデックス UPDATE/DELETEを実現するためのdelta store Kuduのデータファイル
  • 25.
    © 2017 NTTDATA Corporation 25 OSSのColumnarフォーマット Hadoopエコシステム向けのツール群を提供 利⽤例: MapReduceでファイルを作ってHiveで読む ただし更新するためにはファイルの作り直しが必要 Kuduはそこを補完 Apache Parquet https://github.com/apache/parquet-format
  • 26.
    © 2017 NTTDATA Corporation 26 オンメモリの効率を重視したColumnarフォーマット プロダクト間での効率よいデータ交換を⽬指す Apache Arrow https://blog.cloudera.com/blog/2016/02/introducing-apache-arrow-a-fast-interoperable-in-memory-columnar-data- structure-standard/
  • 27.
    © 2017 NTTDATA Corporation 27 データの冗⻑化
  • 28.
    © 2017 NTTDATA Corporation 28 クライアントからNameNodeにブロック割り当てリクエスト 指定されたDataNodeに対して書き込みパイプライン構築 DataNodeからNameNodeにブロック情報を報告 IBR: Incremental Block Report ブロック書き込み開始時/書き込み完了時/sync要求受信時 レポートを受けてNameNode上のブロック情報が状態遷移 ファイルのcloseが成功した時点で末尾までreadできることを担保 HDFSのデータ冗⻑化 DataNode NameNode DataNode Client DataNode write ack write report 1. addBlock LocatedBlock 2. writeBlock ack ack
  • 29.
    © 2017 NTTDATA Corporation 29 ブロックを保存するスレーブノードの選び⽅ 1つ⽬: クライアント on スレーブ ならそのノード そうでなければランダム 2つ⽬: 1つ⽬と別のサーバラックにあるノード 3つ⽬ :2つ⽬と同⼀サーバラックにあるノード 4つ⽬以降: ランダム(偏り過ぎないように調整) HDFSのrack awareness
  • 30.
    © 2017 NTTDATA Corporation 30 HDFSにおまかせ: データファイルもWALも WALを書くときはこまめにsyncが必要 HDFSのhflush/hsyncを利⽤ RegionServerはDataNodeと同居が基本 ⾃分が書いたファイルはlocalityがある region割当直後はlocalityがないのが⽋点 HBaseのデータ冗⻑化 slave RegionServer DataNode slave RegionServer DataNode slave RegionServer DataNode
  • 31.
    © 2017 NTTDATA Corporation 31 Raftアルゴリズムを利⽤ Kuduのデータ冗⻑化 http://kudu.apache.org/overview.html
  • 32.
    © 2017 NTTDATA Corporation 32 ノード間協調とZooKeeper
  • 33.
    © 2017 NTTDATA Corporation 33 分散AP/MWのための分散データストア ⼩さいデータを冗⻑化して格納 ⼀貫性を担保 Zab(ZooKeeper Atomic Broadcast) ファイルシステム的な名前階層を持つznodeを管理 znodeには⼦ノードを作れる znodeにはバイト列(~数KB)を格納できる サーバはznodeのツリー全体をメモリ上に保持 ⼤量のデータ(例:WAL)の複製には向かない Apache ZooKeeper QuorumPeer (Follower) QuorumPeer (Follower) QuorumPeer (Leader) /apps/app1/p_1 /p_2 /app2/...
  • 34.
    © 2017 NTTDATA Corporation 34 クライアントはTCPでつなぎっぱなし znodeをwatch: 変化があったらcallbackしてもらう ephemeralノード: 作者のコネクション切断で消えるznode どのサーバにつなぎにいくかはランダム エラーなら別ノードにリトライ 同じイベントが同じ順番で発⽣ ZooKeeperのクライアントとAPI
  • 35.
    © 2017 NTTDATA Corporation 35 設定/状態の格納 ロック カウンタ シーケンス 待ち合わせ リーダー選出 メンバー管理 ZooKeeperでできること
  • 36.
    © 2017 NTTDATA Corporation 36 NameNode HAのautomatic failoverの制御 Activeになるときのロック Activeなノードがいるかどうかの監視 HDFSがZooKeeperを使うところ ZKFC ZK NameNode transition get lock /hadoop-ha/ActiveStandbyElectorLock ZKFC NameNode ZKFC NameNode
  • 37.
    © 2017 NTTDATA Corporation 37 スレーブの管理 スレーブは⾃⾝のアドレスを登録 znodeが消えたことでダウンを検知 マスターはregionを別ノードに割当 HBaseがZooKeeperを使うところ1 HRegionServer ZK /hbase/rs/node1,... /node2,... /node3,... HRegionServer HRegionServer HMaster
  • 38.
    © 2017 NTTDATA Corporation 38 マスターの管理 Activeなマスターの排他制御 クライアントがマスターのアドレスを取得 マスターの動的追加/削除にも対応可能 でも、全クライアントがZooKeeperにつなぎにくるのは微妙 現実的な運⽤でマスターを動的追加/削除する必要ないかも HBaseがZooKeeperを使うところ2 HMaster ZK /hbase/master HMaster HMaster Client
  • 39.
    © 2017 NTTDATA Corporation 39 使い⽅によっては ZooKeeperがボトルネックになる 逆に複雑になる バックアップとリカバリ ZKクラスタダウン => サービスダウン これは意外と問題ではないかも ZooKeeperを使っていたけど、やめた例 Kafkaのサーバアドレス取得とoffset管理 Stormのtask heartbeat HBaseのリージョン割り当て ZooKeeperの落とし⽳
  • 40.
    © 2017 NTTDATA Corporation 40 メタデータの更新ログ(edits)を冗⻑化するサービス Active NN: JNのquorumにeditsを送信 Standby NN: editsを受信してreplay ZooKeeperはlog replicationに向かない HDFSに特化した実装を⾃前で作った 受けとったeditsをメモリ上で管理不要 writerはactive NNだけ: leader election不要 データを複製する部分のアルゴリズムはRaftとだいたい同じ この仕組みの開発者 = Kuduの開発者 JournalNode in NameNode HA JournalNode NameNode (Active) JournalNode NameNode (Standby) JournalNode journal getJournal
  • 41.
    © 2017 NTTDATA Corporation 41 ログを冗⻑化するためのプロダクト 元々はHDFSのedits⽤を想定して開発 結果的にHDFSでは(あまり)使われず3.0.0でremoved Apache Pulsar(incubating)のバックエンドになった Apache BookKeeper https://bookkeeper.apache.org/distributedlog/technical-review/2016/09/19/kafka-vs-distributedlog.html
  • 42.
    © 2017 NTTDATA Corporation 42 ない スレーブの管理: マスターにRPCでheartbeat マスターのアドレス: 静的な設定 マスターの排他制御: Raftのleader election WALの複製のために作ったRaft実装を活⽤ KuduがZooKeeperを使うところ http://kudu.apache.org/overview.html
  • 43.
    © 2017 NTTDATA Corporation 43 Javaとネイティブコード
  • 44.
    © 2017 NTTDATA Corporation 44 開発や運⽤のためのツールが豊富 技術者が多い 安定した実⾏環境(JVM) いろいろな環境で動く メモリ管理してくれる Javaのよいところ
  • 45.
    © 2017 NTTDATA Corporation 45 逆に特定PFのみの機能は提供しない データストアなので性能の追求も必要 => Cで書いてJNIで呼び出せばよい いろいろな環境で動くけど public class DomainSocket implements Closeable { static { if (SystemUtils.IS_OS_WINDOWS) { loadingFailureReason = "UNIX Domain sockets are not available on Windows."; } else if (!NativeCodeLoader.isNativeCodeLoaded()) { loadingFailureReason = "libhadoop cannot be loaded."; } else { JNIEXPORT void JNICALL Java_org_apache_hadoop_io_nativeio_NativeIO_00024POSIX_posix_1fadvise( JNIEnv *env, jclass clazz, jobject fd_object, jlong offset, jlong len, jint flags) { #ifndef HAVE_POSIX_FADVISE THROW(env, "java/lang/UnsupportedOperationException", "fadvise support not available"); #else ... if ((err = posix_fadvise(fd, (off_t)offset, (off_t)len, flags))) { #ifdef __FreeBSD__ throw_ioe(env, errno); #else throw_ioe(env, err); #endif
  • 46.
    © 2017 NTTDATA Corporation 46 mmap, munmap, mlock 特定のブロックデータをキャッシュにキープ posix_fadvise キャッシュ上にいなくてよいファイル/領域を指定 もうすぐ必要な領域を先読み sync_file_range こまめなsync: writeレイテンシのスパイクを消す sendmsg, recevmsg clientがDNからopen済みfdをもらって直接read 結局⼀番おすすめなのはLinux 初めからLinux前提でよいという気持ちは分かる HDFSのネイティブコード利⽤例
  • 47.
    © 2017 NTTDATA Corporation 47 CRC32Cの計算 HDFSのネイティブコード利⽤例 while (likely(counter)) { __asm__ __volatile__( "crc32q (%7), %0;nt" "crc32q (%7,%6,1), %1;nt" "crc32q (%7,%6,2), %2;nt" : "=r"(c1), "=r"(c2), "=r"(c3) : "0"(c1), "1"(c2), "2"(c3), "r"(block_size), "r"(data) ); data++; counter--; } ... bdata = (uint8_t*)data; while (likely(remainder)) { __asm__ __volatile__( "crc32b (%7), %0;nt" "crc32b (%7,%6,1), %1;nt" "crc32b (%7,%6,2), %2;nt" : "=r"(c1), "=r"(c2), "=r"(c3) : "0"(c1), "1"(c2), "2"(c3), "r"(block_size), "r"(bdata) ); bdata++; remainder--;
  • 48.
    © 2017 NTTDATA Corporation 48 Cで実装している部分はほぼない I/OはHDFSにお任せなため メモリ管理は課題 GCのオーバーヘッド ヒープサイズの上限 オフヒープ: ByteBuffer#allocateDirect ⾃分でメモリ管理するなら初めからC++で書く という気持ちは分かる気がしなくもない HBaseの場合
  • 49.
    © 2017 NTTDATA Corporation 49 まとめ
  • 50.
    © 2017 NTTDATA Corporation 50 APIとRPC ProtocolBuffers タイムアウトとリトライ REST API セキュリティ Kerberos SASL Delegation token 運⽤ツール CLI, shell Web UI, REST API logging, metrics Dependency management 今回とりあげなかった話題
  • 51.
    © 2017 NTTDATA Corporation 51 現実的な運⽤に耐えるソフトウェア 多くのパーツが必要 安定するまで時間がかかる HDFSやHBaseはそれなりの時間をかけてきた Kuduもそこで得た知⾒を活かしている HDFS, HBase, Kudu 異なるワークロードに最適化 GFS, Bigtable, Spanner NoSQLの勃興とSQLへの回帰 アーキテクチャの試⾏錯誤 OSSで中が⾒えるとうれしい まとめ
  • 52.
    © 2017 NTTDATA Corporation