GCP Database Options
GCPUG Admin
Google Developers Expert
Mercari / Merpay Solution Team
@sinmetal
https://gcpug.jp
GCP Database Service
2
太字はGoogleが独自に開発したDB
https://gcpug.jp
GCP Databaseの系譜 (sinmetalの主観)
3
Bigtableをアプリケーションで使いやすいようにQueryやTxを追加し、Bigtableのインフラを共有することでコストを抑えた
Datastoreよりパフォーマンスを改善し、大量のトラフィックを高速に捌けるようになった。
RDBのような柔軟なQueryにも対応
Firebase Realtime DB, Datastore, Spannerのノウハウを融合し、よりGCPらしいRealtime DBへ
Bigtable
Datastore
Spanner
Realtime DB
Firestore
https://gcpug.jp
Cloud Bigtable Introduction
4
https://gcpug.jp
Cloud Bigtableの後ろ側
5
DataはTabletに保存される。
Tabletは動的に増減する。
Tablet
Tablet
Tablet
Tablet
Node
Node
Client
https://gcpug.jp
Tabletの決定方法
6
Tablet
Tablet
Tablet
Tablet
a ~ e
f ~ j
k ~ o
p ~ z
今、Tabletが管理しているKeyの範囲を管理しておけば、指定されたKeyのRowを持っている可能性があるTabletが分かり、そのTabletを担当しているNodeが分かる
Node
Node
Client
https://gcpug.jp
Tabletの分割
7
Tablet
Tablet
Tablet
Tablet
a
f ~ j
k ~ o
p ~ z
Node
Node
Client
Tablet
b ~ e
a のPKのデータばっかり増えたので、a ~ eを分割
https://gcpug.jp
Tabletの再配置
8
Tablet
Tablet
Tablet
Tablet
a
f ~ j
k ~ o
p ~ z
Node
Node
Client
Tablet
b ~ e
Node
https://gcpug.jp
Tabletのhotspot問題
9
Tablet
Tablet
Tablet
Tablet
aa ~ af
f ~ j
k ~ o
p ~ z
Node
Node
Client
Tablet
b ~ e
Tablet
ag ~ az
hot
spot
hot
spot
hot
spot
ひたすらaの行Keyのデータが増えていく
https://gcpug.jp
行Keyの戦略
10
https://gcpug.jp
行Keyの戦略
11
10,20,30,40,50
INSERT 10, 20, 30, 40, 50
10,20
30,40,50
INSERT 60,70,80,90
30,40,50, 60, 70, 80 ,90
10,20
30,40,50
60,70,80,90
10,20
分割
分割
後ろのTabletにINSERTが偏る
https://gcpug.jp
行Keyの戦略
12
30,40,50
60,70,80,90
10,20
INSERT 15,23,35,67
30,35,40,50
60,67,70,80,90
10,15,20,23
データが増えていく時に別々のTabletに書き込まれるようにしていく
データがない状態だと、分散していない状態からスタートするので、じわじわデータを入れていく
Cloud Datastoreのベストプラクティス "500/50/5" rule が参考になる
ローンチした瞬間に凄まじいトラフィックが予想される場合は、ダミーデータを入れておくなども有効
NOTE : “500/50/5” rule
新しいKindに対するオペレーションは毎秒 500 回を上限とし、その後でトラフィックを50%ずつ、5 分ごとに増やしていく
理論上は、この増加スケジュールを使用すると 90 分後に毎秒 740,000 回までオペレーションを増やすことをできる
https://gcpug.jp
行Keyの戦略
13
https://gcpug.jp
Cloud Datastore
14
https://gcpug.jp
GCP Databaseの系譜 (sinmetalの主観)
15
Bigtableをアプリケーションで使いやすいようにQueryやTxを追加し、Bigtableのインフラを共有することでコストを抑えた
Datastoreよりパフォーマンスを改善し、大量のトラフィックを高速に捌けるようになった。
RDBのような柔軟なQueryにも対応
Firebase Realtime DB, Datastore, Spannerのノウハウを融合し、よりGCPらしいRealtime DBへ
Bigtable
Datastore
Spanner
Realtime DB
Firestore
https://gcpug.jp
Cloud Datastoreの後ろ側
16
Bigtableが本領を発揮するにはTB以上のデータが必要だが、通常のアプリケーションはTBもデータがない。
その欠点を克服するためにDatastoreはみんなでBigtableを共有することで、Bigtableをスケールさせている。
Bigtable
Megastore
Datastore
トランザクションを行うためのレイヤー。
プロパティに対するクエリを行うためのレイヤー。
https://gcpug.jp
Cloud Datastoreのクエリの仕組み
17
https://gcpug.jp
Cloud Datastoreのクエリの仕組み
18
Propertyの値をKeyにしてTableを作成しておく
https://gcpug.jp
Indexの作成タイミング
19
https://gcpug.jp
Entity GroupとAncestor Query
20
keyの頭に、親のkeyを入れることで、Bigtable上で連なって保存されるようにしている
https://gcpug.jp
Entity GroupとAncestor Query
21
一度のクエリで親は1人しか指定できないので、JOINとは異なる
子しか取得できないので、親子同時には取得できない
https://gcpug.jp
Firebase Realtime DB
22
https://gcpug.jp
Firebase Realtime DBの後ろ側
23
https://gcpug.jp
Cloud Spanner
24
https://gcpug.jp
GCP Databaseの系譜 (sinmetalの主観)
25
Bigtableをアプリケーションで使いやすいようにQueryやTxを追加し、Bigtableのインフラを共有することでコストを抑えた
Datastoreよりパフォーマンスを改善し、大量のトラフィックを高速に捌けるようになった。
RDBのような柔軟なQueryにも対応
Firebase Realtime DB, Datastore, Spannerのノウハウを融合し、よりGCPらしいRealtime DBへ
Bigtable
Datastore
Spanner
Realtime DB
Firestore
https://gcpug.jp
Spannerの後ろ側
26
Node
Split
Colossus
Split
Split
Split
Split
Split
Split
Node
Client
Insert, Update, Delete, Queryを処理するレイヤー
それぞれSpan Serverを管理する
1台のサーバというわけではなく、複数Zoneに存在している
Table, Indexが保存されているレイヤー
数は動的に変更される
https://gcpug.jp
Splitの決定方法
27
Split
Split
Split
Split
a ~ e
f ~ j
k ~ o
p ~ z
今、Splitが管理しているKeyの範囲を管理しておけば、指定されたKeyのRowを持っている可能性があるSplitが分かり、そのSplitを担当しているNodeが分かる
Node
Node
Client
https://gcpug.jp
Splitの分割
28
Split
Split
Split
Split
a
f ~ j
k ~ o
p ~ z
Node
Node
Client
Split
b ~ e
a のPKのデータばっかり増えたので、a ~ eを分割
https://gcpug.jp
Splitの再配置
29
Split
Split
Split
Split
a
f ~ j
k ~ o
p ~ z
Node
Node
Client
Split
b ~ e
Node
https://gcpug.jp
Splitのhotspot問題
30
Split
Split
Split
Split
aa ~ af
f ~ j
k ~ o
p ~ z
Node
Node
Client
Split
b ~ e
Split
ag ~ az
hot
spot
hot
spot
hot
spot
hotspotが発生しないようにSpannerはSplitの分割や、Splitの担当のNodeを動的に変更していくが、どうにもならん時もある
ひたすらaのPKのデータが増えていく
https://gcpug.jp
PKの戦略
31
https://gcpug.jp
PKの戦略
32
10,20,30,40,50
INSERT 10, 20, 30, 40, 50
10,20
30,40,50
INSERT 60,70,80,90
30,40,50, 60, 70, 80 ,90
10,20
30,40,50
60,70,80,90
10,20
分割
分割
後ろのSplitにINSERTが偏る
https://gcpug.jp
PKの戦略
33
30,40,50
60,70,80,90
10,20
INSERT 15,23,35,67
30,35,40,50
60,67,70,80,90
10,15,20,23
データが増えていく時に別々のSplitに書き込まれるようにしていく
データがない状態だと、分散していない状態からスタートするので、じわじわデータを入れていく
Cloud Datastoreのベストプラクティス "500/50/5" rule が参考になる
ローンチした瞬間に凄まじいトラフィックが予想される場合は、ダミーデータを入れておくなども有効
NOTE : “500/50/5” rule
新しいKindに対するオペレーションは毎秒 500 回を上限とし、その後でトラフィックを50%ずつ、5 分ごとに増やしていく
理論上は、この増加スケジュールを使用すると 90 分後に毎秒 740,000 回までオペレーションを増やすことをできる
https://gcpug.jp
PKの戦略
34
https://gcpug.jp
複合Keyの戦略
35
https://gcpug.jp
INDEXの仕組み
36
DatastoreはIndexを非同期に作成していたが、Spannerは同期的に作るので、Index更新の遅延の影響を受けやすくなってしまった
https://gcpug.jp
TimestampにINDEXを貼るパターン
CreatedAtやUpdatedAtの値はhotspotになりやすい値であり、INDEXも貼りたい値
なので、このソルティングを利用して、INDEXを貼る
now := time.Now()
shardId := crc32.ChecksumIEEE([]byte(now.String())) % 10
id := uuid.New().String()
t := &TweetBenchmark{
ID: id,
Author: getAuthor(),
Content: uuid.New().String(),
CreatedAt: now,
UpdatedAt: now,
CommitedAt: spanner.CommitTimestamp,
ShardCreatedAt: int(shardId),
}
37
https://gcpug.jp
Shard利用時のクエリ
CREATE INDEX TweetBenchmarkIndex ON TweetBenchmark(ShardId, CreatedAt)
SELECT Id
FROM TweetBenchmark@{FORCE_INDEX=TweetBenchmarkIndex}
WHERE ShardCreatedAt BETWEEN 0 AND 9
AND CreatedAt > '2018-05-01T15:14:10.386257Z'
AND CreatedAt < '2018-05-01T15:16:10.386257Z'
ORDER BY CreatedAt DESC;
38
https://gcpug.jp
Shard利用時のクエリ
39
Split
Split
Split
0 ~ 1
6 ~ 7
8 ~ 9
Node
Node
Client
Split
4 ~ 5
Split
2 ~ 3
クエリ時は ShardId BETWEEN 0 AND 9を指定することで、全Splitに対してクエリを実行する
INSERT時はShardIdによってSplitに分散される
https://gcpug.jp
INTERLEAVE
40
Order(1) | name:sinmetal | price:1100 | | | |
OrderDetails(1,1) | | | itemName:ビスケット | price:100 | count:10 |
OrderDetails(1,2) | | | itemName:ガム | price:10 | count:10 |
Order(2) | name:gcpug | price:500 | | | |
OrderDetails(2,1) | | | itemName:ガム | price:10 | count:50 |
https://gcpug.jp
Cloud Firestore (β)
41
https://gcpug.jp
GCP Databaseの系譜 (sinmetalの主観)
42
Bigtableをアプリケーションで使いやすいようにQueryやTxを追加し、Bigtableのインフラを共有することでコストを抑えた
Datastoreよりパフォーマンスを改善し、大量のトラフィックを高速に捌けるようになった。
RDBのような柔軟なQueryにも対応
Firebase Realtime DB, Datastore, Spannerのノウハウを融合し、よりGCPらしいRealtime DBへ
Bigtable
Datastore
Spanner
Realtime DB
Firestore
https://gcpug.jp
Cloud Firestoreの後ろ側
43
Spannerが本領を発揮するにはTB以上のデータが必要だが、通常のアプリケーションはTBもデータがない。
その欠点を克服するためにFirestoreはみんなでSpannerを共有することで、Spannerをスケールさせている。
Spanner
Firestore
Mobile Backend as a Serviceの機能を提供するレイヤー。
https://gcpug.jp
Cloud Datastoreからバージョンアップされたこと
44
https://gcpug.jp
Documentを階層で保持する
45
Documentのフィールドとして、Collectionを持つことができるようになっているので、常にJOINするものは最初から一緒に持たせておくことができる
https://gcpug.jp
SubCollectionの未実装な部分...
46
order.details.name == “ガム” というクエリが実行できない
"collection group query"という機能としてロードマップにあるが、2018/07/14時点ではまだリリースされていない
https://stackoverflow.com/questions/46573014/firestore-query-subcollections
https://gcpug.jp
Cloud SQL Introduction
47
https://gcpug.jp
Cloud SQLの後ろ側
48
Your GCP Project
Cloud SQL GCP Project
Compute Engine
MySQL (Master)
Compute Engine
MySQL (Read Replica)
Cloud SQL Proxy
https://gcpug.jp
Cloud Memorystore for Redis (β)
49
https://gcpug.jp
Cloud Memorystore for Redis (β) の裏側
50
https://gcpug.jp
BigQuery
51
https://gcpug.jp
Dremel Architecture (BigQueryの裏の仕組み)
HDDから秒間読み込めるデータ容量は百数十MBなので、データを予め100MBほどに分割して、別々のHDDに保存しておく。
クエリ実行時に、必要なテーブルが保存されているHDDに対してDremel Nodeを割り当て、分散処理を行っていく
Dremel Node
Jupiter Network
Storage
Storage
Storage
Storage
Storage
Dremel Node
Dremel Node
Dremel Node
Dremel Node
Dremel Node
Dremel Node
Dremel Node
Dremel Node
Dremel Node
Dremel Node
Dremel Node
Dremel Node
Dremel Node
Dremel Node
Root Node
HDDにHotspotがある場合に備えて、同じファイルを複数のStorageに問い合わせて、最初にレスポンスが返ってきたものを採用している
52
列指向ストレージ
行指向
列指向
53
| | |
| | |
| | |
|
|
|
|
|
|
|
|
|
https://gcpug.jp
Dremel
SELECT
state,
COUNT(1) AS count
FROM
`bigquery-public-data.samples.natality`
WHERE
year = 1987
GROUP BY
state
ORDER BY
count DESC
54
https://gcpug.jp
Dremel v1 Query Processing
55
Leaf
Leaf
Mixer1
Colossus
Jupiter
Leaf
Leaf
Mixer1
Mixer0
Leafはそれぞれ取得したデータに対して以下を実行してMixerに渡す
year = 1987
COUNT
GROUP BY state
MixerはLeafから取得したデータに対して以下を実行して、上のMixerにわたす
COUNT
GROUP BY state
http://gcpug.jp
SpannerとBigQueryの思想の違い
56
https://gcpug.jp
Dabatase比較表
57
https://gcpug.jp
Thanks you
Slackで待ってます!
https://slack.gcpug.jp
58
https://gcpug.jp
Resources
Google Cloud Platformの謎テクノロジーを掘り下げる
Google Cloud Storage: tips for reliability, performance and scalability (Google Cloud Next '17)
59
https://gcpug.jp
Resources for Spanner
60
https://gcpug.jp
Resources for Spanner
61
https://gcpug.jp