Cloud Spanner 開発・運用で得られたノウハウ/ColoplTech-02-02
by
COLOPL Inc.
Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
Cloud Spanner 開発・運用で得られたノウハウ 1 山田 和毅
Slide 2
Slide 2 text
自己紹介 ● 山田 和毅 ● 株式会社コロプラ 2017年新卒入社 ● ユージェネチーム 2
Slide 3
Slide 3 text
じめに ● Spanner ○ スケーラブルで安定性も高くコロプラ 多く タイトルで採用 ○ フルマネージドで挙動が不明な部分もある ● 開発・運用する上で得られたノウハウを共有 ○ MySQL から Spanner へ 移行による開発 変化 ○ 開発・運用で気をつけること 3
Slide 4
Slide 4 text
1. Spanner 移行による開発 変化 2. 開発・運用で気をつけるべきこと 4 4
Slide 5
Slide 5 text
ユーザーデータ 取り扱い ● MySQL ○ シャーディングで負荷分散 ○ 処理によって 分散トランザクションが必要 ● Spanner ○ インターリーブ ■ テーブルに親子関係(例: User => UserItem) ■ 物理的に同じ場所に配置される で高パフォーマンス ○ ユーザー間を横断してスキャンなど 苦手 5
Slide 6
Slide 6 text
シャーディングから 解放 ● 自前 シャーディング(MySQL) ○ 接続先をコードで指定 ■ 途中で分割数を変えていたりするとさらに辛い ○ 調査 難易度が高い ■ コロプラ Nite という内製ツールでカバー ● 水平/垂直分割されたRDBMSを便利に検索するため ツールを内製した話 ● シャーディング 考慮がほぼ不要 ○ アプリレイヤ コードが簡潔に ○ ホットスポット回避で分散用 カラムを追加すること ある 6
Slide 7
Slide 7 text
レプリケーション 変化 ● アクセス先やレプリケーション遅延 考慮不要 ● 注意事項 ○ 調査クエリがサービスに直接影響 ■ ログを多めに残しておき BigQuery を使用 ■ 別インスタンスにデータを複製しそ 中でクエリを実行 ○ 管理ツール 実装にも Spanner へ 負荷に注意が必要 ■ コロプラ 横断検索に Elasticsearch などを使用 ● ユーザー名、ランク、ログイン日時など 7
Slide 8
Slide 8 text
共通データ(マスターデータ) 取り扱い ● マスターデータと ○ コロプラで ユーザーが共通で使うデータを別DBで管理 ○ 武器・アイテム・キャラクターなど データ ● 変わらず MySQL を使用 ○ Spanner 同一レコードへ 参照 ホットスポットになりやすい ■ 例:キャッシュがないタイミングで 複数ユーザーが特定 アイテムID データを取得 ○ 一部 タイトル MySQL互換 TiDB を使用 8
Slide 9
Slide 9 text
カラム追加/変更が容易 ● MySQL ○ オンライン ALTER ○ JSON カラムを作って値を管理など ● Spanner ○ レコード量に関係なく自由に変更可能 ■ 適用に時間 かかる ■ 複数カラム 更新なども特に問題なく可能 ■ コロプラで Grafana などで負荷を監視しつつ実行 ○ カラム追加時に NOT NULL が指定不可という ある 9
Slide 10
Slide 10 text
1. Spanner 移行による開発 変化 2. 開発・運用で気をつけるべきこと 10 10
Slide 11
Slide 11 text
クエリパラメータ数 上限 ● クエリパラメータ ○ SELECT … WHERE IN (@a, @b, @c) @a など ○ 950個を超えるとエラー ● ミューテーション ○ トランザクション内で 20000 を超えるとエラー ■ 列数 + インデックス ある列数 ■ (参照: mutation 数え方) ○ バッチ処理など一気にデータ入れる場合など 気をつける 11
Slide 12
Slide 12 text
クエリパラメータ数 上限 ● 実際にリリース前に修正したも ○ ユーザー 図鑑データを図鑑IDで WHERE IN ○ 位置系データ ユーザーデータを WHERE IN ● 対応 WHERE IN をやめるか分割して取得するなど ● WHERE IN しているコードやクエリログ 要チェック ○ マスターデータを元に WHERE IN している箇所 特に注意 ■ 運用でデータが増える可能性あるため常に気を遣うように 12
Slide 13
Slide 13 text
トランザクション リトライ ● Spanner 性質上トランザクション リトライが起きやすい ○ リトライされる前提でコードを書く ● Spanner 以外 データ更新を常に注意 ○ static変数 ○ Redis など キャッシュ ○ キュー ○ イベント発行 ● static変数使わない、ロールバックなど 処理を正しく書く 13
Slide 14
Slide 14 text
トランザクション内 SELECT 空振り ● 「SELECT してデータがなけれ INSERT」 パターン ● データがない場合に abort する確率が上がる ○ リトライが発生し負荷も上がる ● 空振り前提 場合 SELECT せず INSERT するほうが良い ○ UUID 被り チェック しない ○ 被ったらエラーでリトライ 14
Slide 15
Slide 15 text
インデックス 必要な時だけ付ける ● インデックス 内部的に テーブル ● 必要なときだけ付ける ○ Google 内 テストだと、SELECT した結果が テーブル全体 5% 以内 つけると速くなるという検証結果 ■ (参照: D2-5-S06: Cloud Spanner in Action - YouTube ) 15
Slide 16
Slide 16 text
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
Slide 17
Slide 17 text
インターリーブ内が 8GB を超える場合 ● インターリーブ内 データ 基本1つ スプリット ● 8GB を超えるとスプリットが分割 ○ スプリットを跨いだ参照になりうる ○ サイズが見れないため増えていることに気づきづらい ○ (参照: Schema and data model | Cloud Spanner) ● 単調増加するデータ 入れず削除できるも 削除 ○ 物理削除な でアプリレイヤでログを慎重に残すことが重要 ○ コロプラで 一部 API で◯%だけ削除するなどをやっている ○ TTL を使用することで定期的に削除するポリシーを設定可能 17
Slide 18
Slide 18 text
リリース前に必ず見ておくポイント ● クエリパラメータ 制限に引っかからないか ● トランザクション リトライされても大丈夫か ● SELECT 空振りコード確認 ● 無駄にインデックス貼っていないか ● ホットスポットにならないか ● 高頻度に単調増加するログなどを入れていないか ○ インターリーブ内 データが 8GB を超えないか 18
Slide 19
Slide 19 text
まとめ ● Spanner 導入による開発 変化 ○ ユーザーデータ取り扱い 大きな変化 ○ マスターデータ 非Spanner ● 気をつけること ○ クエリパラメータ、ミューテーション 上限 ○ トランザクション リトライ考慮したコード ○ そ 他 リリース前 チェックポイント 19
Slide 20
Slide 20 text
補足資料 21
Slide 21
Slide 21 text
ステイル読み取り Stale Read ● 古いデータ(10秒以上前)を許容する場合に使用 ○ パフォーマンス向上が見込める ○ 他ユーザー名 取得など ● 強力な読み取り Strong Read ○ データが最新 状態か 確認が入り遅くなる場合がある ■ レプリカからリーダーへ 通信 22
Slide 22
Slide 22 text
ローカル開発で エミュレータが便利 ● Spanner ローカル開発がしづらい ○ 常にSpannerに通信できる環境である必要がある ○ データベース 作り直し処理などに少し時間がかかる ● 公式 エミュレーター ○ ローカル メモリ上で動く で快適 ○ デメリット データを永続化できないこと 23
Slide 23
Slide 23 text
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