0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

架構(gòu)師日記-從數(shù)據(jù)庫發(fā)展歷程到數(shù)據(jù)結(jié)構(gòu)設(shè)計探析

京東云 ? 來源:jf_75140285 ? 作者:jf_75140285 ? 2024-09-25 11:20 ? 次閱讀

一 數(shù)據(jù)庫發(fā)展史

起初,數(shù)據(jù)的管理方式是文件系統(tǒng),數(shù)據(jù)存儲在文件中,數(shù)據(jù)管理和維護都由程序員完成。后來發(fā)展出樹形結(jié)構(gòu)和網(wǎng)狀結(jié)構(gòu)的數(shù)據(jù)庫,但都存在著難以擴展和維護的問題。直到七十年代,關(guān)系數(shù)據(jù)庫理論的提出,以表格形式組織數(shù)據(jù),數(shù)據(jù)之間存在關(guān)聯(lián)關(guān)系,具有了良好的結(jié)構(gòu)化和規(guī)范化特性,成為主流數(shù)據(jù)庫類型。

先來看一張數(shù)據(jù)庫發(fā)展史圖鑒:

wKgZombzgWmAGMNwAAEKi_BU55I455.png


隨之高并發(fā)大數(shù)據(jù)時代的來臨,數(shù)據(jù)庫按照各種應(yīng)用場景進行了更細粒度的拆分和演進,數(shù)據(jù)庫細分領(lǐng)域的典型代表:

類型 產(chǎn)品代表 適用場景
層次數(shù)據(jù)庫(NDB) IMS/IDMS 以樹形結(jié)構(gòu)組織數(shù)據(jù),數(shù)據(jù)之間存在父子關(guān)系,查詢速度快,但難以擴展和維護
關(guān)系型數(shù)據(jù)庫(RDBMS) Oracle/MySQL 事務(wù)的一致性需求場景
鍵值數(shù)據(jù)庫(KVDB) Redis/Memcached 針對高性能并發(fā)讀寫場景
文檔數(shù)據(jù)庫(DDB) MongoDB/CouchDB 針對海量復(fù)雜數(shù)據(jù)訪問場景
圖數(shù)據(jù)庫(GDB) Neo4j 以點、邊為基礎(chǔ)存儲單元,高效存儲、查詢圖數(shù)據(jù)場景
時序數(shù)據(jù)庫(TSDB) InfluxDB/OpenTSDB 針對時序數(shù)據(jù)的持久化和多維度的聚合查詢等場景
對象數(shù)據(jù)庫(ODB) Db4O 支持完整的面向?qū)ο?OO)概念和控制機制,目前使用場景較少
索引擎(SE) ElasticSearch/Solr 適合于以搜索為主的業(yè)務(wù)場景
列數(shù)據(jù)庫(WCDB) HBase/ClickHouse 分布式存儲的海量數(shù)據(jù)存儲和查詢場景
XML數(shù)據(jù)庫(NXD) MarkLogic 支持對XML格式文檔進行存儲和查詢等操作場景
內(nèi)容倉庫(CDB) Jackrabbit 大規(guī)模高性能的內(nèi)容倉庫

二 數(shù)據(jù)庫名詞概念

RDBS

1970年的6月,IBM 公司的研究員埃德加·考特 (Edgar Frank Codd) 發(fā)表了那篇著名的《大型共享數(shù)據(jù)庫數(shù)據(jù)的關(guān)系模型》(A Relational Model of Data for Large Shared Data Banks)的論文,拉開了關(guān)系型數(shù)據(jù)庫(Relational DataBase Server)軟件革命的序幕(之前是層次模型和網(wǎng)狀模型數(shù)據(jù)庫為主)。直到現(xiàn)在,關(guān)系型數(shù)據(jù)庫在基礎(chǔ)軟件應(yīng)用領(lǐng)域仍是最主要的數(shù)據(jù)存儲方式之一。

關(guān)系型數(shù)據(jù)庫建立在關(guān)系型數(shù)據(jù)模型的基礎(chǔ)上,是借助于集合代數(shù)等數(shù)學(xué)概念和方法來處理數(shù)據(jù)的數(shù)據(jù)庫。在關(guān)系型數(shù)據(jù)庫中,實體以及實體間的聯(lián)系均由單一的結(jié)構(gòu)類型來表示,這種邏輯結(jié)構(gòu)是一張二維表。關(guān)系型數(shù)據(jù)庫以行和列的形式存儲數(shù)據(jù),這一系列的行和列被稱為表,一組表組成了數(shù)據(jù)庫。

NoSQL

NoSQL(Not Only SQL) 數(shù)據(jù)庫也即非關(guān)系型數(shù)據(jù)庫,它是在大數(shù)據(jù)的時代背景下產(chǎn)生的,它可以處理分布式、規(guī)模龐大、類型不確定、完整性沒有保證的“雜亂”數(shù)據(jù),這是傳統(tǒng)的關(guān)系型數(shù)據(jù)庫遠遠不能勝任的。NoSQL數(shù)據(jù)庫并沒有一個統(tǒng)一的模型,是以犧牲事務(wù)機制和強一致性機制,來獲取更好的分布式部署和橫向擴展能力,使其在不同的應(yīng)用場景下,對特定業(yè)務(wù)數(shù)據(jù)具有更強的處理性能。常用數(shù)據(jù)模型示例如下:

類型 產(chǎn)品代表 應(yīng)用場景 數(shù)據(jù)模型 優(yōu)缺點
鍵值數(shù)據(jù)庫 Redis/Memcached 內(nèi)容緩存,如會話,配置文件等; 頻繁讀寫,擁有簡單數(shù)據(jù)模型的應(yīng)用; 鍵值對,通過散列表來實現(xiàn) 優(yōu)點: 擴展性和靈活性好,性能高; 缺點: 數(shù)據(jù)無結(jié)構(gòu)化,只能通過鍵來查詢
列簇數(shù)據(jù)庫 HBase/ClickHouse 分布式數(shù)據(jù)存儲管理 以列簇存儲,將同一列存在一起 優(yōu)點: 簡單,擴展性強,查詢速度快 缺點: 功能局限,不支持事務(wù)的強一致性
文檔數(shù)據(jù)庫 MongoDB/CouchDB Web應(yīng)用,存儲面向文檔或半結(jié)構(gòu)化數(shù)據(jù) 鍵值對,value是JSON結(jié)構(gòu)文檔 優(yōu)點: 數(shù)據(jù)結(jié)構(gòu)靈活 缺點: 缺乏統(tǒng)一查詢語法
圖形數(shù)據(jù)庫 Neo4j/InfoGrid 社交網(wǎng)絡(luò),應(yīng)用監(jiān)控,推薦系統(tǒng)等專注構(gòu)建關(guān)系圖譜 圖結(jié)構(gòu) 優(yōu)點: 支持復(fù)雜的圖形算法 缺點: 復(fù)雜性高,支持數(shù)據(jù)規(guī)模有限

NewSQL

NewSQL 是一類新的關(guān)系型數(shù)據(jù)庫, 是各種新的可擴展和高性能的數(shù)據(jù)庫的簡稱。它不僅具有 NoSQL 數(shù)據(jù)庫對海量數(shù)據(jù)的存儲管理能力,同時還保留了傳統(tǒng)數(shù)據(jù)庫支持的 ACID 和 SQL 特性,典型代表有TiDB和OceanBase。

OLTP

聯(lián)機事務(wù)處理過程(On-Line Transaction Processing):也稱為面向交易的處理過程,其基本特征是前臺接收的用戶數(shù)據(jù)可以立即傳送到計算中心進行處理,并在很短的時間內(nèi)給出處理結(jié)果,是對用戶操作快速響應(yīng)的方式之一。

OLAP

聯(lián)機分析處理(On-Line Analytical Processing)是一種面向數(shù)據(jù)分析的處理過程,它使分析人員能夠迅速、一致、交互地從各個方面觀察信息,以達到深入理解數(shù)據(jù)的目的。它具有FASMI(Fast Analysis of Shared Multidimensional Information),即共享多維信息的快速分析的特征。

關(guān)于OLTP和OLAP的區(qū)別,借用一張表格對比如下:

wKgaombzgWyAJH29AAgOeEz2uC8350.png

HTAP

HTAP (Hybrid Transactional/Analytical Processing) 混合型數(shù)據(jù)庫基于新的計算存儲框架,能夠同時支撐OLTP和OLAP場景,避免傳統(tǒng)架構(gòu)中大量數(shù)據(jù)交互造成的資源浪費和沖突。

三 領(lǐng)域數(shù)據(jù)庫

列式數(shù)據(jù)庫

傳統(tǒng)的以行形式保存的數(shù)據(jù)主要滿足OLTP應(yīng)用,列形式保存的數(shù)據(jù)主要滿足以查詢?yōu)橹鞯腛LAP應(yīng)用。在列式數(shù)據(jù)庫中,數(shù)據(jù)按列存儲,而每個列中的數(shù)據(jù)類型相同。這種存儲方式使列式數(shù)據(jù)庫能夠更高效地處理大量的數(shù)據(jù),特別是需要進行大規(guī)模的數(shù)據(jù)分析和處理時(如金融、醫(yī)療、電信、能源、物流等行業(yè))。

兩種存儲結(jié)構(gòu)的區(qū)別如下圖:

wKgZombzgW-ATGBSAACjp-vegrw467.png


列式數(shù)據(jù)庫的主要優(yōu)點:

?更高的壓縮比率:由于每個列中的數(shù)據(jù)類型相同,列式數(shù)據(jù)庫可以使用更高效的壓縮算法來壓縮數(shù)據(jù)(壓縮比可達到5~20倍),從而減少存儲空間的使用。

?更快的查詢速度:列式數(shù)據(jù)庫可以只讀取需要的列,而不需要讀取整行數(shù)據(jù),從而加快查詢速度。

?更好的擴展性:列式數(shù)據(jù)庫可以更容易地進行水平擴展,即增加更多的節(jié)點和服務(wù)器來處理更大規(guī)模的數(shù)據(jù)。

?更好的數(shù)據(jù)分析支持:由于列式數(shù)據(jù)庫可以處理大規(guī)模的數(shù)據(jù),它可以支持更復(fù)雜的數(shù)據(jù)分析和處理操作,例如數(shù)據(jù)挖掘、機器學(xué)習(xí)等。

列式數(shù)據(jù)庫的主要缺點:

?更慢的寫入速度:由于數(shù)據(jù)是按列存儲,每次寫入都需要寫入整個列,而不是單個行,因此寫入速度可能較慢。

?更復(fù)雜的數(shù)據(jù)模型:由于數(shù)據(jù)是按列存儲,數(shù)據(jù)模型可能比行式數(shù)據(jù)庫更復(fù)雜,需要更多的設(shè)計和開發(fā)工作。

列式數(shù)據(jù)庫的應(yīng)用場景:

?金融:金融行業(yè)的交易數(shù)據(jù)和市場數(shù)據(jù),例如股票價格、外匯匯率、利率等。列式數(shù)據(jù)庫可以更快速地處理這些數(shù)據(jù),并且支持更復(fù)雜的數(shù)據(jù)分析和處理操作,例如風(fēng)險管理、投資分析等。

?醫(yī)療:醫(yī)療行業(yè)的病歷數(shù)據(jù)、醫(yī)療圖像和實驗數(shù)據(jù)等。列式數(shù)據(jù)庫可以更高效地存儲和處理這些數(shù)據(jù),并且支持更復(fù)雜的醫(yī)學(xué)研究和分析操作。

?電信:電信行業(yè)的用戶數(shù)據(jù)和通信數(shù)據(jù),例如電話記錄、短信記錄、網(wǎng)絡(luò)流量等。列式數(shù)據(jù)庫可以更快速地處理這些數(shù)據(jù),并且支持更復(fù)雜的用戶行為分析和網(wǎng)絡(luò)優(yōu)化操作。

?能源:能源行業(yè)的傳感器數(shù)據(jù)、監(jiān)測數(shù)據(jù)和生產(chǎn)數(shù)據(jù)等。列式數(shù)據(jù)庫可以更高效地存儲和處理這些數(shù)據(jù),并且支持更復(fù)雜的能源管理和控制操作。

?物流:物流行業(yè)的運輸數(shù)據(jù)、庫存數(shù)據(jù)和訂單數(shù)據(jù)等。列式數(shù)據(jù)庫可以更快速地處理這些數(shù)據(jù),并且支持更復(fù)雜的物流管理和優(yōu)化操作。

總之,列式數(shù)據(jù)庫是一種高效處理大規(guī)模數(shù)據(jù)的數(shù)據(jù)庫管理系統(tǒng),但需要權(quán)衡寫入速度、數(shù)據(jù)模型復(fù)雜度和成本等因素。 隨著傳統(tǒng)關(guān)系型數(shù)據(jù)庫與新興的分布式數(shù)據(jù)庫不斷的發(fā)展,列式存儲與行式存儲會不斷融合,數(shù)據(jù)庫系統(tǒng)呈現(xiàn)雙模式數(shù)據(jù)存放方式。

時序數(shù)據(jù)庫

時序數(shù)據(jù)庫全稱為時間序列數(shù)據(jù)庫 ( Time Series Database),用于存儲和管理時間序列數(shù)據(jù)的專業(yè)化數(shù)據(jù)庫,是優(yōu)化用于攝取、處理和存儲時間戳數(shù)據(jù)的數(shù)據(jù)庫。其跟常規(guī)的關(guān)系數(shù)據(jù)庫SQL相比,最大的區(qū)別在于:時序數(shù)據(jù)庫是以時間為索引的規(guī)律性時間間隔記錄的數(shù)據(jù)庫。

時序數(shù)據(jù)庫在物聯(lián)網(wǎng)和互聯(lián)網(wǎng)應(yīng)用程序監(jiān)控(APM)等場景應(yīng)用比較多,以監(jiān)控數(shù)據(jù)采集來舉例,如果數(shù)據(jù)監(jiān)控數(shù)據(jù)采集時間間隔是1s,那一個監(jiān)控項每天會產(chǎn)生86400個數(shù)據(jù)點,若有10000個監(jiān)控項,則一天就會產(chǎn)生864000000個數(shù)據(jù)點。在物聯(lián)網(wǎng)場景下,這個數(shù)字會更大,整個數(shù)據(jù)的規(guī)模,是TB甚至是PB級的。

時序數(shù)據(jù)庫發(fā)展史:

wKgaombzgXCATS6iAAEi8IHIR6s504.png


當(dāng)下最常見的Kubernetes容器管理系統(tǒng)中,通常會搭配普羅米修斯(Prometheus)進行監(jiān)控,Prometheus就是一套開源的監(jiān)控&報警&時間序列數(shù)據(jù)庫的組合。

圖數(shù)據(jù)庫

圖數(shù)據(jù)庫(Graph Database)是基于圖論實現(xiàn)的一種新型NoSQL數(shù)據(jù)庫。它的數(shù)據(jù)存儲結(jié)構(gòu)和數(shù)據(jù)的查詢方式都是以圖論為基礎(chǔ)的。圖論中圖的基本元素為節(jié)點和邊,在圖數(shù)據(jù)庫中對應(yīng)的就是節(jié)點和關(guān)系。

圖數(shù)據(jù)庫在反欺詐多維關(guān)聯(lián)分析場景,社交網(wǎng)絡(luò)圖譜,企業(yè)關(guān)系圖譜等場景中可以做一些非常復(fù)雜的關(guān)系查詢。這是由于圖數(shù)據(jù)結(jié)構(gòu)表現(xiàn)的是實體聯(lián)系本身,它表現(xiàn)了現(xiàn)實世界中事物聯(lián)系的本質(zhì),它的聯(lián)系在節(jié)點創(chuàng)建時就已經(jīng)建立,所以在查詢中能以快捷的路徑返回關(guān)聯(lián)數(shù)據(jù),從而表現(xiàn)出非常高效的查詢性能。

目前市面上較為流行的圖數(shù)據(jù)庫產(chǎn)品有以下幾種:

wKgZombzgXGAeA3cAAPTliqtr4I460.png


與傳統(tǒng)的關(guān)系數(shù)據(jù)庫相比,圖數(shù)據(jù)庫具有以下優(yōu)點:

1.更快的查詢速度:圖數(shù)據(jù)庫可以快速遍歷圖數(shù)據(jù),找到節(jié)點之間的關(guān)聯(lián)和路徑,因此查詢速度更快。

2.更好的擴展性:圖數(shù)據(jù)庫可以輕松地擴展到大規(guī)模的數(shù)據(jù)集,因為它們可以分布式存儲和處理數(shù)據(jù)。

3.更好的數(shù)據(jù)可視化:圖數(shù)據(jù)庫可以將數(shù)據(jù)可視化為圖形,使用戶更容易理解和分析數(shù)據(jù)。

4.更好的數(shù)據(jù)一致性:圖數(shù)據(jù)庫可以確保數(shù)據(jù)的一致性,因為它們可以在節(jié)點和邊之間建立強制性的關(guān)系。

四 數(shù)據(jù)結(jié)構(gòu)設(shè)計

前面簡單介紹了數(shù)據(jù)庫相關(guān)的基礎(chǔ)知識,下面再介紹幾種我們常見的數(shù)據(jù)結(jié)構(gòu)設(shè)計相關(guān)的應(yīng)用實踐:拉鏈表,位運算和環(huán)形隊列。

4.1 拉鏈表

拉鏈表是一種數(shù)據(jù)倉庫中常用的數(shù)據(jù)模型,用于記錄維度數(shù)據(jù)的變化歷史。我們以一個人員變動的場景舉例,假設(shè)有一個員工信息表,其中包含了員工的姓名、工號、職位、部門、入職時間等信息。如果需要記錄員工的變動情況,就可以使用拉鏈表來實現(xiàn)。

首先,在員工信息表的基礎(chǔ)上新增兩個字段:生效時間和失效時間。當(dāng)員工信息發(fā)生變動時,不再新增一條記錄,而是修改原有記錄的失效時間,同時新增一條新的記錄。如下表所示:

姓名 工號 職位 部門 入職時間 生效時間 失效時間
張三 001 經(jīng)理 技術(shù) 2010-01-01 2010-01-01 2012-12-31
張三 001 總監(jiān) 技術(shù) 2013-01-01 2013-01-01 2015-12-31
張三 001 總經(jīng)理 技術(shù) 2016-01-01 2016-01-01 9999-12-31

這里的生效時間指的是該記錄生效的時間,失效時間指的是該記錄失效的時間。例如,張三最初是技術(shù)部經(jīng)理,生效時間為入職時間,失效時間為2012年底,之后晉升為技術(shù)部總監(jiān),生效時間為2013年初,失效時間為2015年底,最后又晉升為技術(shù)部總經(jīng)理,生效時間為2016年初,失效時間為9999年底。

通過這種方式,可以記錄員工變動的歷史信息,并能夠方便地查詢某個時間點的員工信息。例如,如果需要查詢張三在2014年的職位和部門信息,只需查詢生效時間小于2014年且失效時間大于2014年的記錄即可。

拉鏈表通常包括以下幾個字段:

1.主鍵:唯一標(biāo)識每個記錄的字段,通常是一個或多個列的組合。 2.生效時間:記錄的生效時間,即該記錄開始生效的時間。 3.失效時間:記錄的失效時間,即該記錄失效的時間。 4.版本號:記錄的版本號,用于標(biāo)識該記錄的版本。 5.其他維度屬性:記錄的其他維度屬性,如客戶名、產(chǎn)品名、員工名等。

當(dāng)一個記錄的維度屬性發(fā)生變化時,不再新增一條記錄,而是修改原有記錄的失效時間,同時新增一條新的記錄。新記錄的生效時間為變化的時間,失效時間為9999年底。這樣就能夠記錄每個維度屬性的歷史變化信息,同時保證查詢時能夠正確獲取某個時間點的維度屬性信息。

拉鏈表與傳統(tǒng)的流水表相比,它們的主要區(qū)別在于:

1.數(shù)據(jù)結(jié)構(gòu)不同:流水表是一張只有新增和更新操作的表,每次更新都會新增一條記錄,記錄中包含了所有的歷史信息。而拉鏈表則是一張有新增、更新和刪除操作的表,每個記錄都有一個生效時間段和失效時間段,記錄的歷史信息通過時間段的變化來體現(xiàn)。

2.查詢方式不同:流水表的查詢方式是基于時間點的查詢,即查詢某個時間點的記錄信息。而拉鏈表的查詢方式是基于時間段的查詢,即查詢某個時間段內(nèi)的記錄信息。

3.存儲空間不同:由于流水表需要記錄所有歷史信息,所以存儲空間相對較大。而拉鏈表只記錄生效時間段和失效時間段,所以存儲空間相對較小。

4.數(shù)據(jù)更新方式不同:流水表只有新增和更新操作,每次更新都會新增一條記錄,不會對原有記錄進行修改。而拉鏈表有新增、更新和刪除操作,每次更新會修改原有記錄的失效時間,同時新增一條新的記錄。

4.2 巧用位運算

借助于計算機位運算的特性,可以巧妙的解決某些特定問題,使實現(xiàn)更加優(yōu)雅,節(jié)省存儲空間的同時,也可以提高運行效率,典型應(yīng)用場景:壓縮存儲、位圖索引、數(shù)據(jù)加密、圖形處理和狀態(tài)判斷等,下面介紹幾個典型案例。

4.2.1 位運算

?使用位運算實現(xiàn)開關(guān)和多選項疊加(資源權(quán)限)等應(yīng)用場景。一個int類型有32個位,理論上可以表示32個開關(guān)狀態(tài)或業(yè)務(wù)選項;以用戶每個月的簽到場景舉例:用一個int字段來表示用戶一個月的簽到情況,0表示未簽到,1表示簽到。想知道某一天是否簽到,則只需要判斷對應(yīng)的比特位上是否為1。計算一個月累計簽到了多少次,只需要統(tǒng)計有多少個比特位為1就可以了。這種設(shè)計巧妙的數(shù)據(jù)存儲結(jié)構(gòu)在后面的位圖(BitMap)中,還會進行更為詳細的介紹。

wKgaombzgXKAeh5_AABxEi1PHo8738.png


?使用位運算實現(xiàn)業(yè)務(wù)優(yōu)先級計算:

public abstract class PriorityManager { // 定義業(yè)務(wù)優(yōu)先級常量 public static final int PRIORITY_LOW = 1; // 二進制:001 public static final int PRIORITY_NORMAL = 2; // 二進制:010 public static final int PRIORITY_HIGH = 4; // 二進制:100 // 定義用戶權(quán)限常量 public static final int PERMISSION_READ = 1; // 二進制:001 public static final int PERMISSION_WRITE = 2; // 二進制:010 public static final int PERMISSION_DELETE = 4;// 二進制:100 // 定義用戶權(quán)限和業(yè)務(wù)優(yōu)先級的組合值 public static final int PERMISSION_LOW_PRIORITY = PRIORITY_LOW | PERMISSION_READ; // 二進制:001 | 001 = 001 public static final int PERMISSION_NORMAL_PRIORITY = PRIORITY_NORMAL | PERMISSION_READ | PERMISSION_WRITE; // 二進制:010 | 001 | 010 = 011 public static final int PERMISSION_HIGH_PRIORITY = PRIORITY_HIGH | PERMISSION_READ | PERMISSION_WRITE | PERMISSION_DELETE; // 二進制:100 | 001 | 010 | 100 = 111 // 判斷用戶權(quán)限是否滿足業(yè)務(wù)優(yōu)先級要求 public static boolean checkPermission(int permission, int priority) { return (permission & priority) == priority; } }

?其它使用位運算的典型場景:HashMap中的隊列長度的設(shè)計和線程池ThreadPoolExcutor中使用AtomicInteger字段ctl,存儲當(dāng)前線程池狀態(tài)和線程數(shù)量(高3位表示當(dāng)前線程的狀態(tài),低29位表示線程的數(shù)量)。

4.2.2 BitMap

位圖(BitMap)是一種常用的數(shù)據(jù)結(jié)構(gòu),在索引,數(shù)據(jù)壓縮等方面有廣泛應(yīng)用?;舅枷刖褪怯靡粋€bit位來標(biāo)記某個元素對應(yīng)的Value,而Key即是該元素。由于采用了Bit為單位來存儲數(shù)據(jù),因此可以大大節(jié)省存儲空間,是少有的既能保證存儲空間又能保證查找速度的數(shù)據(jù)結(jié)構(gòu)(而不必空間換時間)。

舉個例子,假設(shè)有這樣一個需求:在20億個隨機整數(shù)中找出某個數(shù)m是否存在其中,并假設(shè)32位操作系統(tǒng),4G內(nèi)存,在Java中,int占4字節(jié),1字節(jié)=8位(1 byte = 8 bit)。

?如果每個數(shù)字用int存儲,那就是20億個int,因而占用的空間約為 (2000000000*4/1024/1024/1024)≈7.45G

?如果按位存儲就不一樣了,20億個數(shù)就是20億位,占用空間約為 (2000000000/8/1024/1024/1024)≈0.233G

存儲空間可以壓縮節(jié)省31倍!那么它是如何通過二進制位實現(xiàn)數(shù)字標(biāo)記的呢? 其原理是用每個二進制位(下標(biāo))表示一個真實數(shù)字,0表示不存在,1表示存在,這樣我們可以很容易表示{1,2,4,6}這幾個數(shù):

wKgZombzgXOAQytfAACIntPSF1Y344.png


計算機內(nèi)存分配的最小單位是字節(jié),也就是8位,那如果要表示{12,13,15}怎么辦呢?可以另申請一個字節(jié)b[1]:

wKgaombzgXSAE9hYAAFUD-n8WvA923.png


通過一個二維數(shù)組來實現(xiàn)位數(shù)疊加,1個int占32位,那么我們只需要申請一個int數(shù)組長度為 int index[1+N/32] 即可存儲,其中N表示要存儲的這些數(shù)中的最大值:

index[0]:可以表示0~31

index[1]:可以表示32~63

index[2]:可以表示64~95

以此類推...如此一來,給定任意整數(shù)M,那么M/32就得到下標(biāo),M%32就知道它在此下標(biāo)的哪個位置。

BitMap數(shù)據(jù)結(jié)構(gòu)通常用于以下場景:

1.壓縮存儲大量布爾值:BitMap可以有效地壓縮大量的布爾值,從而減少內(nèi)存的使用;

2.快速判斷一個元素是否存在:BitMap可以快速地判斷一個元素是否存在,只需要查找對應(yīng)的位即可;

3.去重:BitMap可以用于去重操作,將元素作為索引,將對應(yīng)的位設(shè)置為1,重復(fù)元素只會對應(yīng)同一個位,從而實現(xiàn)去重;

4.排序:BitMap可以用于排序,將元素作為索引,將對應(yīng)的位設(shè)置為1,然后按照索引順序遍歷位數(shù)組,即可得到有序的元素序列;

5.ElasticSearch和Solr等搜索引擎中,在設(shè)計搜索剪枝時,需要保存已經(jīng)搜索過的歷史信息,可以使用位圖減小歷史信息數(shù)據(jù)所占空間;

4.2.3 布隆過濾器

位圖(Bitmap)這種數(shù)據(jù)存儲結(jié)構(gòu),如果數(shù)據(jù)量大到一定程度,比如64bit類型的數(shù)據(jù),簡單算一下存儲空間就知道,海量硬件資源要求,已經(jīng)不太現(xiàn)實了:

wKgZombzgXaAWHqYAAAhJgzDFV0545.png


所以另一個著名的工業(yè)實現(xiàn) -布隆過濾器(Bloom Filter)出現(xiàn)了。如果說BitMap對于每一個可能的整型值,通過直接尋址的方式進行映射,相當(dāng)于使用了一個哈希函數(shù),那布隆過濾器就是引入了k ( k > 1 )個相互獨立的哈希函數(shù),保證在給定的空間和誤判率情況下,完成元素判重的過程。下圖中是k = 3 時的布隆過濾器:

wKgaombzgXeAKiJ4AAFUuAG3Be8804.png


布隆過濾器的內(nèi)部依賴于哈希算法,當(dāng)檢測某一條數(shù)據(jù)是否見過時,有一定概率出現(xiàn)假陽性(False Positive),但一定不會出現(xiàn)假陰性(False Negative)。也就是說,當(dāng) 布隆過濾器認為一條數(shù)據(jù)出現(xiàn)過,那么該條數(shù)據(jù)很可能出現(xiàn)過;但如果布隆過濾器認為一條數(shù)據(jù)沒出現(xiàn)過,那么該條數(shù)據(jù)一定沒出現(xiàn)過。布隆過濾器通過引入一定錯誤率,使得海量數(shù)據(jù)判重在可以接受的內(nèi)存代價中得以實現(xiàn)。

上圖中,x,y,z經(jīng)由哈希函數(shù)映射將各自在Bitmap中的3個位置置為1,當(dāng)w出現(xiàn)時,僅當(dāng)3個標(biāo)志位都為1時,才表示w在集合中。圖中所示的情況,布隆過濾器將判定w不在集合中。

常見實現(xiàn)

?Java中Guava工具包中實現(xiàn);

?Redis 4.0開始以插件形式提供布隆過濾器功能;

適用場景

?網(wǎng)頁爬蟲對URL的去重,避免爬去相同的URL地址,比如Chrome瀏覽器就是使用了一個布隆過濾器識別惡意鏈接;

?垃圾郵件過濾,從數(shù)十億個垃圾郵件列表中判斷某郵箱是否是殺垃圾郵箱;

?解決數(shù)據(jù)庫緩存擊穿,黑客攻擊服務(wù)器時,會構(gòu)建大量不存在于緩存中的key向服務(wù)器發(fā)起請求,在數(shù)據(jù)量足夠大的時候,頻繁的數(shù)據(jù)庫查詢會導(dǎo)致掛機;

?谷歌Bigtable、Apache HBase、Apache Cassandra和PostgreSQL使用布隆過濾器來減少對不存在的行或列的磁盤查找;

?秒殺系統(tǒng),查看用戶是否重復(fù)購買;

4.2.4 小結(jié)

?位運算有著執(zhí)行速度快,占用空間小,代碼實現(xiàn)簡潔等優(yōu)點,往往能起到四兩撥千斤的效果。同樣也有著代碼可讀性差,使用范圍和可維護性受限等不足;

?在BitMap中,占用空間大小還與實際應(yīng)用場景有關(guān),這種結(jié)構(gòu)無法容忍誤判,只能判斷一個元素是否存在,如果數(shù)據(jù)離散度過高,空間利用率反而更低;

?布隆過濾器則有著空間利用率高,可以容忍一定的誤判率的優(yōu)點。與BitMap相比,也存在著無法刪除元素,誤判率無法達到0等不足;

4.3 環(huán)形隊列

環(huán)形隊列是一種用于表示一個固定尺寸、頭尾相連的數(shù)據(jù)結(jié)構(gòu),很適合緩存數(shù)據(jù)流。在通信開發(fā)(Socket,TCP/IP,RPC開發(fā)),在內(nèi)核的進程間通信(IPC),視頻音頻播放等各種場景中,都有其身影。日常開發(fā)過程中使用的Dubbo、Netty、Akka、Quartz、ZooKeeper 、Kafka等各種中間件,也都有環(huán)形隊列的思想。下面介紹兩種常用的環(huán)形數(shù)據(jù)結(jié)構(gòu):Hash環(huán)和時間輪。

4.3.1 一致性Hash環(huán)

先來看一下,典型Hash算法結(jié)構(gòu)如下:

wKgZombzgXqABbo5AABV91C96Us090.png


以上圖Hash策略為例,當(dāng)節(jié)點數(shù)N發(fā)生變化的時候 之前所有的 hash映射幾乎全部失效,如果集群是無狀態(tài)的服務(wù),倒是沒什么事情,但是如果是分布式緩存這種場景,就會導(dǎo)致比較嚴重的問題。比如 Key1原本是路由到Node1上,命中緩存的Value1數(shù)據(jù)。但是當(dāng)N節(jié)點變化后,Key1可能就路由到了Node2節(jié)點,這就產(chǎn)生了緩存數(shù)據(jù)無法命中的問題。而無論是機器故障還是緩存擴容,都會導(dǎo)致節(jié)點數(shù)的變化。

如何解決上面場景的問題呢?就是接下來介紹的一致性Hash算法。

一致性哈希將整個哈希值空間組織成一個虛擬的圓環(huán),假設(shè)某哈希函數(shù)H的值空間為0-2^32-1(即哈希值是一個32位無符號整型),所有的輸入值都被映射到 0-2^32-1 之間,組成一個圓環(huán)。整個哈希空間環(huán)如下:

wKgaombzgXuAYnTRAAD_8hIxZTE834.png


路由數(shù)據(jù)的過程如下:將數(shù)據(jù)key使用相同的函數(shù)Hash計算出哈希值,并確定此數(shù)據(jù)在環(huán)上的位置,從此位置沿環(huán)順時針“行走”,遇到的第一個節(jié)點就是其應(yīng)該定位到的服務(wù)器。如果某個節(jié)點的服務(wù)器故障,其影響范圍也不再是所有集群,而是限定在故障節(jié)點與其上游節(jié)點的部分區(qū)域。

當(dāng)某個節(jié)點宕機后,原本屬于它的請求都會被重新hash映射到下游節(jié)點,會突然造成下游節(jié)點壓力過大有可能也會造成下游節(jié)點宕機,從而容易形成雪崩,為此引入了虛擬節(jié)點來解決這個問題。

根據(jù)Node節(jié)點生成很多的虛擬節(jié)點分布在圓環(huán)上,,一個真實節(jié)點映射對應(yīng)多個虛擬節(jié)點。這樣當(dāng)某個節(jié)點掛了后原本屬于它的請求,會被均衡的分布到其他節(jié)點上降低了產(chǎn)生雪崩的情況,也解決了物理節(jié)點數(shù)少,導(dǎo)致請求分布不均的問題。

帶有虛擬節(jié)點的Hash環(huán):

wKgZombzgXyAMsilAAFWxAL3tjE244.png

一致性Hash算法由于均衡性,持久性的映射特點被廣泛應(yīng)用于負載均衡領(lǐng)域,比如nginx、dubbo等內(nèi)部都有一致性hash的實現(xiàn)。

4.3.2 時間輪分片

時間輪(TimeWheel)是一種實現(xiàn)延遲功能(定時器)的精妙的算法,可以實現(xiàn)高效的延時隊列。以Kafka中的時間輪實現(xiàn)方案為例,它是一個存儲定時任務(wù)的環(huán)形隊列,底層采用數(shù)組實現(xiàn),數(shù)組中的每個元素可以存放一個定時任務(wù)列表(TimerTaskList)。TimerTaskList是一個環(huán)形的雙向鏈表,鏈表中的每一項表示的都是定時任務(wù)項(TimerTaskEntry),其中封裝了真正的定時任務(wù)TimerTask。

wKgaombzgX2ACWH5AAFCJl9Tzn4295.png


通過上圖可以發(fā)現(xiàn),時間輪算法不再任務(wù)隊列作為數(shù)據(jù)結(jié)構(gòu),輪詢線程不再負責(zé)遍歷所有任務(wù),而是僅僅遍歷時間刻度。時間輪算法好比指針不斷在時鐘上旋轉(zhuǎn)、遍歷,如果一個發(fā)現(xiàn)某一時刻上有任務(wù)(任務(wù)隊列),那么就會將任務(wù)隊列上的所有任務(wù)都執(zhí)行一遍。

假設(shè)相鄰bucket到期時間的間隔為bucket=1s,從0s開始計時,1s后到期的定時任務(wù)掛在bucket=1下,2s后到期的定時任務(wù)掛在bucket=2下,當(dāng)檢查到時間過去了1s時,bucket=1下所有節(jié)點執(zhí)行超時動作,當(dāng)時間到了2s時,bucket=2下所有節(jié)點執(zhí)行超時動作。時間輪使用一個表盤指針(pointer),用來表示時間輪當(dāng)前指針跳動的次數(shù),可以用tickDuration * (pointer + 1)來表示下一次到期的任務(wù),需要處理此bucket所對應(yīng)的 TimeWheel中的所有任務(wù)。

時間輪的優(yōu)點

1.任務(wù)的添加與移除,都是O(1)級的復(fù)雜度;

2.只需要有一個線程去推進時間輪,不會占用大量的資源;

3.與其他任務(wù)調(diào)度模式相比,CPU的負載和資源浪費減少;

適用場景

時間輪是為解決高效調(diào)度任務(wù)而產(chǎn)生的調(diào)度模型。在周期性定時任務(wù),延時任務(wù),通知任務(wù)等場景都可以發(fā)揮效用。

五 總結(jié)

本文針對數(shù)據(jù)存儲相關(guān)名詞概念進行了解釋,重點介紹了數(shù)據(jù)庫技術(shù)的發(fā)展史。為了豐富文章的可讀性以及實用性,又從數(shù)據(jù)結(jié)構(gòu)設(shè)計層面進行了部分技術(shù)實戰(zhàn)能力的外延擴展,闡述了拉鏈表,位運算,環(huán)形隊列等相關(guān)數(shù)據(jù)結(jié)構(gòu)在軟件開發(fā)領(lǐng)域的應(yīng)用,希望本文給你帶來收獲。

注:本文個別圖片來自互聯(lián)網(wǎng)

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
收藏 人收藏

    評論

    相關(guān)推薦

    kintex產(chǎn)品架構(gòu)設(shè)計文檔(成為架構(gòu)師也是電子人不錯的選...

    kintex產(chǎn)品架構(gòu)設(shè)計文檔(成為架構(gòu)師也是電子人不錯的選擇) ROCE(儒仕),用心為每一位電子人!Xilinx7系列普及講座,架構(gòu)師設(shè)計方案模板,交流學(xué)習(xí) 內(nèi)容請下載附件pdf,更多內(nèi)容請登錄ww..rocetech..co
    發(fā)表于 04-30 16:41

    數(shù)據(jù)庫系統(tǒng)是什么?數(shù)據(jù)庫系統(tǒng)概念之數(shù)據(jù)庫設(shè)計資料免費下載

      什么是概念結(jié)構(gòu)設(shè)計1.將需求分析得到的用戶需求抽象為信息結(jié)構(gòu)即概念模型的過程就是概念結(jié)構(gòu)設(shè)計2.概念結(jié)構(gòu)是各種數(shù)據(jù)模型的共同基礎(chǔ),它比
    發(fā)表于 09-07 14:34 ?1次下載
    <b class='flag-5'>數(shù)據(jù)庫</b>系統(tǒng)是什么?<b class='flag-5'>數(shù)據(jù)庫</b>系統(tǒng)概念之<b class='flag-5'>數(shù)據(jù)庫</b>設(shè)計資料免費下載

    如何進行數(shù)據(jù)庫設(shè)計?數(shù)據(jù)庫設(shè)計介紹和需求分析及結(jié)構(gòu)設(shè)計資料概述

    數(shù)據(jù)庫設(shè)計的任務(wù)是指根據(jù)需求研制數(shù)據(jù)庫結(jié)構(gòu)并應(yīng)用 數(shù)據(jù)庫的過程。數(shù)據(jù)庫設(shè)計內(nèi)容包括數(shù)據(jù)庫
    發(fā)表于 09-13 17:05 ?0次下載
    如何進行<b class='flag-5'>數(shù)據(jù)庫</b>設(shè)計?<b class='flag-5'>數(shù)據(jù)庫</b>設(shè)計介紹和需求分析及<b class='flag-5'>結(jié)構(gòu)設(shè)計</b>資料概述

    如何使用PowerDesigner進行數(shù)據(jù)庫靜態(tài)結(jié)構(gòu)設(shè)計?詳細資料概述

    把用戶需求抽象為概念模型即為概念結(jié)構(gòu)設(shè)計。 概念模型除了要求能反映客觀世界并且易于理解外,還要求其易于向數(shù)據(jù)模型(如關(guān)系模型)轉(zhuǎn)化。 概念模型獨立于具體的數(shù)據(jù)庫系統(tǒng),是整個數(shù)據(jù)庫設(shè)
    發(fā)表于 09-13 17:05 ?0次下載
    如何使用PowerDesigner進行<b class='flag-5'>數(shù)據(jù)庫</b>靜態(tài)<b class='flag-5'>結(jié)構(gòu)設(shè)計</b>?詳細資料概述

    數(shù)據(jù)庫靜態(tài)結(jié)構(gòu)如何設(shè)計?詳細資料任務(wù)和方法說明

    任務(wù):實現(xiàn)數(shù)據(jù)庫設(shè)計新奧爾良方法中概念結(jié)構(gòu)設(shè)計和邏輯結(jié)構(gòu)設(shè)計
    發(fā)表于 09-27 15:32 ?1次下載
    <b class='flag-5'>數(shù)據(jù)庫</b>靜態(tài)<b class='flag-5'>結(jié)構(gòu)</b>如何設(shè)計?詳細資料任務(wù)和方法說明

    數(shù)據(jù)庫教程之如何進行數(shù)據(jù)庫設(shè)計

    本文檔的主要內(nèi)容詳細介紹的是數(shù)據(jù)庫教程之如何進行數(shù)據(jù)庫設(shè)計內(nèi)容包括了:1 數(shù)據(jù)庫設(shè)計概述 ,2 數(shù)據(jù)庫需求分析 ,3 數(shù)據(jù)庫
    發(fā)表于 10-19 10:41 ?21次下載
    <b class='flag-5'>數(shù)據(jù)庫</b>教程之如何進行<b class='flag-5'>數(shù)據(jù)庫</b>設(shè)計

    數(shù)據(jù)庫設(shè)計的七大知識點總結(jié)詳細資料免費下載

    本文檔的主要內(nèi)容詳細介紹的是數(shù)據(jù)庫設(shè)計的七大知識點總結(jié)包括了:1 數(shù)據(jù)庫設(shè)計概述2 需求分析3 概念結(jié)構(gòu)設(shè)計4 邏輯結(jié)構(gòu)設(shè)計5 數(shù)據(jù)庫的物理
    發(fā)表于 10-19 10:41 ?0次下載
    <b class='flag-5'>數(shù)據(jù)庫</b>設(shè)計的七大知識點總結(jié)詳細資料免費下載

    數(shù)據(jù)庫學(xué)習(xí)入門資料之數(shù)據(jù)庫的概念結(jié)構(gòu)詳細資料概述

    什么是概念結(jié)構(gòu)設(shè)計 將需求分析得到的用戶需求抽象為信息結(jié)構(gòu)即概念模型的過程就是概念結(jié)構(gòu)設(shè)計 概念結(jié)構(gòu)是各種數(shù)據(jù)模型的共同基礎(chǔ),它比
    發(fā)表于 10-25 16:29 ?0次下載
    <b class='flag-5'>數(shù)據(jù)庫</b>學(xué)習(xí)入門資料之<b class='flag-5'>數(shù)據(jù)庫</b>的概念<b class='flag-5'>結(jié)構(gòu)</b>詳細資料概述

    數(shù)據(jù)庫概念結(jié)構(gòu)是如何設(shè)計的概念結(jié)構(gòu)設(shè)計資料概述

    本文檔的主要內(nèi)容詳細介紹的是數(shù)據(jù)庫概念結(jié)構(gòu)是如何設(shè)計的概念結(jié)構(gòu)設(shè)計資料概述主要內(nèi)容包括了:1 概念結(jié)構(gòu)2 概念結(jié)構(gòu)設(shè)計的方法與步驟3
    發(fā)表于 10-26 11:49 ?22次下載
    <b class='flag-5'>數(shù)據(jù)庫</b>概念<b class='flag-5'>結(jié)構(gòu)</b>是如何設(shè)計的概念<b class='flag-5'>結(jié)構(gòu)設(shè)計</b>資料概述

    數(shù)據(jù)庫的設(shè)計概念總結(jié)

    本文檔的主要內(nèi)容詳細介紹的是數(shù)據(jù)庫的設(shè)計概念總結(jié)主要內(nèi)容包括了:1.數(shù)據(jù)庫設(shè)計概述,2.需求分析,3.概念結(jié)構(gòu)設(shè)計,4.邏輯結(jié)構(gòu)設(shè)計,5.數(shù)據(jù)庫
    發(fā)表于 01-09 17:29 ?13次下載
    <b class='flag-5'>數(shù)據(jù)庫</b>的設(shè)計概念總結(jié)

    數(shù)據(jù)庫設(shè)計開發(fā)案例教程之數(shù)據(jù)庫設(shè)計的資料介紹

    本文檔的主要內(nèi)容詳細介紹的是數(shù)據(jù)庫設(shè)計開發(fā)案例教程之數(shù)據(jù)庫設(shè)計的資料介紹主要內(nèi)容包括了:1 數(shù)據(jù)庫設(shè)計概述,2 需求分析,3 概念結(jié)構(gòu)設(shè)計,4 邏輯
    發(fā)表于 01-11 11:20 ?17次下載
    <b class='flag-5'>數(shù)據(jù)庫</b>設(shè)計開發(fā)案例教程之<b class='flag-5'>數(shù)據(jù)庫</b>設(shè)計的資料介紹

    數(shù)據(jù)架構(gòu)師的職責(zé)有哪些

    架構(gòu)師按照專注領(lǐng)域不同,可分為企業(yè)架構(gòu)師、基礎(chǔ)結(jié)構(gòu)架構(gòu)師、特定技術(shù)架構(gòu)和解決方案架構(gòu)師等,專職架構(gòu)師
    的頭像 發(fā)表于 04-04 16:24 ?3745次閱讀

    數(shù)據(jù)庫教程之數(shù)據(jù)庫系統(tǒng)設(shè)計課件的資料免費下載

    結(jié)構(gòu)特性設(shè)計通常是指數(shù)據(jù)庫模式或數(shù)據(jù)庫結(jié)構(gòu)設(shè)計,它應(yīng)該具有最小冗余的、能滿足不同用戶數(shù)據(jù)需求的、能實現(xiàn)數(shù)
    發(fā)表于 01-17 17:11 ?17次下載

    干貨:20個MySQL開源數(shù)據(jù)庫架構(gòu)設(shè)計原則

    干貨:20個MySQL開源數(shù)據(jù)庫架構(gòu)設(shè)計原則
    的頭像 發(fā)表于 08-28 10:57 ?3289次閱讀

    原華為云高斯數(shù)據(jù)庫首席架構(gòu)師出任易鯨捷CEO

    近日,貴州易鯨捷信息技術(shù)有限公司宣布,原華為云高斯數(shù)據(jù)庫首席架構(gòu)師、華為IT產(chǎn)品線數(shù)據(jù)平臺部CTO,曾任南大通用CTO、CEO,中國數(shù)據(jù)庫領(lǐng)軍人物之一的武新博士正式加盟易鯨捷并出任CE
    發(fā)表于 06-30 09:52 ?602次閱讀