Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

超実践 Cloud Spanner 設計講座

7,856 views

Published on

Cloud Spanner の実案件で学んだことを全て紹介します!

Published in: Technology
  • Be the first to comment

超実践 Cloud Spanner 設計講座

  1. 1. 超実践 Cloud Spanner 設計講座 知ってることを全て紹介します! Proprietary Samir Hammoudi aka サミール クラウドカスタマエンジニア JULY 21, 2017
  2. 2. Cloud Spanner とは? Google のマネージド・スケーラブル・リレーショナルデータベース・サービス 完全マネージドのグローバルスケールで DB サービス1 2 3 4 ゾーン間・リージョン間の自動 synchronous レプリケーション スキーマ、ACID トランザクション、SQL Google内部では、既に5年以上の運用経験 (AdWords, Google Play…)
  3. 3. 注意事項:Cloud Spanner ≠ MySQL Cloud Spanner は MySQL の単なる置き換えではない ● スキーマは似てるが、分散データベースのため、MySQLと違う可能性がある ● SQL の SELECT系とDDLは対応済み、DML も対応予定 → 現時点では Mutation オブジェクトを利用して INSERT/UPDATE/DELETE を行う ● Auto-increment がない(Spannerではアンチパターンだから) ● MySQL 互換ではない(Spannerのクライアントライブラリを提供) ● パフォーマンスのプロファイルが違う(Scale-up DB vs Scale-out DB) → 高負荷をかけても Cloud Spanner のレイテンシは安定(Quizletの事例をご参考ください) ● Cloud Spanner では PK の選択がクリティカル ←これ何回言っても足りないので赤にしました! ● FK が存在しない(Spanner では Interleave が FK 相当) MySQL とは似てるところも色々あるが、Cloud Spanner は分散データベースだということを忘れないでね!!
  4. 4. MySQL ではないが... 特に大規模アクセスのあるコンテンツや DB運用に苦労しているサービスに最適! ノードを追加するだけでオートシャードされ、 理論上無限にスケールしつつ、 レイテンシーがより安定 :) 運用も楽 ^_^
  5. 5. 今日のおさらいリスト 1. PK の選択が重要 ←これが1番重要!! 2. なぜテーブルをインターリーブするか? 3. インデックスとインターリーブについて 4. Channels と Sessions 5. ノード追加・削除の際、リシャードがなぜ1〜2sでできるのか? 6. エラーについて 7. 容量に関する上限 8. テーブルが分割(Split)されるロジック 9. 負荷試験は十分長く実行する 10. 負荷試験間はデータベースをDropする 11. TPSの数え方 12. ノード数を縮小するについて 13. グラフの ”Total storage” の意味って? 14. Query Plan Cache ←これも重要!!
  6. 6. PK の選択が重要 ● シーケンシャルな PK を使わないこと → hotspots が発生する ○ auto-increment PK を使わない (even though it doesn’t exist in Cloud Spanner!) ○ 時系列の PK を使わない ● MySQL の auto-increment を使用しているテーブルを Spanner にインポートする場合は: ○ 新しい PK を作り、乱数をオススメします (e.g. UUID). ○ 元の PK から 計算する shard_id を作る (e.g. shard_id = hash(auto-inc_id)). ○ シーケンシャルな PK を使うが、DB に格納する前やクエリーする時はビットを逆にする ● UUID が一番おすすめとしている PK です。 これ重要!
  7. 7. PKを選択する時の注意点 - Hotspot (1/2) ● Hotspot とは、データが Spanner サーバー間にちゃんと分散されない現象 ○ 1つの Spanner サーバーに書き込みが集中して、パフォーマンスが減少 ○ 同じサーバーを利用するサービスにインパクトも可能 ● 現象の理由 ○ 新しく書き込まれるレコードはテーブルの最後に追加されて、同じ Spanner サーバーに格納 される(時系列のPK) CREATE TABLE Users ( LastAccessTimestamp INT64 NOT NULL, UserId INT64 NOT NULL, ... ) PRIMARY KEY (LastAccessTimestamp, UserId);
  8. 8. PKを選択する時の注意点 - Hotspot (2/2) ● Hotspot の対策 ○ PK の順序を交換 ○ 新しく書き込まれるレコードは、テーブルの最後に追加されず、 Spanner サーバー間にちゃんと分散される CREATE TABLE Users (  UserId INT64 NOT NULL,  LastAccessTimestamp INT64 NOT NULL, ... ) PRIMARY KEY (UserId, LastAccessTimestamp);
  9. 9. なぜテーブルを インターリーブするか user_id SELECT user_name, item_id FROM users INNER JOIN items ON users.user_id = items.user_id WHERE user_id = 1234; user_id user_name 1111 john 1122 paul 1234 bob user_id item_id 1111 001 1111 002 1234 001 user_name user_id item_id 1111 john 1122 paul 1234 bob 1111 001 1111 002 1234 001 Spanserver A Spanserver B 1111 john 1111 001 1111 002 1122 paul 1234 bob 1234 001 Spanserver A Logical View Physical View No interleave Physical View With interleave インタリーブをすると、 JOIN   クエリ が2つのサーバにアクセスすることも なく、1サーバで済む
  10. 10. インデックスとインターリーブについて テーブルがインターリーブされている場合、不要なインデックスを作っているかもしれません。 See the example below: Table DDL index user CREATE TABLE test_user ( user_id INT64 NOT NULL, create_date TIMESTAMP NOT NULL ) PRIMARY KEY (user_id) CREATE INDEX idx_user_id ON user ( user_id ) item CREATE TABLE test_item ( user_id INT64 NOT NULL, item_id INT64 NOT NULL ) PRIMARY KEY (user_id, item_id), INTERLEAVE IN PARENT user ON DELETE CASCADE CREATE INDEX idx_user_id_in_item ON item ( user_id ) この例ではセカンダリイン デックスは不要です PK は自動的に  イ ンデックスされる user_id は既に親テーブルで インデックスされている
  11. 11. Channels と sessions ● Channels ○ Cloud Spanner へ接続する gRPC コネクション数 ○ Default = 4, max = 256. ○ コードの中で定義する必要がある ■ SpannerOptions options = SpannerOptions.newBuilder().setNumChannels(8).build(); ● Sessions ○ Session はトランザクションを実行できるコンテキストです。並列で行われるトランザクションは各自 session を利用する必要がある。例えば、あるアプリが並列に100トランザクションを行うとしたら、Session pool を最 低100に設定する必要があります。 ○ Default value = Default number of channels * 100 = 400 ○ Recommendations: Number of sessions = number of expected threads ○ データベースごとにセッション数の上限が:10000 per node. ○ 詳細はこちら:https://cloud.google.com/spanner/docs/sessions?hl=ja
  12. 12. エラー (auto-retry or SpannerException) Cloud Console 上のグラフにエラーが発生する場合 があります。 ● エラーの原因は通常トランザクションが abort されたからです ● エラーが発生したとグラフで見えるが、コード の中で SpannerException をキャッチできな い ● それはクライアントライブラリが自動的に abort されたトランザクションをリトライするか らです ● 自動リトライが失敗すると、 SpannerException をキャッチできます ● 基本エラーは無視しても問題ありません
  13. 13. ノード追加・削除の際、リシャードが なぜ1〜2sでできるのか? (1/5) S S S S ノード = Spanner Servers 2TB まで管理できるサーバ Colossus (分散ストレージ) 実データはここに格納される C クライアント Split ノード数:4 各ノードは 複数の Split の オーナー
  14. 14. ノード追加・削除の際、リシャードが なぜ1〜2sでできるのか? (2/5) S S S S ノード = Spanner Servers Colossus (分散ストレージ) C クライアント Split ノード数:4>3 1ノードを削除
  15. 15. ノード追加・削除の際、リシャードが なぜ1〜2sでできるのか? (3/5) S S S ノード = Spanner Servers Colossus (分散ストレージ) C クライアント Split ノード数:3 1〜2秒後 Split のオーナー が変わるだけ
  16. 16. ノード追加・削除の際、リシャードが なぜ1〜2sでできるのか? (4/5) S S S S ノード = Spanner Servers Colossus (分散ストレージ) C クライアント Split ノード数:3>4 1ノードを追加
  17. 17. ノード追加・削除の際、リシャードが なぜ1〜2sでできるのか? (5/5) S S S S ノード = Spanner Servers Colossus (分散ストレージ) C クライアント Split ノード数:4 1〜2秒後 Split のオーナー がまた変わる だけ
  18. 18. 容量に関する上限(2GB and 2TB) Cloud Spanner には 2TB size limit per node という容量上限があります。 インターリーブテーブルを使うと、裏上限がもう1つあります: 2GB per parent record and related child records Max 2GB
  19. 19. テーブルが分割(Split)されるロジック Cloud Spanner は容量と負荷状況次第、テーブルを split します。ただし、実際にどのタイミングでテーブルが分割されるか は保証できません。 Cloud Spanner では以下の2つの条件でテーブルが分割されます: ● Size-based splits ○ テーブルの容量が数GB程度になったら、テーブルを split します ● Load-based splits ○ Cloud Spanner は分散できる負荷だと、テーブルを split します。分散できない負荷は、      例えばシー ケンシャルな INSERT(だから Hotspot が発生する)。 上記は、どれだけ PK の選択肢が重要かを示しています。
  20. 20. 負荷試験は十分長く実行する Cloud Spanner の負荷試験を行う場合、5分ではなく、20〜30分の負荷試験をオススメします。その理由は、データの容量 が多くなることにより、Split がより多く発生して、データが正常に全ノード間に分散されるからです。 テーブルが十分 split されると、全ノードが 活用され、Cloud Spanner の最大の パフォーマンスを出せるようになります。 Split happens
  21. 21. 負荷試験間はデータベースをDropする 負荷試験を毎回行う際は、Insert したデータを全て削除するのではなく、データベースを Drop するようオススメします。 データの削除+再Insert は、テーブルスキャンのパフォーマンスを劣化します。それは、削除されたデータは Garbage Collector が物理的に削除するまではテーブルに append されるからです。テーブルのクリーンアップまで1週間までかかり ます。 Spanner のストレージは log-structured merge trees (LSM Tree)を使用している。 → Delete のオペレーションは "append a delete mutation" とストレージレベルで見られる。古いデータはデータベースがク リーンアップされるまで削除されない。 → 削除された PK がまだ格納されているので、テーブルスキャンがインパクトされる。
  22. 22. TPSの数え方 パフォーマンスグラフは受信した API リクエスト数を表示する ● "reads/s" は read と query を含む ● "writes/s" はトランザクションのコミット数を示す その結果、TPS は "writes/s" ということになります 3 read API calls と 9 buffered mutations を含むトランザクションは 3R, 1W とカウントされる
  23. 23. ノード数を縮小 するについて Cloud Spanner にはオートスケール機能はまだありません。 ノード数を縮小しようとすると、1ノードまでに縮小できない場合があります。 Spanner の仕組み上、Delete や Update されたデータは Garbage Collector が起動するまでに一時的に格納されます。そ の理由は2つ:整合性のあるバックアップを行うためとより高いパフォーマンスを提供するためです(Cloud Spanner はデー タ容量が多いほど、パフォーマンスが出るので)。 1 2 3 1. Monitor Spanner CPU usage 2. Trigger function when threshold hit 3. Function add a node Autoscale workaround
  24. 24. グラフの ”Total storage” の意味って? Cloud Console のグラフとして表示される “Total storage” には最新のデータ+ 削除・更新されたデータを含まれています。削除・更新されたデータは1週間以内 にクリーンアップされます(平均 3.5 日)。 古いデータを一時的に確保するメリットは: ● 高スループットの Read/Write を提供するため ● 整合性のあるバックアップを取るため お客様に課金されるデータ: ● ライブデータ ● 削除・更新されたデータ(1週間以内にクリーンアップされるまで)
  25. 25. Query Plan Cache SQL クエリを Spanner で使用する際に、bound parameters を使用す るのが重要です。 Cloud Spanner のノードは query plan cache の数が限られています。 クエリの中に静的パラメータを使用すると、各クエリが違うものと見られ て、query plan cache を効果的に活用することができません。この問題 を避けるには、以下の例のようにクエリは parameter binding を利用す る必要があります。 Statement statement = Statement .newBuilder("SELECT name WHERE id > @msg_id AND id < @msg_id + 100") .bind("msg_id").to(500) .build(); これ重要!
  26. 26. Additional readings ● SQL Best Practices ● Best Practices for Schema Design ● Efficient Bulk Loading ● Quizlet Cloud Spanner tests

×