Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Cloud Spanner 開発・運用で得られたノウハウ/ColoplTech-02-02

COLOPL Inc.
February 16, 2022

Cloud Spanner 開発・運用で得られたノウハウ/ColoplTech-02-02

※資料内の参照リンクを選択し閲覧する場合は、ダウンロードをお願いいたします

\積極的に技術発信を行なっております/
▽ Twitter/COLOPL_Tech
https://twitter.com/colopl_tech

▽ connpassページ
http://colopl.connpass.com

▽ COLOPL Tech Blog
http://blog.colopl.dev

COLOPL Inc.

February 16, 2022
Tweet

More Decks by COLOPL Inc.

Other Decks in Technology

Transcript

  1. じめに • Spanner ◦ スケーラブルで安定性も高くコロプラ 多く タイトルで採用 ◦ フルマネージドで挙動が不明な部分もある •

    開発・運用する上で得られたノウハウを共有 ◦ MySQL から Spanner へ 移行による開発 変化 ◦ 開発・運用で気をつけること 3
  2. ユーザーデータ 取り扱い • MySQL ◦ シャーディングで負荷分散 ◦ 処理によって 分散トランザクションが必要 •

    Spanner ◦ インターリーブ ▪ テーブルに親子関係(例: User => UserItem) ▪ 物理的に同じ場所に配置される で高パフォーマンス ◦ ユーザー間を横断してスキャンなど 苦手 5
  3. シャーディングから 解放 • 自前 シャーディング(MySQL) ◦ 接続先をコードで指定 ▪ 途中で分割数を変えていたりするとさらに辛い ◦

    調査 難易度が高い ▪ コロプラ Nite という内製ツールでカバー • 水平/垂直分割されたRDBMSを便利に検索するため ツールを内製した話 • シャーディング 考慮がほぼ不要 ◦ アプリレイヤ コードが簡潔に ◦ ホットスポット回避で分散用 カラムを追加すること ある 6
  4. レプリケーション 変化 • アクセス先やレプリケーション遅延 考慮不要 • 注意事項 ◦ 調査クエリがサービスに直接影響 ▪

    ログを多めに残しておき BigQuery を使用 ▪ 別インスタンスにデータを複製しそ 中でクエリを実行 ◦ 管理ツール 実装にも Spanner へ 負荷に注意が必要 ▪ コロプラ 横断検索に Elasticsearch などを使用 • ユーザー名、ランク、ログイン日時など 7
  5. 共通データ(マスターデータ) 取り扱い • マスターデータと ◦ コロプラで ユーザーが共通で使うデータを別DBで管理 ◦ 武器・アイテム・キャラクターなど データ

    • 変わらず MySQL を使用 ◦ Spanner 同一レコードへ 参照 ホットスポットになりやすい ▪ 例:キャッシュがないタイミングで   複数ユーザーが特定 アイテムID データを取得 ◦ 一部 タイトル MySQL互換 TiDB を使用 8
  6. カラム追加/変更が容易 • MySQL ◦ オンライン ALTER ◦ JSON カラムを作って値を管理など •

    Spanner ◦ レコード量に関係なく自由に変更可能 ▪ 適用に時間 かかる ▪ 複数カラム 更新なども特に問題なく可能 ▪ コロプラで Grafana などで負荷を監視しつつ実行 ◦ カラム追加時に NOT NULL が指定不可という ある 9
  7. クエリパラメータ数 上限 • クエリパラメータ ◦ SELECT … WHERE IN (@a,

    @b, @c) @a など ◦ 950個を超えるとエラー • ミューテーション ◦ トランザクション内で 20000 を超えるとエラー ▪ 列数 + インデックス ある列数 ▪ (参照: mutation 数え方) ◦ バッチ処理など一気にデータ入れる場合など 気をつける 11
  8. クエリパラメータ数 上限 • 実際にリリース前に修正したも ◦ ユーザー 図鑑データを図鑑IDで WHERE IN ◦

    位置系データ ユーザーデータを WHERE IN • 対応 WHERE IN をやめるか分割して取得するなど • WHERE IN しているコードやクエリログ 要チェック ◦ マスターデータを元に WHERE IN している箇所 特に注意 ▪ 運用でデータが増える可能性あるため常に気を遣うように 12
  9. トランザクション リトライ • Spanner 性質上トランザクション リトライが起きやすい ◦ リトライされる前提でコードを書く • Spanner

    以外 データ更新を常に注意 ◦ static変数 ◦ Redis など キャッシュ ◦ キュー ◦ イベント発行 • static変数使わない、ロールバックなど 処理を正しく書く 13
  10. トランザクション内 SELECT 空振り • 「SELECT してデータがなけれ INSERT」 パターン • データがない場合に

    abort する確率が上がる ◦ リトライが発生し負荷も上がる • 空振り前提 場合 SELECT せず INSERT するほうが良い ◦ UUID 被り チェック しない ◦ 被ったらエラーでリトライ 14
  11. インデックス 必要な時だけ付ける • インデックス 内部的に テーブル • 必要なときだけ付ける ◦ Google

    内 テストだと、SELECT した結果が テーブル全体 5% 以内 つけると速くなるという検証結果 ▪ (参照: D2-5-S06: Cloud Spanner in Action - YouTube ) 15
  12. Query Optimizer バージョンを固定 • 何もしないと自動で変わる ◦ v2: 2020/3/1 ◦ v3:

    2021/8/1 • GCPコンソールに お知らせが出る • バージョンを固定しておくと安心 ◦ 任意 タイミングでバージョン変更対応を展開 ◦ ALTER DATABASE MyDatabase SET OPTIONS (optimizer_version = 3); ◦ (参照: Managing the query optimizer | Cloud Spanner) 16
  13. インターリーブ内が 8GB を超える場合 • インターリーブ内 データ 基本1つ スプリット • 8GB

    を超えるとスプリットが分割 ◦ スプリットを跨いだ参照になりうる ◦ サイズが見れないため増えていることに気づきづらい ◦ (参照: Schema and data model | Cloud Spanner) • 単調増加するデータ 入れず削除できるも 削除 ◦ 物理削除な でアプリレイヤでログを慎重に残すことが重要 ◦ コロプラで 一部 API で◯%だけ削除するなどをやっている ◦ TTL を使用することで定期的に削除するポリシーを設定可能 17
  14. リリース前に必ず見ておくポイント • クエリパラメータ 制限に引っかからないか • トランザクション リトライされても大丈夫か • SELECT 空振りコード確認

    • 無駄にインデックス貼っていないか • ホットスポットにならないか • 高頻度に単調増加するログなどを入れていないか ◦ インターリーブ内 データが 8GB を超えないか 18
  15. まとめ • Spanner 導入による開発 変化 ◦ ユーザーデータ取り扱い 大きな変化 ◦ マスターデータ

    非Spanner • 気をつけること ◦ クエリパラメータ、ミューテーション 上限 ◦ トランザクション リトライ考慮したコード ◦ そ 他 リリース前 チェックポイント 19
  16. ステイル読み取り Stale Read • 古いデータ(10秒以上前)を許容する場合に使用 ◦ パフォーマンス向上が見込める ◦ 他ユーザー名 取得など

    • 強力な読み取り Strong Read ◦ データが最新 状態か 確認が入り遅くなる場合がある ▪ レプリカからリーダーへ 通信 22
  17. GCPコンソール上で 注意点 • トランザクションが貼れない ◦ UPDATE文などを間違えられない • 時刻 UTCで扱われる ◦

    内部 UTCで保存され表示もすべてUTC ◦ 9時間 時差を考慮 ▪ x: SELECT ... WHERE createdAt > "2022-02-16 19:30:00" • これだと午前3時になる。まだ勉強会始まってない ▪ o: SELECT ... WHERE createdAt > "2022-02-16 19:30:00+09:00" 24