摘要:?前言 TableStore是阿里云自研的一款分布式NoSQL數(shù)據(jù)庫(kù),提到NoSQL數(shù)據(jù)庫(kù),現(xiàn)在對(duì)很多應(yīng)用研發(fā)來(lái)說(shuō)都已經(jīng)不再陌生。當(dāng)前很多應(yīng)用系統(tǒng)底層不會(huì)再僅僅依賴(lài)于關(guān)系型數(shù)據(jù)庫(kù),而是會(huì)根據(jù)不同的業(yè)務(wù)場(chǎng)景,來(lái)選型使用不同類(lèi)型的數(shù)據(jù)庫(kù),例如緩存型KeyValue數(shù)據(jù)會(huì)存儲(chǔ)在Redis,文檔型數(shù)據(jù)會(huì)存儲(chǔ)在MongoDB,圖數(shù)據(jù)會(huì)存儲(chǔ)在Neo4J等。
前言
TableStore是阿里云自研的一款分布式NoSQL數(shù)據(jù)庫(kù),提到NoSQL數(shù)據(jù)庫(kù),現(xiàn)在對(duì)很多應(yīng)用研發(fā)來(lái)說(shuō)都已經(jīng)不再陌生。當(dāng)前很多應(yīng)用系統(tǒng)底層不會(huì)再僅僅依賴(lài)于關(guān)系型數(shù)據(jù)庫(kù),而是會(huì)根據(jù)不同的業(yè)務(wù)場(chǎng)景,來(lái)選型使用不同類(lèi)型的數(shù)據(jù)庫(kù),例如緩存型KeyValue數(shù)據(jù)會(huì)存儲(chǔ)在Redis,文檔型數(shù)據(jù)會(huì)存儲(chǔ)在MongoDB,圖數(shù)據(jù)會(huì)存儲(chǔ)在Neo4J等。
回顧下NoSQL的發(fā)展歷程,NoSQL誕生于Web 2.0時(shí)代,互聯(lián)網(wǎng)高速發(fā)展的一個(gè)時(shí)代,也帶來(lái)了一次互聯(lián)網(wǎng)數(shù)據(jù)的爆發(fā)。傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù)很難承載如此海量的數(shù)據(jù),需要一種具備高擴(kuò)展能力的分布式數(shù)據(jù)庫(kù)。但基于傳統(tǒng)的關(guān)系數(shù)據(jù)模型,去實(shí)現(xiàn)高可用和可擴(kuò)展的分布式數(shù)據(jù)庫(kù)是非常有挑戰(zhàn)的一件事?;ヂ?lián)網(wǎng)上大部分?jǐn)?shù)據(jù)的數(shù)據(jù)模型很簡(jiǎn)單,沒(méi)必要一概用關(guān)系模型來(lái)建模。如果能打破關(guān)系模型以一種更簡(jiǎn)單的數(shù)據(jù)模型來(lái)對(duì)數(shù)據(jù)建模、弱化事務(wù)和約束、以高可用和可擴(kuò)展為目標(biāo),以此為目標(biāo)設(shè)計(jì)的數(shù)據(jù)庫(kù)能更好的滿(mǎn)足業(yè)務(wù)需求,正是基于此種理念推動(dòng)了NoSQL的發(fā)展。
總結(jié)下,NoSQL的發(fā)展是基于互聯(lián)網(wǎng)時(shí)代對(duì)業(yè)務(wù)的新挑戰(zhàn)以及數(shù)據(jù)庫(kù)的新需求而推動(dòng)的,基于此發(fā)展起來(lái)的NoSQL,有其顯著的特征:
多數(shù)據(jù)模型:為滿(mǎn)足不同數(shù)據(jù)的需求,誕生出了很多不同的數(shù)據(jù)模型,例如KeyValue、Document、Wide Column、Graph以及Time Series等。這是NoSQL數(shù)據(jù)庫(kù)發(fā)展的一個(gè)最顯著特征,打破了關(guān)系模型的約束,選擇一個(gè)多元的發(fā)展方向。數(shù)據(jù)模型的選擇是更加場(chǎng)景化的,更貼近業(yè)務(wù)的實(shí)際需求,能夠做更深層次的優(yōu)化。
高并發(fā)、低延遲:NoSQL數(shù)據(jù)庫(kù)的發(fā)展更多由在線(xiàn)業(yè)務(wù)的需求推動(dòng),其設(shè)計(jì)目標(biāo)更多的是面向在線(xiàn)業(yè)務(wù)提供高并發(fā)、低延遲的訪(fǎng)問(wèn)。
高可擴(kuò)展:為應(yīng)對(duì)爆發(fā)的數(shù)據(jù)量增長(zhǎng),可擴(kuò)展是最核心的設(shè)計(jì)目標(biāo)之一,所以底層架構(gòu)往往在設(shè)計(jì)之初即考慮分布式架構(gòu)。
從DBEngines的發(fā)展趨勢(shì)統(tǒng)計(jì)上也可以看到,各類(lèi)NoSQL數(shù)據(jù)庫(kù)在近幾年都是處于一個(gè)蓬勃發(fā)展的狀態(tài)。阿里云TableStore作為一款分布式NoSQL數(shù)據(jù)庫(kù),在數(shù)據(jù)模型上選擇了多模型的架構(gòu),同時(shí)支持WideColumn和Timeline。
WideColumn模型是由Bigtable提出,后被其他同類(lèi)型系統(tǒng)廣泛應(yīng)用的一種經(jīng)典模型,目前世界上的絕大部分半結(jié)構(gòu)化、結(jié)構(gòu)化數(shù)據(jù)都是存儲(chǔ)在該模型系統(tǒng)中。除了WideColumn模型外,我們推出了另一種全新的數(shù)據(jù)模型:Timeline,Timeline模型是一種用于消息數(shù)據(jù)的新一代模型,適用于IM、Feeds和物聯(lián)網(wǎng)設(shè)備消息下推等消息系統(tǒng)中消息的存儲(chǔ)和同步,目前已經(jīng)開(kāi)始被廣泛使用。接下來(lái),我們?cè)敿?xì)了解下這兩種模型。
?
Wide Column模型
上圖是Wide Column模型的一個(gè)模型圖,為更好的理解這個(gè)模型,我們拿關(guān)系模型來(lái)做一個(gè)對(duì)比。關(guān)系模型可以簡(jiǎn)單的理解為一個(gè)二維的模型,由行列組成,每一行的列固定Schema。所以關(guān)系模型的特征是:二維以及固定Schema,這是一個(gè)最簡(jiǎn)單的理解,拋開(kāi)事務(wù)和約束來(lái)看的話(huà)。Wide Column模型是一個(gè)三維的模型,在行與列二維的基礎(chǔ)上,增加了一個(gè)時(shí)間維度。時(shí)間維度體現(xiàn)在屬性列上,屬性列可以擁有多個(gè)值,每個(gè)值對(duì)應(yīng)一個(gè)Timestamp作為版本。并且每一行是Schema Free的,沒(méi)有強(qiáng)Schema定義。所以Wide Column模型對(duì)比關(guān)系模型,簡(jiǎn)單總結(jié)就是:三維、Schema Free、簡(jiǎn)化事務(wù)和約束。
再詳細(xì)看下這個(gè)模型的組成,有幾個(gè)主要部分:
主鍵(Primary Key):每一行都會(huì)有主鍵,主鍵會(huì)由多列(1-4列)構(gòu)成,主鍵的定義是固定Schema,主鍵的作用主要是唯一區(qū)分一行數(shù)據(jù)。
分區(qū)鍵(Partition Key):主鍵的第一列稱(chēng)為分區(qū)鍵,分區(qū)鍵用于對(duì)表進(jìn)行范圍分區(qū),每個(gè)分區(qū)會(huì)分布式的調(diào)度到不同的機(jī)器上進(jìn)行服務(wù)。在同一個(gè)分區(qū)鍵內(nèi),我們提供跨行事務(wù)。
屬性列(Attribute Column):一行中除開(kāi)主鍵列外,其余都是屬性列。屬性列會(huì)對(duì)應(yīng)多個(gè)值,不同值對(duì)應(yīng)不同的版本,一行可存儲(chǔ)不限個(gè)數(shù)個(gè)屬性列。
版本(Version):每一個(gè)值對(duì)應(yīng)不同的版本,版本的值是一個(gè)時(shí)間戳,用于定義數(shù)據(jù)的生命周期。
數(shù)據(jù)類(lèi)型(Data Type):TableStore支持多種數(shù)據(jù)類(lèi)型,包含String、Binary、Double、Integer和Boolean。
生命周期(Time To Live):每個(gè)表可定義數(shù)據(jù)生命周期,例如生命周期配置為一個(gè)月,則該表數(shù)據(jù)中在一個(gè)月之前寫(xiě)入的數(shù)據(jù)就會(huì)被自動(dòng)清理。數(shù)據(jù)的寫(xiě)入時(shí)間由版本來(lái)決定,版本一般由服務(wù)端在數(shù)據(jù)寫(xiě)入時(shí)根據(jù)服務(wù)器時(shí)間來(lái)定,也可由應(yīng)用自己指定。
最大版本數(shù)(MaxVersion):每個(gè)表可定義每一列最多保存的版本數(shù),用于控制一列的版本的個(gè)數(shù),老版本的超過(guò)個(gè)數(shù)上限的數(shù)據(jù)會(huì)被自動(dòng)清理。
?
Wide Column模型的特色,總結(jié)來(lái)說(shuō)就是:三維結(jié)構(gòu)(行、列和時(shí)間)、寬行、多版本數(shù)據(jù)以及生命周期管理。同時(shí)Wide Column模型在數(shù)據(jù)操作層面,提供兩類(lèi)數(shù)據(jù)訪(fǎng)問(wèn)API,Data API和Stream API。
Data API
關(guān)于Data API的詳細(xì)文檔請(qǐng)參考這里,Data API是標(biāo)準(zhǔn)的數(shù)據(jù)API,提供數(shù)據(jù)的在線(xiàn)讀寫(xiě),包括:
PutRow:新插入一行,如果存在相同行,則覆蓋。
UpdateRow:更新一行,可增加、刪除一行中的屬性列,或者更新已經(jīng)存在的屬性列的值。如果該行不存在,則新插入一行。
DeleteRow:刪除一行。
BatchWriteRow:批量更新多張表的多行數(shù)據(jù),可組合PutRow、UpdateRow和DeleteRow。
GetRow:讀取一行數(shù)據(jù)。
GetRange:范圍掃描數(shù)據(jù),可正序掃描或者逆序掃描。
BatchGetRow:批量查詢(xún)多張表的多行數(shù)據(jù)。
Stream API
在關(guān)系模型數(shù)據(jù)庫(kù)中是沒(méi)有對(duì)數(shù)據(jù)庫(kù)內(nèi)增量數(shù)據(jù)定義標(biāo)準(zhǔn)API的,但是在傳統(tǒng)關(guān)系數(shù)據(jù)庫(kù)的很多應(yīng)用場(chǎng)景中,增量數(shù)據(jù)(binlog)的用途是不可忽視的。這個(gè)在阿里內(nèi)部場(chǎng)景中,有很廣泛的應(yīng)用,并且提供了DRC這類(lèi)中間件將這部分?jǐn)?shù)據(jù)的能力完全挖掘了出來(lái)。將增量數(shù)據(jù)的能力挖掘出來(lái)后,我們可以在技術(shù)架構(gòu)上做很多事:
異構(gòu)數(shù)據(jù)源復(fù)制:MySQL數(shù)據(jù)增量同步到NoSQL,做一個(gè)冷數(shù)據(jù)存儲(chǔ)。
對(duì)接流計(jì)算:可實(shí)時(shí)對(duì)MySQL內(nèi)數(shù)據(jù)做統(tǒng)計(jì),做一些大屏類(lèi)應(yīng)用。
對(duì)接搜索系統(tǒng):可將搜索系統(tǒng)擴(kuò)展為MySQL的二級(jí)索引,增強(qiáng)MySQL內(nèi)數(shù)據(jù)的檢索能力。
?
但即使關(guān)系數(shù)據(jù)庫(kù)的增量數(shù)據(jù)如此有用,業(yè)界也沒(méi)有規(guī)范的API定義來(lái)獲取這部分增量數(shù)據(jù)。TableStore是早早發(fā)覺(jué)了這部分?jǐn)?shù)據(jù)存在的價(jià)值,提供了標(biāo)準(zhǔn)化的API來(lái)將這部分?jǐn)?shù)據(jù)的能力開(kāi)放出來(lái),這就是我們的Stream API(文檔)。
Stream API大致包括:
ListStream:獲取表的Stream,范圍Stream的ID。
DescribeStream:獲取Stream的詳細(xì)信息,拉取Stream內(nèi)Shard列表,以及Shard結(jié)構(gòu)樹(shù)。
GetShardIterator:獲取Shard當(dāng)前增量數(shù)據(jù)的Iterator。
GetStreamRecord:根據(jù)Shard Iterator獲取Shard內(nèi)的增量數(shù)據(jù)。
?
TableStore Stream的實(shí)現(xiàn)會(huì)比MySQL Binlog復(fù)雜很多,因?yàn)門(mén)ableStore本身是一個(gè)分布式的架構(gòu),Stream也是一個(gè)分布式的增量數(shù)據(jù)消費(fèi)框架。Stream的數(shù)據(jù)消費(fèi)必須保序獲取,Stream的Shard與TableStore內(nèi)部的表的分區(qū)一一對(duì)應(yīng),表的分區(qū)會(huì)存在分裂和合并,為保證在分區(qū)分裂和合并后老Shard和新增Shard的數(shù)據(jù)消費(fèi)仍然能保序,我們?cè)O(shè)計(jì)了一套比較精密的機(jī)制。對(duì)于TableStore Stream的設(shè)計(jì),不在這里贅述,我們之后會(huì)發(fā)布更詳細(xì)的設(shè)計(jì)文檔。
當(dāng)前由于Stream內(nèi)部架構(gòu)的復(fù)雜,將這部分復(fù)雜度也引入到了Stream數(shù)據(jù)消費(fèi)側(cè),在用戶(hù)使用Stream API時(shí)并不是那么簡(jiǎn)單。在今年我們也規(guī)劃了一個(gè)全新的數(shù)據(jù)消費(fèi)通道服務(wù),來(lái)簡(jiǎn)化Stream數(shù)據(jù)的消費(fèi),提供更簡(jiǎn)單易用的API,盡情期待。
?
Timeline模型
Timeline模型是我們針對(duì)消息數(shù)據(jù)場(chǎng)景所新創(chuàng)的一個(gè)數(shù)據(jù)模型,它的特色在于能夠滿(mǎn)足消息數(shù)據(jù)場(chǎng)景對(duì)消息保序、海量消息存儲(chǔ)、實(shí)時(shí)同步的特殊需求。

如上圖是Timeline的模型圖,將一張大表內(nèi)的數(shù)據(jù)抽象為多個(gè)Timeline,一個(gè)大表能夠承載的Timeline個(gè)數(shù)無(wú)上限。
Timeline的構(gòu)成主要包括:
Timeline ID:唯一標(biāo)識(shí)Timeline的ID。
Timeline Meta:Timeline的元數(shù)據(jù),元數(shù)據(jù)內(nèi)可包含任意鍵值對(duì)屬性。
Message Sequence:消息隊(duì)列,承載該Timeline下的所有消息。消息在隊(duì)列里有序保存,并且根據(jù)寫(xiě)入順序分配自增的ID。一個(gè)消息隊(duì)列可承載的消息個(gè)數(shù)無(wú)上限,在消息隊(duì)列內(nèi)部可根據(jù)消息ID隨機(jī)定位某條消息,并提供正序或者反序掃描。
Message Entry:消息體,包含消息的具體內(nèi)容,可以包含任意鍵值對(duì)。
?
Timeline的模型邏輯上與消息隊(duì)列有一些相似之處,Timeline類(lèi)似于消息隊(duì)列中的Topic。不同之處在于,TableStore Timeline更側(cè)重Topic的規(guī)模。在即時(shí)通訊場(chǎng)景,每個(gè)用戶(hù)的收件箱和寄件箱都是一個(gè)Topic,在物聯(lián)網(wǎng)消息場(chǎng)景,每個(gè)設(shè)備對(duì)應(yīng)一個(gè)Topic,Topic的量級(jí)會(huì)達(dá)到千萬(wàn)甚至億級(jí)別。TableStore Timeline基于底層的分布式引擎,單表能支持理論無(wú)上限的Timeline(Topic),簡(jiǎn)化隊(duì)列的Pub/Sub模型,支持消息保序、隨機(jī)定位以及正反序掃描,更貼近即時(shí)通訊(IM)、Feeds流以及物聯(lián)網(wǎng)消息系統(tǒng)等海量消息數(shù)據(jù)場(chǎng)景的需求。
?
關(guān)于Timeline模型的起源,可以看下這篇文章 - 《現(xiàn)代IM系統(tǒng)中消息推送和存儲(chǔ)架構(gòu)的實(shí)現(xiàn)》,具體的應(yīng)用可以參考下這篇文章 - 《TableStore Timeline:輕松構(gòu)建千萬(wàn)級(jí)IM和Feed流系統(tǒng)》。
?
Timeline是在去年新推出的一個(gè)數(shù)據(jù)模型,我們還在不斷的打磨?;谶@個(gè)模型,我們已經(jīng)幫助釘釘、菜鳥(niǎo)智能客服、淘票票小聚場(chǎng)、智能設(shè)備管理等業(yè)務(wù)構(gòu)建即時(shí)通訊、Feeds流、物聯(lián)網(wǎng)等領(lǐng)域的消息系統(tǒng),歡迎使用。
?
最后,歡迎加入我們的內(nèi)部釘釘群(群號(hào):11789671)進(jìn)行交流。
本文為云棲社區(qū)原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。
電子發(fā)燒友App
































評(píng)論