Google Cloud Spanner 學(xué)習(xí)報告

Google Cloud Spanner 學(xué)習(xí)報告

  • 17 Jan 2019

本人介紹,未使用過 Google Cloud Spanner,不是 DBA本股。

簡介

Google 的 AdWords 曾經(jīng)是靠 MySQL+手工Sharding來支撐,但在擴展和可靠性上不能滿足要求。于是開發(fā)了全局一致性和自動 Sharding 的數(shù)據(jù)庫 Spanner夹纫。

Spanner 帶動了一波云原生數(shù)據(jù)庫的熱潮,云原生數(shù)據(jù)庫的特點是设凹,計算和存儲分離舰讹,增加 node 就可以增加存儲能力和性能;自動分片闪朱;支持分布式事務(wù)月匣。

國內(nèi)的云原生數(shù)據(jù)有阿里云的 云數(shù)據(jù)庫POLARDB,騰訊云的
云數(shù)據(jù)庫 CynosDB奋姿,這兩個數(shù)據(jù)庫的特點還有完全兼容 MySQL锄开,其中 CynosDB 還可以支持 PostgreSQL 10(參考時間 2019年1月17日),現(xiàn)有應(yīng)用無需更改 SDK称诗,減少數(shù)據(jù)庫遷移的成本萍悴。

TrueTime

Spanner 數(shù)據(jù)庫告訴了人們,當(dāng)數(shù)據(jù)容量增加粪狼,分片數(shù)量增加退腥,依然可以享受高性能和事務(wù)全局一致性,依靠的最驚艷的技術(shù)就是 TrueTime再榄。

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

事務(wù)依靠全局一致性的順序 id 來保證事務(wù)執(zhí)行順序的正確性困鸥,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

不同的數(shù)據(jù)庫間做數(shù)據(jù)遷移猬腰,都要理解兩個數(shù)據(jù)庫各自的優(yōu)點鸟废,才能更好的用上新數(shù)據(jù)庫。例如從 MySQL 遷移到 HBase姑荷,如果表設(shè)計一模一樣的話盒延,簡直就是浪費了 Hbase 的特性缩擂,而且因為 Hbase 沒有二級索引(雖然可以簡單設(shè)計一下)可能業(yè)務(wù)性能會下降。

先簡單說一下 Spanner 的存儲架構(gòu)

Spanner 的數(shù)據(jù)都是存放在節(jié)點機器添寺,下面簡稱 node胯盯,而 node 存放分片(split),數(shù)據(jù)在 split 的訪問順序是有序的计露,參考過論文博脑,數(shù)據(jù)在 split 中使用 KV 結(jié)構(gòu)存儲。node 之間的數(shù)據(jù)也是有序的票罐,可以這樣理解:node1{spli1, split2}, node2{split3}, node3{split4, split5, slit 6}叉趣。

第一個問題,順序?qū)懭?HotSpot

數(shù)據(jù)主鍵如果是有序的胶坠,例如用自增 id 或者 MongoDB 的 ObjectId君账,新數(shù)據(jù)很大可能會寫入到第一個或者最后一個split,造成單個 node 的負載超高沈善,而其他 node 很空閑乡数,這樣對于寫性能不能做到增加 node 就增加性能。

Spanner 產(chǎn)品文檔給出了幾種解決辦法:

1. 調(diào)換主鍵順序

因為 spanner 是可以定義多個列來組合稱主鍵闻牡,登錄日志表如原主鍵是 (time, user_id), 因為 time 字段是自增的净赴,可以用 (user_id, time) 來做主鍵。登錄的 user_id 是無序的所以可以把數(shù)據(jù)寫入到盡量多的 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,加快用戶端的訂單查找速度严沥。而根據(jù) shop_id 查找訂單可能是低頻的猜极,能接受的延時稍高。Spanner 文檔是使用 hash() % N 來存儲數(shù)字型 shard_id消玄,我這里只是給出另一種實現(xiàn)跟伏,不一定是最好。

3. 使用 UUID v4

新表設(shè)計可以使用 UUID翩瓜,但是如果從舊數(shù)據(jù)庫轉(zhuǎn)移過來受扳,例如 MongoDB,直接把 ObjectId 替換成 UUID 的話兔跌,一般都是新增一個主鍵然勘高,保留舊主鍵,并且為舊主鍵增加索引。但是更好的辦法應(yīng)該是使用前一種方法华望,增加 shard_id层亿。不過,具體是否更好還是要看業(yè)務(wù)立美,增加 shard_id 的好處是服務(wù)使用方還是可以直接舊 id 來訪問單條數(shù)據(jù)。

4. 按位反轉(zhuǎn)

// 隨手打的不要介意 
// 不是所有語言都能很好處理 64 位整數(shù)和二進制運算, 下面用 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) 位

出現(xiàn) HotSpot 的其他因素

1. 索引

Spanner 的索引也是數(shù)據(jù)表,也就是數(shù)索引的設(shè)計也會影響寫入性能

Table 主鍵設(shè)計好了裕偿,但是因為業(yè)務(wù)需要需要增加二級索引洞慎,而二級索引的字段的數(shù)據(jù)是自增的話,索引表的新數(shù)據(jù)都會寫到同一個 split嘿棘,從而造成 HotSpot劲腿。

2. 父子關(guān)系表設(shè)計

您可以在一個數(shù)據(jù)庫中定義多個表,而且鸟妙,如果希望 Cloud Spanner 以物理方式協(xié)同定位表的行焦人,從而實現(xiàn)高效檢索,您還可以選擇定義表之間的父子關(guān)系重父。 https://cloud.google.com/spanner/docs/schema-and-data-model?hl=zh-CN

假設(shè) root table(父表) shops(shop_id, shop_name), 字表 shop_orders(shop_id, order_id) INTERLEAVE IN PARENT shops花椭,這樣同一個 shop_id 下的所有訂單都會放在同一個 split,就算 shop_orders 表加入了 shard_id 都沒沒有用的房午,當(dāng)同一個店鋪高并發(fā)寫入訂單的時候矿辽,會造成存放該 shop_id 數(shù)據(jù)的 split 出現(xiàn) HotSpot。

父子表適合字表數(shù)據(jù)相對少的情況郭厌,例如一個訂單一張發(fā)票袋倔,那么發(fā)票表可以是訂單表的子表。

數(shù)據(jù)庫選型考慮

由于 Google Cloud Spanner 是 GCP 托管的服務(wù)折柠,存儲費對于新舊數(shù)據(jù)都是一致的宾娜,一個電子商務(wù)網(wǎng)站,顧客一般不會經(jīng)骋鹤撸看 1 年前的訂單碳默,這時候的訂單數(shù)據(jù)如何可以存放在成本相對小的服務(wù)器,可以大大減少云服務(wù)費用缘眶。

另外一個考慮就是嘱根,不是所有應(yīng)用都一定要用到 Spanner,Google 給出另一個選擇合適數(shù)據(jù)庫的方法:

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

image.png

圖片來自 Google Cloud

參考資料

閱讀原文

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末巷懈,一起剝皮案震驚了整個濱河市该抒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌顶燕,老刑警劉巖凑保,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件冈爹,死亡現(xiàn)場離奇詭異,居然都是意外死亡欧引,警方通過查閱死者的電腦和手機频伤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來芝此,“玉大人憋肖,你說我怎么就攤上這事』槠唬” “怎么了岸更?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長膊升。 經(jīng)常有香客問我怎炊,道長,這世上最難降的妖魔是什么廓译? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任评肆,我火速辦了婚禮,結(jié)果婚禮上非区,老公的妹妹穿的比我還像新娘糟港。我一直安慰自己,他們只是感情好院仿,可當(dāng)我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布秸抚。 她就那樣靜靜地躺著,像睡著了一般歹垫。 火紅的嫁衣襯著肌膚如雪剥汤。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天排惨,我揣著相機與錄音吭敢,去河邊找鬼。 笑死暮芭,一個胖子當(dāng)著我的面吹牛鹿驼,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播辕宏,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼畜晰,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了瑞筐?” 一聲冷哼從身側(cè)響起凄鼻,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后块蚌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體闰非,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年峭范,在試婚紗的時候發(fā)現(xiàn)自己被綠了财松。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡纱控,死狀恐怖游岳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情其徙,我是刑警寧澤,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布喷户,位于F島的核電站唾那,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏褪尝。R本人自食惡果不足惜闹获,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望河哑。 院中可真熱鬧避诽,春花似錦、人聲如沸璃谨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽佳吞。三九已至拱雏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間底扳,已是汗流浹背铸抑。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留衷模,地道東北人鹊汛。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像阱冶,于是被迫代替她去往敵國和親刁憋。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,619評論 2 354

推薦閱讀更多精彩內(nèi)容