本文介紹 dynamo-sql 項目開發(fā)的初衷、設(shè)計目標(biāo)、以及實現(xiàn)要點。
1. no-sql 數(shù)據(jù)庫的標(biāo)準(zhǔn)化需求
眾所周知诵竭,業(yè)界主流的關(guān)系數(shù)據(jù)庫長得普遍類似景描,因為有 SQL 規(guī)范約束,再另類的 DB 系統(tǒng)也不會太過于標(biāo)新立異秀撇。所以超棺,關(guān)系數(shù)據(jù)庫系統(tǒng)通常具備良好的可替換性,從一種 DB 切換到另一種 DB呵燕,一般不必付出太大代價棠绘。
但不同廠商的 no-sql 系統(tǒng)差別巨大,一方面再扭,因為 no-sql 起步比 sql 晚得多氧苍,目前還處于戰(zhàn)國紛爭時代,沒有跡象表明主流 no-sql 可以歸并了泛范。另一方面让虐,主流廠商,尤其在 PaaS 層面提供服務(wù)的廠商罢荡,通常將 no-sql 實施手段與編程語言特性緊密捆綁赡突,典型的如 Google 的 Cloud Datastore,這大大拉低了 no-sql 標(biāo)準(zhǔn)化能力区赵。
對于國內(nèi)用戶惭缰,no-sql 可替換的需求遠比國外強烈,幾個成氣候的云計算平臺不夠中立笼才,像阿里云漱受、騰訊云,自身都是互聯(lián)網(wǎng)大玩家骡送,其經(jīng)營范圍均覆蓋一多半互聯(lián)網(wǎng)業(yè)務(wù)昂羡。還有一家國外的,AWS摔踱,比較中立虐先,技術(shù)也先進,可惜水土不服昌渤,大家選擇 AWS 心里是不安的赴穗,哪天他們經(jīng)營不下去了怎么辦憔四,類似 GAE 退出中國重演的機率其實不低膀息。當(dāng)年筆者花了數(shù)月時間用 GAE 開發(fā)了一個論壇,即將上線了赵,Google 說走就走潜支,投入全都打水漂了。
不過柿汛,事情也沒那么悲觀冗酿。我們做不到 no-sql 廣泛可替換性埠对,降低要求,實現(xiàn)小范圍裁替、有條件的可替換似乎也沒那么難项玛。在公有云領(lǐng)域,亞馬遜處于絕對領(lǐng)先位置弱判,據(jù) Gartner 最近全球云市場份額報告顯示襟沮,AWS 所占份額兩倍于第二名至第十名份額的總和,這是一家獨大的態(tài)勢昌腰。在這一市場格局下开伏,如果 AWS 提供的某項服務(wù)是優(yōu)質(zhì)的、技術(shù)領(lǐng)先的遭商,那么固灵,業(yè)界的技術(shù)標(biāo)準(zhǔn)就該向他看齊,而 AWS DynamoDB 正好滿足此條件劫流。
如果為 DynamoDB 設(shè)計一套通用的 SQL 規(guī)格巫玻,新興云計算廠商推出的 no-sql 又是仿 DynamoDB 設(shè)計的,我們退而求其次的 “可替換性設(shè)計目標(biāo)” 就達到了祠汇。況且大审,針對國內(nèi)市場,新興廠商向老大看齊座哩,保持兼容性徒扶,能從老大那里分流部分用戶,算是不錯的市場策略根穷。
2. 已有 no-sql 數(shù)據(jù)庫的 DSL 設(shè)計
為 no-sql 數(shù)據(jù)庫套一層類 SQL 的 DSL 描述層在業(yè)界較常見姜骡,像 Google 為他的 Cloud Datastore 加了一層 GQL 描述,針對 DynamoDB 業(yè)界也有數(shù)個增設(shè) SQL 層的開源項目屿良。這里圈澈,我先簡單介紹這些 SQL-like 的規(guī)格特色。
Google 的 GQL 只提供 SELECT 查詢尘惧,只讀不寫康栈,我估計它之所以不支持記錄更新,是因為 Datastore 的字段讀寫已融入編程特性喷橙,以對象化方式描述表啥么、記錄、字段贰逾,寫操作是直接的賦值語句悬荣,上下文還融合了事務(wù)處理語句。所以疙剑,讓 GQL 支持?jǐn)?shù)據(jù)庫寫操作反而會變得不方便氯迂。
給 DynamoDB 追加 SQL 的開源項目在 github 能找到五個以上践叠,做得較好有:
DynamoDb.SQL 基于 .Net 平臺,只供查詢嚼蚀,沒支持 update禁灼、delete 等寫操作,DQL 基于 Python轿曙,有查詢匾二,也提供 insert、update拳芙、delete 等寫操作察藐,甚至還提供 create table 操作。dynamodb-sql 基于 Javascript舟扎,設(shè)計功能較全分飞,遺憾的是,功能還沒做完作者停止開發(fā)了睹限。
這些項目總有一些缺陷譬猫,尤其未注重 “通用性” 設(shè)計,在跨 DB 可移植方面考慮得較少羡疗。具體而言染服,像 create table、descript table 這類跨越 DB 很難尋求一致設(shè)計的指令就不該去做叨恨;還有一些專屬特性柳刮,應(yīng)理解為 “配置參數(shù)”,而非表現(xiàn)為 SQL 語言規(guī)格痒钝,做成語言規(guī)格就不容易跨 DB 獲得普遍支持秉颗。
因為缺少現(xiàn)成的,我們就自己動手新做了一個送矩,即 dynamo-sql蚕甥,用 Javascript 開發(fā),已在 github 上開源栋荸,項目主頁在這里菇怀。有關(guān) dynamo-sql 的 SQL 規(guī)格,請參考 這篇介紹 晌块。
3. SQL 與 NO-SQL 的差異
SQL 作為一種領(lǐng)域?qū)S谜Z言(Domain Specific Language爱沟,DSL),之所以在傳統(tǒng)數(shù)據(jù)庫上產(chǎn)生摸袁,無非為了達到 “一致規(guī)格” 與 “簡化應(yīng)用” 兩個目的钥顽,我們?yōu)?DynamoDB 設(shè)計 SQL 也同樣基于這兩個目的义屏。但針對 no-sql 的 DSL 設(shè)計似乎更麻煩些靠汁,因為你面對的是 “非結(jié)構(gòu)化” 的數(shù)據(jù)表蜂大,得針對傳統(tǒng)數(shù)據(jù)庫與 no-sql 數(shù)據(jù)庫的關(guān)鍵差異,有重點的去解決問題蝶怔。
先來對比 SQL 與 no-sql 的差異奶浦,有一個視頻講得很好,SQL vs NoSQL: Battle of the Backends踢星,請自行搬梯訪問澳叉。我截一張圖放給大家看看:
圖中對比的是 Google 的兩類數(shù)據(jù)庫服務(wù),Datastore 是 no-sql沐悦,Cloud SQL 是在云端開放的類似 MySQL 的傳統(tǒng) DB 系統(tǒng)成洗。傳統(tǒng) SQL 在查詢、事務(wù)處理藏否、一致性方面占優(yōu)瓶殃,而在橫向伸展、易管理副签、Schema 變更方面不如 no-sql遥椿。
盡管 MySQL 為應(yīng)對伸展擴容問題,也發(fā)展出 “分片” 等技術(shù)淆储,但本質(zhì)沒變冠场,拿它去解決該用 no-sql 實現(xiàn)的系統(tǒng),就像破漏的船只本砰,無論怎么修補碴裙,都無法從根上解決問題。事實上点额,在微服務(wù)框架體系里青团,什么時候該用 SQL,什么時候該用 no-sql咖楣,劃分標(biāo)準(zhǔn)還是很清晰的督笆,數(shù)據(jù)庫如何選型也實際指導(dǎo)了微服務(wù)如何劃分。一個產(chǎn)品如果沒采用微服務(wù)架構(gòu)诱贿,SQL 與 no-sql 如何選型是個大問題娃肿,而微服務(wù)框架下,在兩大 DB 之間如何選擇就不該成問題珠十。要命的是料扰,某新興公有云服務(wù)商還缺一個像樣的 no-sql 系統(tǒng),手頭只一把錘子焙蹭,于是嘗試用傳統(tǒng)那套東西解決所有問題晒杈,既然都進軍公有云了,還陷在私有云思路里孔厉,遲早會出問題的拯钻。有點扯遠了帖努,前幾天我參加了一個云計算分享會,有點感觸順便提一下粪般。
回到 no-sql 的本質(zhì)拼余,我想,抓住 “分級索引” 特性是問題的關(guān)鍵亩歹。以 DynamoDB 為例匙监,有 “主鍵”,沒 “外鍵”小作,主鍵又有 “分區(qū)鍵” 與 “排序鍵”亭姥,分區(qū)鍵提供全局檢索,相當(dāng)于有兩層表格體系顾稀,第一層解決某條記錄的全局檢索致份,決定把它的內(nèi)容保存到哪個分區(qū)中,第二層則是指定分區(qū)中表格础拨,分區(qū)確定了氮块,在分區(qū)內(nèi)建立的索引稱為 “本地二級索引”,即 LSI诡宗。如果單以主鍵還滿足不了全局查詢的需求滔蝉,那就再建 “全局二級索引”,即 GSI塔沃。
由于索引方式差別巨大蝠引,SQL 與 no-sql 在 DSL 表述時,也表現(xiàn)出巨大差異蛀柴。比如螃概,后者的 DSL 不再支持多索引聯(lián)合查詢,也不支持 join 等復(fù)雜操作鸽疾。不過吊洼,no-sql 在查詢的過濾條件,update 前的判斷條件等制肮,有更豐富支持冒窍。
4. 不過度封裝
AWS-SDK 的 DynamoDB 通過類似如下代碼操作數(shù)據(jù)庫:
dynamodb.getItem(params, function(err,data) {
// ...
});
對于 GET 操作,調(diào)用 dynamodb.getItem()
豺鼻,對于 PUT 操作综液,調(diào)用 dynamodb.putItem()
,其它操作儒飒,如 SELECT谬莹、SCAN、UPDATE、DELETE 等都通過不同 API 調(diào)用實現(xiàn)附帽,各 API 規(guī)格一樣埠戳,都用 params
參數(shù)指明如何操作。所以士葫,我們封裝的 SQL 語句乞而,經(jīng)翻譯送悔,都準(zhǔn)確生成所需的 params
參數(shù)慢显,再由 AWS-SDK 最后實現(xiàn)數(shù)據(jù)庫作業(yè)。
如何封裝 SQL欠啤?我們面臨兩種選擇荚藻,一是簡單處理,近似于直譯洁段,讓 SQL 的能力與 AWS-SDK 提供的接口一一對應(yīng)应狱,二是提供 PaaS 級別的封裝,把易用性再提高一些祠丝。
AWS 的 DynamoDB 按官方的提法疾呻,是 IaaS 層面的服務(wù),與之可對照的是 Google 的 Datastore写半,是 PaaS 服務(wù)岸蜗。這兩種 DB 除了規(guī)格特性不同之外,所謂 IaaS 與 PaaS 的差別叠蝇,無非后者稍多一點封裝而已璃岳,實質(zhì)差別并不大。
最終我們還是選擇了簡單直譯的方式悔捶,如果想多封裝些铃慷,也就下面幾點可改進:
追加事務(wù)處理
設(shè)置事務(wù)起始標(biāo)志,事務(wù)處理中出錯后允許回退蜕该,Google 的 Datastore 支持事務(wù)處理犁柜,功能不如傳統(tǒng)數(shù)據(jù)庫的事務(wù)機制那么強大,但封裝后還是能讓設(shè)計簡化一些的堂淡。在 DynamoDB 現(xiàn)有 API 基礎(chǔ)上封裝對等的事務(wù)機制并不難赁温,因為一致性讀、有條件寫入淤齐、返回寫入前舊值等特性是現(xiàn)成的股囊,增加一些事務(wù)處理規(guī)則,實現(xiàn)起來代碼量不算太大更啄。
不過稚疹,就算提供事務(wù)支持,封裝本身存在風(fēng)險,你屏蔽了一些開發(fā)者該知道的處理過程内狗,當(dāng)系統(tǒng)出異常要定位問題時怪嫌,事務(wù)封裝將成障礙。索引與排序做點優(yōu)化
受限于 DynamoDB 底層機制柳沙,可做的事情不多岩灭。
5. 兼容 S3 Select 查詢
AWS 新近推出 S3 Select 服務(wù),它用一種類似 SQL 的查詢語句赂鲤,直接用一個命令提取 S3 文件噪径,一般是 CSV 數(shù)據(jù)表文件,然后由 S3 實施查詢数初,只返回合乎條件的數(shù)據(jù)集找爱,而不是 CSV 整個文件的內(nèi)容。這項服務(wù)可節(jié)約不少流量成本泡孩,結(jié)合 S3 的靜態(tài)網(wǎng)站功能顯得比較有意義车摄。
既然,我們?yōu)?DynamoDB 封裝了 SQL仑鸥,為什么不把這 SQL 規(guī)格延伸到 S3 呢吮播?讓 DynamoDB 提供強服務(wù) DB,讓 S3 提供弱服務(wù) DB眼俊,形成雙級服務(wù)機制意狠。
如下是查詢 S3 文件 DB 的例子:
SELECT fieldA,fieldB FROM s3/file_db
與查詢 DynamoDB 差別在于,表名要有 "/"
分隔泵琳。此特性目前還沒實現(xiàn)(語法分析已支持)摄职,留以后去做。
不多說了获列,dynamo-sql 項目的代碼量不大谷市,感興趣的童鞋請讀源碼,歡迎各家云服務(wù)商重用該 SQL 規(guī)格击孩,為自家 no-sql 提供封裝迫悠。如需交流請發(fā)郵件:shadow_widget@126.com 。
?