cba google app engine 20101208

104
Google をををををををををを ををををををを をを

Upload: kazunori-sato

Post on 28-Nov-2014

1.946 views

Category:

Technology


1 download

DESCRIPTION

 

TRANSCRIPT

Page 1: CBA Google App Engine 20101208

Google を支えるクラウド技術

スティルハウス 佐藤一憲

Page 2: CBA Google App Engine 20101208

アジェンダ

• Google App Engine とは• 分散 KVS と Bigtable • Datastore サービス• Datastore のクエリ

Page 3: CBA Google App Engine 20101208

自己紹介• スティルハウス 佐藤一憲

– twitter: @kazunori_279– ブログ : 「スティルハウスの書庫」– Web: http://www.sth.co.jp/

• コミュニティ活動– appengine ja night– Google API Expert (App Engine)

• 主な業務– 開発 : Adobe Flex/AIR 、 Rails 、 GAE/J– テクニカルライティングや翻訳(ペンネーム吉川和巳)– セミナー講師など

Page 4: CBA Google App Engine 20101208

Google App Engine とは

Page 5: CBA Google App Engine 20101208

Google App Engine とは

• Google App Engine とは– Web アプリホスティングサービス

• 自分のアプリを Google のクラウド上で運用できる

– 2008 年 4 月に Python 版リリース– 2009 年 4 月に Java 版リリース

Page 6: CBA Google App Engine 20101208

Google App Engine とは

• 利用状況( 2010 年 12 月現在)– 10 億 PV /日( mixi と同程度) – 開発者の増加は 10 万人/月– アプリの増加は 15 万件/週

Page 7: CBA Google App Engine 20101208

App Engine のすごいところ

• App Engine のすごいところ– 「 2 ケタ安」の圧倒的な低コスト– どこまでもスケール+高可用性– 開発・運用環境が構築不要

Page 8: CBA Google App Engine 20101208

「 2 ケタ安」の低コスト

• 無償分と有償分– 初期コストはゼロ– 無償分だけでも“ 400 万 PV /月相当を運用可能”

  無償提供分 有償提供分の単価

ストレージ容量 1G バイト $0.15 / 1G バイト ×1か月

ネットワーク帯域(上り)

1G バイト/ 1 日 $0.10 / 1G バイト

ネットワーク帯域(下り)

1G バイト/ 1 日 $0.12 / 1G バイト

CPU 時間 6.5 時間/ 1 日 $0.10 / 1 時間

メール受信件数 2000 件/ 1 日 $0.0001 / 1 件

Page 9: CBA Google App Engine 20101208

「 2 ケタ安」の低コスト

• 「ふにゃもらけ」の事例– Mixi アプリを App Engine で提供– 1 日 600 万 PV 以上(月 1.8 億 PV 相当)– Google からの請求は 1 日 $15 (月額 4 万相

当)• スティルハウス担当事例

– 従来はデータセンターのサーバーを 1 台使用– 400 万件のデータ(約 11GB )を App Engine

移行– 月額 $4– サーバー管理者が不要に

Page 10: CBA Google App Engine 20101208

どこまでもスケール+高可用性• Google のクラスタ環境を簡単に利用できる

– 自動クラスタリングによる負荷分散と高可用性– 負荷状況に応じて App Server を動的に増減 – アプリ間の隔離性を維持、個々のアプリの安全性と

パフォーマンスを確保• Bigtable のスケーラビリティ

– RDB につきもののスケーラビリティ上限がない• テーブル間の結合( join )ができない• トランザクションの整合性保証の範囲を限定している

– App Engine の全アプリのデータは、 1 つの Bigtableテーブルに格納されている

Page 11: CBA Google App Engine 20101208

スケールアウト事例

• ホワイトハウスの "Open For Questions" – 2 日間だけ提供された投票サイト

• その結果を受けてオバマ大統領が記者会見を行った – 10 万件の質問と 360 万件の投票を受け付けた

• ピーク時には毎秒 700 回のクエリを実行した – App Engine を out of box で使用

• Google Moderator のソースをベースに、ホワイトハウス側の開発者がチューンしてデプロイ。 Google 側による特別な作り込み等は行っていない

– App Engine 上の他のアプリには一切影響なし

Page 12: CBA Google App Engine 20101208

スケールアウト事例• "Open For Questions" のトラフィック推移

Page 13: CBA Google App Engine 20101208

開発・運用環境が構築不要

• 統合開発環境を提供 – サーバーの構築や管理が不要。デプロイが容易

• 管理コンソールを提供– ログ管理、管理コンソールや各種ツールを提

Page 14: CBA Google App Engine 20101208

Google App Engine Stack の構成

• Google App Engine Stack の構成

Page 15: CBA Google App Engine 20101208

App Engine Stack の構成要素• App Engine が提供する API

Page 16: CBA Google App Engine 20101208

App Server について• App Server のサンドボックスによる制限

– HTTP リクエスト処理は最大 30 秒まで• App Engine最大の制約のひとつ• 時間のかかる処理は Task Queue で

– ファイルシステムへの書き込み– 外部サーバへのソケット接続

• HTTP リクエスト送信は可能– スレッド生成– ガベージコレクション実行やシステム停止– カスタムクラスローダの利用

Page 17: CBA Google App Engine 20101208

App Server のスケールアウト

• 高負荷時の自動デプロイ – 高負荷状態が一定時間続くと、新しい App

Server が追加され負荷分散し、負荷が低くなると削除される

• アプリが受けられる負荷に上限はあるか? – 同時 30 リクエストの制限

• リクエスト処理時間に応じてスループット上限は変化– それ以上の負荷を扱いたい場合は Google に依頼

する。アプリごとに safety limit を解除できる

Page 18: CBA Google App Engine 20101208

分散 KVS と Bigtable

Page 19: CBA Google App Engine 20101208

分散 KVS とは

• 分散 KVS とは– 「キー」と「値」のペアを保持する分散デー

タストア– 「 Map 」や連想配列のようなもの

Page 20: CBA Google App Engine 20101208

分散 KVS とは• 各社のクラウド向け分散 KVS

– Google• Bigtable

– Amazon Web Service• Amazon Dynamo

– マイクロソフト Azure• Azure Storage Service

– 楽天「 ROMA 」• オープンソース実装

– Facebook による「 Cassandra 」など

Page 21: CBA Google App Engine 20101208

分散 KVS の長所短所

• メリット– スケールアウト構成を取りやすく、スケーラ

ビリティが頭打ちにならない– 高可用性を実現しやすい

• デメリット– データ全体を対象としたトランザクションの

整合性確保が困難– RDB のような高度なクエリやテーブルの結

合( join )が困難

Page 22: CBA Google App Engine 20101208

分散 KVS と RDB

• 分散 KVS と RDB の長所短所

Page 23: CBA Google App Engine 20101208

RDB はスケールしない?• RDB のスケーラビリティ強化手段

– RDB サーバーのスケールアップ• 大型サーバーへの載せ替え

– DB のレプリケーションやシャード(パーティション)分割によるクラスタ構築

– 分散キャッシュ( Oracle RAC やmemcached など)によるクラスタ構築

–→いずれも複雑で高コストなソリューション• 数千万~数億円以上

• RDB のスケールアウトは原理的に困難

Page 24: CBA Google App Engine 20101208

RDB と CAP 定理• CAP 定理

– UC Berkley 大の Eric Brewer教授が 2000 年に発表– Consistency, Availability, Partition

• 分散環境( P )では整合性( C )と可用性( A )間でトレードオフ発生

Page 25: CBA Google App Engine 20101208

BASE トランザクション

• BASE トランザクション– CAP 定理を反映した分散環境での“ゆるい”ト

ランザクション– Basically Available

• 可用性の高さを優先する(悲観排他より楽観排他)

– Soft-State and Eventually Consistent• 状態の一時的な不整合を許容する• 結果的に整合性が確保される仕組みにしておく• 例: DNS 、 Google Wave の OT

Page 26: CBA Google App Engine 20101208

分散 KVS と CAP 定理

• 分散 KVS では– ACID 保証の範囲を制限、可用性を確保

Page 27: CBA Google App Engine 20101208

クラウドによる全体最適化• 分散 KVS の「制約」こそ「クラウドのキモ」

– 整合性が限定、結合できない、 etc...– →アプリが分散環境に対応するための必須条件

• クラウドによる全体最適化– 分散環境に対応した多数のアプリを、きわめて効率

よく集約(コンソリデーション)できる• 独立した OS 、仮想マシン、 DB が不要

• クラウドという巨大単一コンピュータへの融合– 「 2 ケタ安」のコストを実現– 無制限のスケーラビリティと高可用性を安価に提供– メインフレームへの回帰?

Page 28: CBA Google App Engine 20101208

クラウドによる全体最適化

Page 29: CBA Google App Engine 20101208

Bigtable の概要

• Bigtable とは –巨大分散データストア

• リレーショナルモデルに基づく RDB ではない– いわゆる分散 Key-value Store ( KVS )や NoSQL

• 膨大な数の汎用サーバーをつなげてペタバイト規模のデータを扱えるよう設計

• 現在およそ数 PB– 全世界 36 か所以上のデータセンターに配置

された数万台~数 10 万台のサーバーに分散– Google クラウドの「虎の子」

Page 30: CBA Google App Engine 20101208

Bigtable の概要

• Bigtable の歴史 –およそ 7 人年の開発作業を経て、 2005 年 4

月からプロダクション利用を開始 – Google の 70 以上のプロジェクトが利用

• 検索 , GMail, Analytics, Finance, Earth, YouTube, Map など

• Bigtable の特徴– 実用上、無制限のスケーラビリティ– サーバー冗長化による高可用性

Page 31: CBA Google App Engine 20101208

無制限のスケーラビリティ• 実用上はスケーラビリティに上限がない

– テーブルの規模が 100 件でも、数 1000 万件でも、個々の行の読み書きは数 10 ms 程度で完了

– 膨大な数のユーザーが Bigtable に同時にアクセスしても、レスポンスの低下は発生しない

– 一般的な Web アプリケーションの大半では、 RDBサーバーがボトルネックとなってデータ量やアクセス件数の増加にともないレスポンス時間が低下

– Bigtable を使った Web アプリケーションではそれが皆無

Page 32: CBA Google App Engine 20101208

サーバー冗長化による高可用性• Google独自の分散ファイルシステム「 Google

File System ( GFS )」– 異なるラックに設置された 3 台以上のサーバーにコ

ピー– サーバー障害によってデータが失われる可能性はきわめて低い

– いずれか 1 台のサーバーが停止しても他の 2 台のいずれかから同じデータを瞬時に取得

• Bigtable のサービスを構成するサーバー群はすべてが冗長化– SPoF ( Single Point of Failure )を排除– Oracle RAC などのハイエンドの RDB クラスタに匹敵する高可用性

Page 33: CBA Google App Engine 20101208

Bigtable の構成要素

• Bigtable のテーブル – Bigtable のテーブルは、「分散化された多次元ソートマップ」 • 簡単に言うと、ソート済みの Excel表のようなも

の • 個々のセルは履歴を残せる( multidimensional )

Page 34: CBA Google App Engine 20101208

Bigtable の構成要素

• Bigtable のテーブル – テーブルの実体は、巨大な key-value store

• キー:行キー+カラムキー+タイムスタンプ• 行キーは最大 64KB まで(大半は 10~ 100 バイ

ト) – 行キーの辞書順でソートされている – 行単位の CRUD はアトミックに実行

• 複数行にまたがる更新処理は原子性が保証されない

–古い履歴データや削除された行は、自動的にGC

Page 35: CBA Google App Engine 20101208

Bigtable にできること

• Bigtable にできること –キーを指定した行単位の CRUD

• 行単位の ACID 特性が保証される – 2種類のスキャン:

• prefix scan: キーの前方一致検索で複数行を一括取得

• range scan: キーの範囲指定検索で複数行を一括取得

• ソート済みなので高速に実行できる – Bigtable ではカラムの値に基づく検索は一切実

行できない!

Page 36: CBA Google App Engine 20101208

Bigtable にできること

Page 37: CBA Google App Engine 20101208

Bigtable の内部構造• Google の典型的なクラスターノード構成

Page 38: CBA Google App Engine 20101208

Bigtable の内部構造• 個々のノードの基本構成

– Intel ベースの安い PC – Linux OS – Scheduler スレーブ

• Scheduler マスターの指示に従ってノード上に各種サービスをデプロイする

– GFS チャンクサーバー • GFS のチャンク(データ)を保存する

– タブレットサーバー • Bigtable のタブレットを管理する

Page 39: CBA Google App Engine 20101208

Bigtable の内部構造• Bigtable クラスター全体を管理するサー

ビス– Scheduler マスター

• 各ノードに各種サービスをデプロイする – Chubby

• 分散ロックサービス – GFS マスター

• GFS チャンクサーバー群を統括する – Bigtable マスター

• tablet server群を統括する

Page 40: CBA Google App Engine 20101208

Bigtable の内部構造• Bigtable クラスター

– 複数の Bigtable テーブルからなるクラスター • 2006 年 8 月時点では、 388 の Bigtable クラスターと

24,500 のタブレットサーバーが稼働中

• タブレット – Bigtable のテーブルを分割したもの

• テーブルの内容はタブレット単位で各タブレットサーバーに分散保存される

• 1 つのタブレットは 100~ 200MB 程度のデータを保存。それ以上になると分割される

• 1 台のタブレットサーバーは 100 以下のタブレットを保存

Page 41: CBA Google App Engine 20101208

Bigtable の内部構造

• タブレット –復旧が高速

• 1 台がダウンしても、その 100 個のタブレットは他の 100 台のサーバーが保有している

– Bigtable マスターが負荷分散を管理• 高負荷のサーバーからタブレットを移動

Page 42: CBA Google App Engine 20101208

タブレットサーバーのメカニズム

• タブレットサーバーの階層問い合わせ

Page 43: CBA Google App Engine 20101208

タブレットサーバーのメカニズム

• タブレットサーバーの検索 –あるキーのデータを取得するとき

• クライアントはタブレットサーバーの IP アドレスを取得

• DNS ライクな階層問い合わせ –検索の流れ

• ブートストラップとなる Chubby サービスにアクセス

• METADATA タブレットを持つタブレットサーバーの IP アドレスを取得

• METADATA タブレットには、各キーに対応するタブレットサーバーの IP が記録されている

Page 44: CBA Google App Engine 20101208

タブレットサーバーのメカニズム

• タブレットサーバーの検索 – タブレットサーバーの検索には、最大で 3 回

のネットワーク通信が必要• 通常はクライアント側に METADATA タブレット内容がキャッシュされており、クライアントはタブレットサーバーに直接接続できる

Page 45: CBA Google App Engine 20101208

キャッシュ管理とディスクアクセス

• Bigtable のキャッシュ構造

GFS GFS GFS

SSTable (ディスク上のファイル)

memtable (キャッシュ)

minor compaction(ディスクに flush )

major compaction(ゴミファイルを GC )

テーブルへのアクセス コミットログ

Page 46: CBA Google App Engine 20101208

キャッシュ管理とディスクアクセス

• memtable によるキャッシュ管理– memtable は、タブレットにコミットされた更新内容を記録するソート済みのバッファ

– 個々の更新処理はディスク上のコミットログに記録され、更新内容は memtable に記録される

Page 47: CBA Google App Engine 20101208

キャッシュ管理とディスクアクセス

• マイナーコンパクション – memtable がいっぱいになると、その内容が

SSTable にフラッシュされる– ( Oracle の DBWR +チェックポイントと同様)

Page 48: CBA Google App Engine 20101208

キャッシュ管理とディスクアクセス

• SSTable によるディスク保存– SSTable とは、 memtable の内容保存に利用

されるファイルフォーマット – ソート済みのイミュータブル(変更不可)な

マップ( key-value ペア) • イミュータブルなのでファイルアクセス時のロッ

クが不要、同時アクセスを効率的に扱える • コピーオンライトですばやくタブレットを分割で

きる

Page 49: CBA Google App Engine 20101208

キャッシュ管理とディスクアクセス

• メジャーコンパクション–削除されたデータがゴミとして残るので、

マーク&スウィープ GC を実行する • ( PostgreSQL の vacuum と同様)

Page 50: CBA Google App Engine 20101208

GFS の利用

• GFS によるディスクへの書き込み – GFS ( Google File System )とは、 SSTable等のファイル保存に用いられるファイルシステム

– ファイルは必ず 3 台以上のサーバーに書き込み • ローカルの GFS チャンクサーバーが空いていれば、そこに 1 つを書き込み

• 残り 2 つは、離れた場所(少なくとも同じラックではない場所)の GFS チャンクサーバーに書き込み

Page 51: CBA Google App Engine 20101208

GFS の利用• GFS によるデータのレプリケーション

Page 52: CBA Google App Engine 20101208

GFS の利用

• GFS によるディスクへの書き込み – タブレットが移動しない限り、タブレット

サーバーはローカルの GFS チャンクサーバーにアクセス

– 負荷分散のためタブレットが移動すると、データは残したままタブレットのみ移動

– バイナリアップグレード時などに、できるだけローカルに置くようにデータを再配置

Page 53: CBA Google App Engine 20101208

Datastore サービス

Page 54: CBA Google App Engine 20101208

Datastore サービスとは

• App Engine におけるデータ保存サービス– Bigtable 上に実装されている

• Datastore サービスでできること– オブジェクトの CRUD ( Create, Read,

Update, Delete )• エンティティグループ単位で ACID を確保(後述)

– オブジェクトのクエリ(検索)• JDOQL または GQL を使用

Page 55: CBA Google App Engine 20101208

Datastore サービスとは

• JDO API によるオブジェクト保存の例

        PersistenceManager pm = PMF.get().getPersistenceManager();

        Employee e = new Employee("Alfred", "Smith", new Date());

        try {            pm.makePersistent(e);        } finally {            pm.close();        }

Page 56: CBA Google App Engine 20101208

Datastore 用語

• Datastore 用語と既存用語のおおまかな対比– カインド( kind )

• クラス/テーブル– エンティティ( entity )

• オブジェクト/レコード– プロパティ( property )

• フィールド/カラム–キー( key )

• オブジェクト ID /プライマリーキー

Page 57: CBA Google App Engine 20101208

エンティティテーブル

• エンティティテーブルとは – エンティティを保存するテーブル

• App Engine内のすべてのエンティティテーブルが1 つの Bigtable テーブルに格納されている

– 個々のエンティティは、キーで識別• キーの辞書順でソートされている

– 個々のエンティティのプロパティ内容は、すべて Bigtable の 1 つのカラムにシリアライズされて格納 • Protocol Buffer形式で保存される

Page 58: CBA Google App Engine 20101208

キー• キー

– アプリ ID +パス(カインド名+ ID またはキー名)• ID は自動採番

– エンティティグループなし:カインド内でユニーク– エンティティグループあり:エンティティグループ内でユニーク

• キー名はアプリ側で設定– ユニークにする必要がある

– エンティティのキーは変更できない–表記例

• Foo(25)– カインド名+ ID (アプリ ID は表示されない)

• agR0ZXN0cgkLEgNGb28YGQw– protocol buffer+BASE64

Page 59: CBA Google App Engine 20101208

プロパティ

• プロパティ – variable properties

• エンティティごとにプロパティの数や種類を変えられる

• 「プロパティがない」と「プロパティが null 」は区別される

– heterogenous property types • エンティティごとにプロパティの型を変えること

ができる • ( GAE/J でこれを使えるかは不明)

Page 60: CBA Google App Engine 20101208

プロパティの特徴

• Datastore のプロパティの特徴 – multiple value properties (MVP)

• 1 つのプロパティに List や tuple を保存できる– シリアライズして保存される

• クエリの例: name == 'Foo' – List内のいずれか 1 つの値が Foo なら true になる

• 非正規化や設計の最適化に活用できる– 1:N関連の代わりに使う(非正規化)– ジョインテーブルの代わりに使う

– Serializable オブジェクトを格納可能

Page 61: CBA Google App Engine 20101208

Datastore のパフォーマンス• Datastore の性能は、エンティティの数とは無関係

– 保存されているエンティティが 1 件でも、 1000 件でも、 1000万件でも、パフォーマンスに変化はない

• エンティティへの読み書き速度– エンティティの読み込み:平均数 10ms 程度– エンティティの更新:平均 100ms 程度

• 個々のエンティティの更新処理は遅い– アプリケーションのパフォーマンスを決めるのは、更新処理の

実装方法。参照処理は桁違いに速い • 平均数 10ms 程度

– Datastore パフォーマンスの監視ページ• http://code.google.com/status/appengine/

Page 62: CBA Google App Engine 20101208

Datastore サービスの API

• Datastore サービスの API– JDO (Java Data Objects)

• オブジェクト DB の標準 API• ○:ドキュメントと実績が豊富• ×:性能が低い( LLAPI の 1/3 程度)、 Bigtable

と乖離している– JPA (Java Persistence API)

• ORM の標準 API• ×:ドキュメントや実績が少ない

Page 63: CBA Google App Engine 20101208

Datastore サービスの API

• Datastore サービスの API– low-level API ( LLAPI )

• Bigtable にもっとも近い独自 API• ○:性能が高い。 Bigtable を理解しやすい• ×:低レベル。ドキュメントがあまりない

– Slim3 Datastore• ひがやすを氏開発(サードパーティ)• ○:性能が高い。高レベルで使いやすい• ×:実績が少ない

Page 64: CBA Google App Engine 20101208

Datastore サービスの API

Slim3 のパフォーマンステストツールの実行例

Page 65: CBA Google App Engine 20101208

Datastore のクエリ

Page 66: CBA Google App Engine 20101208

クエリ• Datastore のクエリとは

– 複数のエンティティを条件検索できる• 通常、 160~ 200ms 程度で処理

– 条件の記述方法• JDOQL• GQL

Query query = pm.newQuery("select from Employee " +                              "where lastName == lastNameParam " +                              "order by hireDate desc " +                              "parameters String lastNameParam")

    List<Employee> results = (List<Employee>) query.execute("Smith");

Page 67: CBA Google App Engine 20101208

Bigtable のスキャン

Page 68: CBA Google App Engine 20101208

クエリ = インデックス+スキャン

• クエリは「インデックス+スキャン」で実装 – Bigtable はクエリをサポートしていない

• 「値」に基づく検索を実行できない– すべてのクエリは、インデックスとスキャン

の組み合わせで実現• すべてのクエリの検索結果をあらかじめインデッ

クステーブルに並べておく

Page 69: CBA Google App Engine 20101208

3種類のインデックス

• Datastore のインデックスとは– エンティティテーブルとは別のテーブル– 3種類のインデックス

• カインドインデックス • シングルプロパティインデックス • コンポジットインデックス

Page 70: CBA Google App Engine 20101208

カインドインデックス

• カインド名順でソートされたインデックス –あるクラスのすべてのエンティティの一覧を

提供 – 例: Emp でカインドインデックスをスキャン

SELECT * FROM Emp

Page 71: CBA Google App Engine 20101208

カインドインデックス

Page 72: CBA Google App Engine 20101208

シングルプロパティインデックス

• 「エンティティの個々のプロパティ値」でソートされたインデックス– すべてのプロパティについてデフォルトで作成• インデックス不要なプロパティを明示できる

–昇順用と降順用の 2 つが作成される• 1 つのプロパティを条件に検索/ソートで

きる– 例: name == ‘ 佐藤 ' – 例: ORDER BY name – 例: age >= 20 AND age <= 40

Page 73: CBA Google App Engine 20101208

シングルプロパティインデックス

Page 74: CBA Google App Engine 20101208

コンポジットインデックス

• 「複数のプロパティ値の組み合わせ」でソートされたインデックス– 「カスタムインデックス」とも呼ぶ– 自動定義または手動定義

• 複数のプロパティ値で検索できる– 例: dept_key = D1 & age >= 30 & age <= 40– 「 Emp/D1/30 」から「 Emp/D1/40 」まで range スキャン

– 「 < <= > >= 」などの不等号条件( inequality filter )は、ひとつのプロパティに対してのみ利用可能

Page 75: CBA Google App Engine 20101208

コンポジットインデックス

Page 76: CBA Google App Engine 20101208

コンポジットインデックス

• コンポジットインデックスのデメリット – すべてのプロパティ値の順列組み合わせでイ

ンデックス内容が作成されるので、インデックスサイズが膨大になりやすい

– クエリを多用/誤用するとインデックスが増え、更新処理が遅くなる• multi-value property 利用時のインデックス爆発

( index explosion )– 「ここぞ」という用途に限って使うべき

• できるだけコード上でのフィルタリングやソートがよい

Page 77: CBA Google App Engine 20101208

マージジョイン

• マージジョイン( merge join )とは –複数プロパティの等号条件( equality filter )検索をコンポジットインデックスに頼らずに実現• 例: dept_key = D1 & age = 40 & name = ‘ 佐藤’

–複数のシングルプロパティインデックスをマージしながら検索

– "zig-zag" アルゴリズムにより、個々のインデックスを並行してスキャン

Page 78: CBA Google App Engine 20101208

マージジョイン• zig-zag アルゴリズムによるマージジョイ

Page 79: CBA Google App Engine 20101208

Datastore を構成する Bigtable

• Datastore サービスを構成する 7 つの Bigtable– Entities テーブル

• すべてのアプリのエンティティを保持– EntitiesByKind テーブル– EntitiesByPropertyASC テーブル– EntitiesByPropertyDESC テーブル– EntitiesByCompositeProperties テーブル– カスタムインデックステーブル– ID sequences テーブル

Page 80: CBA Google App Engine 20101208

Entities テーブル

• キー– App ID +パス(カインド名+ ID またはキー名)

• プロパティ– プロパティ名+プロパティ値のペア– Protocol Buffer形式

• メタデータ– ルートエンティティのキー、カインド名

• カスタムインデックスデータ– インデックス ID 、祖先エンティティのキー一覧、プ

ロパティ値一覧

Page 81: CBA Google App Engine 20101208

インデックステーブル

• EntitiesByKind テーブル– カインドインデックスを保持– App ID 、カインド名、エンティティキー

• EntitiesByPropertiy ASC/DESC テーブル– シングルプロパティインデックスを保持– App ID 、カインド名、プロパティ名、プロパティ値、

エンティティキー• EntitiesByCompositeProperty テーブル

– コンポジットインデックスを保持– インデックス ID 、 App ID 、カインド名、祖先エン

ティティのキー一覧、プロパティ値一覧、エンティティキー

Page 82: CBA Google App Engine 20101208

その他のテーブル

• カスタムインデックステーブル– コンポジットインデックスの定義を保持

• ID sequences テーブル– ID採番用

Page 83: CBA Google App Engine 20101208

クエリの制限• テーブル間の join ができない

– 非正規化して対処する • 「正規化するな、 JOIN済みのでっかいテーブルを作れ」

select * from PERSON p, ADDRESS a

where a.person_id = p.id and p.age > 25 and a.country = “US”

select from com.example.Person where age > 25 and country = “US”

– 複数のクエリに分割する – multiple value property を使う

Page 84: CBA Google App Engine 20101208

クエリの制限

• 集約関数がない( group by できない) – count() で全件カウントできない

• 毎回対象データをすべて取得してループで集計するのは非効率

• 集約したい値は、集約用のエンティティを用意して集計

– sharding counter: 書き込みが集中しないように複数のエンティティに分散して書き込みし、後で集計

– memcache counter: memcache に書き込みし、 Task Queueでエンティティに保存

Page 85: CBA Google App Engine 20101208

クエリの制限

• 集約関数がない( group by できない) – max()/min() で最大値/最小値を得られない

• 対象プロパティで降順/昇順でソートして、 1 件目の値を得る

Page 86: CBA Google App Engine 20101208

クエリの制限

• 関数やストアドプロシージャはない – toUpper/toLower などがない – 別のプロパティを設け、 toUpper済みの値を入

れる – 書き込み時にできるだけ事前処理を行っておく

ことで、読み込みを高速化できる

Page 87: CBA Google App Engine 20101208

クエリの制限

• クエリの構文の制約 – 全文検索ができない

• LIKE による部分一致検索はできない • 前方一致なら可能: name >= 'a' AND name <= 'a<

UTF-8 コードポイントの最大値> ' • 検索対象の文字列を形態素解析し、ワードごとのイン

デックスを作成する– 2010 年に全文検索対応予定?

Page 88: CBA Google App Engine 20101208

クエリの制限

• そのほかの制約 – OR 、 != が使えない

• 近日対応予定– inequality filters ( < <= >= > )は 1 つのプロ

パティにのみ利用可能– Text型や Blob型のプロパティはインデック

スを作成できない(クエリできない)–あるプロパティで inequality filters を使うと、他のプロパティを最優先にしたソートができない

Page 89: CBA Google App Engine 20101208

Backup Slides

Page 90: CBA Google App Engine 20101208

Datastore のトランザクション

Page 91: CBA Google App Engine 20101208

エンティティグループとは

• エンティティグループとは– エンティティ間の親子関係

• 親( parent )と子( children )• 子のキーに親のキーを埋め込む• 最上位の親はルートエンティ

ティ( root entity )と呼ばれる• 親は変更できない

– デフォルトでは• 個々のエンティティは個別のエ

ンティティグループ(ルートエンティティ)となる

Dept

Emp

1

*

Page 92: CBA Google App Engine 20101208

エンティティグループとキー

/Grandparent:123

/Grandparent:123/Parent:52

/Grandparent:287

/Grandparent:287/Parent:85

/Grandparent:287/Parent:88/Child:47

/Grandparent:287/Parent:88/Child:66

カインド名 ID

親のキー

パス

Page 93: CBA Google App Engine 20101208

エンティティグループとは• エンティティグループの指定方法

– 明示的な指定• 子のキーを、親のエンティティのキーを使って生成する

– 詳しい手順: http://d.hatena.ne.jp/uehaj/20090509/1241856856

– JDO の owned関係• User と Address 間で親子関係を定義• unowned関係はサポートしていない

– エンティティグループが個別になるので ACID を保証できないため

– OOP や RDB の「関連(リレーション)」とは無関係• 関連をそのまま当てはめると問題も(後述)

Page 94: CBA Google App Engine 20101208

エンティティグループとは

• エンティティグループの 2 つの役割– ローカリティを指定する

• パフォーマンスの向上– トランザクション・スコープを指定• ACID の保証

– CAP 定理とエンティティグループ• 特定範囲(ローカリティ)のみを対象に ACID 保証

001 abc002 def

ACID

Page 95: CBA Google App Engine 20101208

ローカリティ

• ローカリティ– エンティティグループのすべてのエンティティ

は、 1 つのサーバーに保存される確率が高い• より高いパフォーマンスが期待できる

– 参考: http://groups.google.com/group/google-appengine-java/browse_thread/thread/fd758c65e14b5c76/e4afc1e348a36a36?show_docid=e4afc1e348a36a36

• 大量のエンティティがある場合は複数サーバーに分割• GFS によりデータは他 2 カ所にバックアップされる• キー順でソートされている

/Grandparent:Alice /Grandparent:Alice/Parent:Sam /Grandparent:Ethel /Grandparent:Ethel/Parent:Jane /Grandparent:Ethel/Parent:Jane/Child:Timmy /Grandparent:Ethel/Parent:Jane/Child:William /Grandparent:Frank

Page 96: CBA Google App Engine 20101208

トランザクション・スコープ

• Datastore のトランザクション・スコープ– トランザクションの開始( begin )と終了

( commit/rollback )を指示する– エンティティ・グループ

• エンティティグループ単位で ACID を保証 – Bigtable は行単位の ACID しか保証しない– Datastore ではエンティティグループ単位での

ACID を保証している• SERIALIZABLE 相当

–異なるエンティティグループ間では保証されない

Page 97: CBA Google App Engine 20101208

Datastore と BASE

• 楽観的排他制御( optimistic lock )を実装 – エンティティグループのルートエンティティに

て、トランザクションの最終コミット時間のタイムスタンプを記録

– トランザクションの開始時に同タイムスタンプを確認

– コミット時にタイムスタンプを再度確認する • タイムスタンプが変化していなければ、更新内容を保存して、タイムスタンプを更新

• タイムスタンプが変化してれば、他のトランザクションとの競合が発生しているので、トランザクションをロールバック

Page 98: CBA Google App Engine 20101208

Datastore と BASE

• 楽観的排他制御( optimistic lock )を実装 – RDB の悲観的排他制御( SELECT FOR

UPDATE )のようにエンティティをロックしない

– スループットは高いが、競合時のリトライが必要• Python 版は 3 回まで自動リトライし、 Java 版は自動

リトライしない

Page 99: CBA Google App Engine 20101208

Datastore と BASE

• リトライの例        for (int i = 0; i < NUM_RETRIES; i++) {            pm.currentTransaction().begin();

            ClubMembers members = pm.getObjectById(ClubMembers.class, "k12345");            members.incrementCounterBy(1);

            try {                pm.currentTransaction().commit();                break;

            } catch (JDOCanRetryException ex) {                if (i == (NUM_RETRIES - 1)) {                     throw ex;                }            }        }

Page 100: CBA Google App Engine 20101208

Datastore と BASE

• 分散トランザクションへの対応 – App Engine では異なるエンティティグループ間

の分散トランザクション(グローバルトランザクション)はサポートされていない

– ただしアプリレベルでの実装例はある • http://code.google.com/intl/ja/events/io/sessions/

DesignDistributedTransactionLayerAppEngine.html • http://code.google.com/intl/ja/events/io/sessions/

TransactionsAcrossDatacenters.html

Page 101: CBA Google App Engine 20101208

トランザクションの注意点

• 1 TX = 1 エンティティグループ– 1 つのトランザクション内では、 1 つのエン

ティティグループの更新処理しか実行できない

–複数のエンティティグループを更新する場合は、個別のトランザクションが必要• =ルートエンティティの更新は個別 TX が必要

• 1 つのエンティティの更新は 1 回まで– 1 つのトランザクション内では、 1 つのエン

ティティを複数回更新できない

Page 102: CBA Google App Engine 20101208

トランザクションの注意点

• トランザクション内で実行可能なクエリの制限– ancestor filter を持つクエリのみ実行可能– コミット前の値は読み込みできない

• READ_COMMITTED 相当• http://code.google.com/intl/ja/appengine/articles/

transaction_isolation.html • http://groups.google.com/group/google-appengine-

java/browse_thread/thread/4a67044929428295

Page 103: CBA Google App Engine 20101208

エンティティグループのボトルネック

• 1 つのエンティティグループにトランザクション負荷を集中させない– エンティティグループの利用は必

要最小限に抑えた方が性能は向上する

– リレーショナルモデルやオブジェクト指向の関連をそのままあてはめると問題が生じることも

Dept

Emp

1

*

Page 104: CBA Google App Engine 20101208

エンティティグループのボトルネック

• 例: 1 つの Department と 1000 の Employee– 1000 の Employee のうち、いずれか 1 つの

Employee しか同時にトランザクションを実行できない

–他はエラーとなりリトライが必要• 例: 1 つの User と数個の Address

– 1 人のユーザーの住所に対して複数のトランザクションが同時実行される頻度は低い

– 負荷は集中しない