Google Cloud Spanner 学习报告

Google Cloud Spanner 学习报告

  • 17 Jan 2019

本人介绍,未使用过 Google Cloud Spanner,不是 DBA。

简介

Google 的 AdWords 曾经是靠 MySQL+手工Sharding来支撑,但在扩展和可靠性上不能满足要求。于是开发了全局一致性和自动 Sharding 的数据库 Spanner。

Spanner 带动了一波云原生数据库的热潮,云原生数据库的特点是,计算和存储分离,增加 node 就可以增加存储能力和性能;自动分片;支持分布式事务。

国内的云原生数据有阿里云的 云数据库POLARDB,腾讯云的
云数据库 CynosDB,这两个数据库的特点还有完全兼容 MySQL,其中 CynosDB 还可以支持 PostgreSQL 10(参考时间 2019年1月17日),现有应用无需更改 SDK,减少数据库迁移的成本。

TrueTime

Spanner 数据库告诉了人们,当数据容量增加,分片数量增加,依然可以享受高性能和事务全局一致性,依靠的最惊艳的技术就是 TrueTime。

注意,Spanner 的可序列化(serializability)依靠的还是 Lock,但是外部一致性(external consistency)依靠的是 TrueTime

事务依靠全局一致性的顺序 id 来保证事务执行顺序的正确性,Spanner 使用的是时间戳,而就算使用原子时钟,时间还是会有乱序的存在。TrueTime.now() 返回了 [earliest, latest] 间隔,牺牲了少许等待时间换来更高的一致性。下面 quote 一下 Google 的文章

Thus, if two intervals do not overlap, then we know calls were definitely ordered in real time. If the intervals overlap, we do not know the actual order.

Schema Design

不同的数据库间做数据迁移,都要理解两个数据库各自的优点,才能更好的用上新数据库。例如从 MySQL 迁移到 HBase,如果表设计一模一样的话,简直就是浪费了 Hbase 的特性,而且因为 Hbase 没有二级索引(虽然可以简单设计一下)可能业务性能会下降。

先简单说一下 Spanner 的存储架构

Spanner 的数据都是存放在节点机器,下面简称 node,而 node 存放分片(split),数据在 split 的访问顺序是有序的,参考过论文,数据在 split 中使用 KV 结构存储。node 之间的数据也是有序的,可以这样理解:node1{spli1, split2}, node2{split3}, node3{split4, split5, slit 6}

第一个问题,顺序写入 HotSpot

数据主键如果是有序的,例如用自增 id 或者 MongoDB 的 ObjectId,新数据很大可能会写入到第一个或者最后一个split,造成单个 node 的负载超高,而其他 node 很空闲,这样对于写性能不能做到增加 node 就增加性能。

Spanner 产品文档给出了几种解决办法:

1. 调换主键顺序

因为 spanner 是可以定义多个列来组合称主键,登录日志表如原主键是 (time, user_id), 因为 time 字段是自增的,可以用 (user_id, time) 来做主键。登录的 user_id 是无序的所以可以把数据写入到尽量多的 split

2. 增加 shard_id 字段

通过保存原主键的 hash 或者只是保存 hash。例如原主键是 (shop_id, user_id, order_id),可以增加 shard_id 字段 shard_id = md5(shop_id + user_id + order_id)[0:3],新主键为 (shard_id, shop_id, user_id),这里还可以考虑到只需要 shop_id 和 user_id 计算 md5,因为这样的话每个用户下的订单都可能放在同一个 split,加快用户端的订单查找速度。而根据 shop_id 查找订单可能是低频的,能接受的延时稍高。Spanner 文档是使用 hash() % N 来存储数字型 shard_id,我这里只是给出另一种实现,不一定是最好。

3. 使用 UUID v4

新表设计可以使用 UUID,但是如果从旧数据库转移过来,例如 MongoDB,直接把 ObjectId 替换成 UUID 的话,一般都是新增一个主键然,保留旧主键,并且为旧主键增加索引。但是更好的办法应该是使用前一种方法,增加 shard_id。不过,具体是否更好还是要看业务,增加 shard_id 的好处是服务使用方还是可以直接旧 id 来访问单条数据。

4. 按位反转

// 随手打的不要介意 
// 不是所有语言都能很好处理 64 位整数和二进制运算, 下面用 javascript 做例子

function getNewId(oldId) {
    let newId = 0;
    const MAX_BITS = 51;
    for (let i = 0; i < MAX_BITS; i++) {
        newId *= 2; // newId <<= 1;
        if (oldId & 1) {
            newId |= 1;
        }
        oldId = Math.floor(oldId / 2);
    }
    return newId;
}

还有一种做法做法其实跟 shard_id 差不多,就是把最高位的第 2 到 N + 1 位用来保存hash,原 id 保存在低 (63 - N) 位

出现 HotSpot 的其他因素

1. 索引

Spanner 的索引也是数据表,也就是数索引的设计也会影响写入性能

Table 主键设计好了,但是因为业务需要需要增加二级索引,而二级索引的字段的数据是自增的话,索引表的新数据都会写到同一个 split,从而造成 HotSpot。

2. 父子关系表设计

您可以在一个数据库中定义多个表,而且,如果希望 Cloud Spanner 以物理方式协同定位表的行,从而实现高效检索,您还可以选择定义表之间的父子关系。 https://cloud.google.com/spanner/docs/schema-and-data-model?hl=zh-CN

假设 root table(父表) shops(shop_id, shop_name), 字表 shop_orders(shop_id, order_id) INTERLEAVE IN PARENT shops,这样同一个 shop_id 下的所有订单都会放在同一个 split,就算 shop_orders 表加入了 shard_id 都没没有用的,当同一个店铺高并发写入订单的时候,会造成存放该 shop_id 数据的 split 出现 HotSpot。

父子表适合字表数据相对少的情况,例如一个订单一张发票,那么发票表可以是订单表的子表。

数据库选型考虑

由于 Google Cloud Spanner 是 GCP 托管的服务,存储费对于新旧数据都是一致的,一个电子商务网站,顾客一般不会经常看 1 年前的订单,这时候的订单数据如何可以存放在成本相对小的服务器,可以大大减少云服务费用。

另外一个考虑就是,不是所有应用都一定要用到 Spanner,Google 给出另一个选择合适数据库的方法:

https://cloud.google.com/storage-options/

image.png

图片来自 Google Cloud

参考资料

阅读原文

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容