y-ohgi's blog

しがないSREなフリーランスの徒然

GCPのCloud SpannerをGAEで動かす

概要

GCPのCloud Spannerについて調べて動かしてみた話

やったこと

  • Cloud Spannerの調査
  • GAEからCloud Spannerを叩く

アウトプット

github: https://github.com/y-ohgi/gcp-practice

GAE(Google App Engine)

  • GCPのPaaS
  • 勝手にスケールするし負荷分散もしてくれる凄いやつ
  • 今回はGAE FEでランタイムはnodejsを使用。
    • Cloud Spannerのライブラリが存在する言語で、僕がサクッと書けるのがRubyとNode.jsだけだった
    • なのでNode.jsでExpressを採用するためにGAE FEを採用

Cloud Spanner

概要

Googleが作成し、もともとGoogle社内で使用されてきたRDB。 水平スケールが可能で、CAP定理の3つを(ほぼ)選択できる唯一のエンタープライズDB。
インターフェイスRDBだが、裏側のストレージはKVS   メンテナンスウィンドウが無いため、マイクロサービスのコアな部分に必要なRDBとして扱うことができそう

水平スケール

例えば従来のMySQLPostgreSQLなどは読み込みはリードレプリカを横に増やすことで水平スケール(インスタンス台数を増やす。)させる事が可能。
書き込みはその限りではなく、垂直スケール(インスタンスサイズを上げる。)でのみしか対応ができない。
Cloud Spannerは従来のマスター・スレーブ形式とは異なり、全てのノードがReadとWriteを行うことが可能、これにより水平スケールが可能に。
Paxosという合意アルゴリズム原子時計を用いてトランザクションを管理している

CAP定理

分散システムにおいて、3つの要素のうち2つしか同時に満たすことができないというもの。
大事なのが「分散システム」という文脈。

  1. C: Consistency
    • 一貫性
    • ストレージ内で共有されているデータが一貫していること。
    • 厳密なトランザクションの有無
      • 例えばAWSのNoSQLサービスのDynamoDBであれば、トランザクションは存在せずAとPを重視されたシステム。
  2. A: Availability
    • 可用性
    • 読み込みと書き込みの両方で、100%の可用性が担保されている
    • データが壊れたり、ロック待ちの状態にならないこと
  3. P: Tolerance to Network Partions
    • ネットワーク分断耐性
    • 1つのサーバーに障害が発生したりデータの破損があったとしても問題なく使用できること

Cloud Spannerはこの3つを、業務遂行上要求されるであろう非機能要件レベルで満たすことが可能。

お値段

  • $1.17/h
    • 91,400円/月 = $1.17 * 105円 * 24h * 31day
  • クラスター化されてるとはいえ3台がベストプラクティスらしいので。
    • 274,200/月 = 91,400円/月 * 3台
    • 隣の席の人月より安い!!

DBの設計時に気をつける点

Cloud Spannerを叩く

DDL

テーブル作成用DDL
VARCHARではなくSTRINGになっていたり、よく見るSQLとは少し違う

CREATE TABLE blogs (
  blog_id STRING(36),
  title STRING(150),
  body STRING(MAX),
  created_at TIMESTAMP
) PRIMARY KEY(blog_id);

CREATE TABLE comments (
  comment_id STRING(36),
  blog_id STRING(36),
  name STRING(50),
  body STRING(MAX),
  created_at TIMESTAMP
) PRIMARY KEY(blog_id, comment_id),
  INTERLEAVE IN PARENT blogs ON DELETE CASCADE; # インターリーブの設定。

SELECT

ANSI規格準拠のSELECT文を使用可能

const query = {
  sql: `SELECT * FROM blogs WHERE blog_id = @id`,
  params: {
    id: id
  }
}

database()
  .run(query)
  .then(res => {
      //
     console.log(res)
  })

INSERT

データの挿入にはSQL文(INSERT文)は使用不可。
SDKを介してリクエストを送信することでのみ挿入が行える(ここらへんNoSQLっぽい)。

const values = [
  {
    blog_id: uuid(),
    title: 'title',
    created_at: new Date() // TIMESTAMP型はUTCである必要あり
  }
]

tables('blogs')
  .insert(values)
  .then(data => console.log(data))

動かして得た知見

GAE

  • DockerfileがGAEの起動ファイルである app.yaml ど同じ階層にいるとランタイムを custom にしろと言われてエラー
    • 仰せのままにcustomにしたら動いた。
    • Docker上でgcloudコマンド叩く必要が出てきたためDockerを途中で切り捨てた。
  • GAEへ渡す環境変数リポジトリ上から隠す

Spanner

  • Spannerはローカルで起動できない
  • ローカルからSpanner(クラウド上の。)を叩くとレスポンスが著しく遅い。
    • 体感2秒ほど待つと帰ってくる。遅い。
  • 高い。
    • やっぱり高い。課金が1時間100円ちょっとなので無料枠がゴリゴリ減る。

雑記

諸々調べてるとCAP定理を語るのは古いとかなんとか書かれてたり。ちゃんと自分で調べて答えを出す必要を感じる。
あと、サーバーに乗せるところまでやらないと見えてこないものがあるなと今日このごろ。今回だとGAE x Spannerのレイテンシが遅かったりとか(GAEからSpannerはgRPCではなくHTTPっぽい)。
というかデプロイしないとクラウドで遊べないのが問題。

参考