分布式技術(shù)原理與實戰(zhàn)45講--第24講:NoSQL 數(shù)據(jù)庫有哪些典型應(yīng)用
前面的內(nèi)容介紹了數(shù)據(jù)庫讀寫分離和分庫分表相關(guān)知識,都是針對關(guān)系型數(shù)據(jù)庫的,即通常說的 RDBMS。除了關(guān)系型數(shù)據(jù)庫,NoSQL 在項目開發(fā)中也有著越來越重要的作用,與此同時,NoSQL 相關(guān)的內(nèi)容也是面試的常客。今天我們一起來看下 NoSQL 數(shù)據(jù)庫有哪些應(yīng)用。
對比關(guān)系型數(shù)據(jù)庫
在介紹 NoSQL 數(shù)據(jù)庫之前,先回顧下關(guān)系型數(shù)據(jù)庫。還記得 SQL 語言的全稱嗎?Structured Query Language,也就是結(jié)構(gòu)化查詢語言,結(jié)構(gòu)化查詢對應(yīng)的存儲實現(xiàn)是關(guān)系型數(shù)據(jù)庫,我們熟悉的 MySQL、Oracle 和 SQL Server,都是關(guān)系型數(shù)據(jù)庫的代表。
關(guān)系型數(shù)據(jù)庫通過關(guān)系模型來組織數(shù)據(jù),在關(guān)系型數(shù)據(jù)庫當(dāng)中一個表就是一個模型,一個關(guān)系數(shù)據(jù)庫可以包含多個表,不同數(shù)據(jù)表之間的聯(lián)系反映了關(guān)系約束。
不知道你是否應(yīng)用過 ER 圖?在早期的軟件工程中,數(shù)據(jù)表的創(chuàng)建都會通過 ER 圖來定義,ER 圖(Entity Relationship Diagram)稱為 實體-聯(lián)系圖,包括實體、屬性和關(guān)系三個核心部分。
下面是在電商領(lǐng)域中,一個簡化的會員、商品和訂單的 ER 圖:

簡化版的會員、商品和訂單 ER 圖
ER圖中的實體采用矩形表示,即數(shù)據(jù)模型中的數(shù)據(jù)對象,例如電商業(yè)務(wù)模型中的會員、商品、訂單等,每個數(shù)據(jù)對象具有不同的屬性,比如會員有賬戶名、電話、地址等,商品有商品名稱、價格、庫存等屬性。不同的數(shù)據(jù)對象之間又對應(yīng)不同的關(guān)系,比如會員購買商品、創(chuàng)建訂單。
有了 ER 圖等的輔助設(shè)計,關(guān)系型數(shù)據(jù)庫的數(shù)據(jù)模型可以非常好的描述物理世界,比較方便地創(chuàng)建各種數(shù)據(jù)約束。
另外一方面,關(guān)系型數(shù)據(jù)庫對事務(wù)支持較好,支持 SQL 規(guī)范中的各種復(fù)雜查詢,比如 join、union 等操作。正是由于對 SQL 規(guī)范的支持,也使得關(guān)系型數(shù)據(jù)庫對擴(kuò)展不友好,比較難進(jìn)行分布式下的集群部署。
NoSQL 數(shù)據(jù)庫特性
NoSQL 數(shù)據(jù)庫是在 SQL 的基礎(chǔ)上發(fā)展的,對 NoSQL 的具體解釋,你可以認(rèn)為是 Not Only SQL,也可以認(rèn)為是 Non-Relational SQL。
NoSQL 對應(yīng)非關(guān)系型數(shù)據(jù)庫,不同于傳統(tǒng)的關(guān)系型數(shù)據(jù)庫,如果說關(guān)系型數(shù)據(jù)庫是武俠小說中的正統(tǒng)功夫,NoSQL 數(shù)據(jù)庫就是野路子,少了很多約束,也就不拘一格、自成一派。那么對比關(guān)系型數(shù)據(jù)庫,NoSQL 型數(shù)據(jù)庫有哪些優(yōu)點呢?
良好的擴(kuò)展性,容易通過集群部署
關(guān)系型數(shù)據(jù)庫在進(jìn)行擴(kuò)展時,要考慮到如何分庫分表、擴(kuò)容等,各種實現(xiàn)方案都比較重,對業(yè)務(wù)侵入較大。NoSQL 數(shù)據(jù)庫去掉了關(guān)系型數(shù)據(jù)庫的關(guān)系特性,天生對集群友好,這樣就非常容易擴(kuò)展。
讀寫性能高,支持大數(shù)據(jù)量
關(guān)系型數(shù)據(jù)庫對一致性的要求較高,數(shù)據(jù)表的結(jié)構(gòu)復(fù)雜,讀寫的性能要低于非關(guān)系型數(shù)據(jù)庫。另外一方面,部分 NoSQL 數(shù)據(jù)庫采用全內(nèi)存實現(xiàn),更適合一些高并發(fā)的訪問場景。
不限制表結(jié)構(gòu),靈活的數(shù)據(jù)模型
應(yīng)用關(guān)系型數(shù)據(jù)庫,需要通過 DML 語句創(chuàng)建表結(jié)構(gòu),數(shù)據(jù)表創(chuàng)建以后,增刪字段需要重新修改表結(jié)構(gòu)。如果使用 NoSQL,一般不需要事先為數(shù)據(jù)建立存儲結(jié)構(gòu)和字段,可以存儲各種自定義的數(shù)據(jù)。
NoSQL 數(shù)據(jù)庫有這么多優(yōu)點,但是在項目開發(fā)中,關(guān)系型數(shù)據(jù)庫和非關(guān)系型數(shù)據(jù)庫不是對立的,而是相輔相成的。從性能的角度來講,NoSQL 數(shù)據(jù)庫的性能優(yōu)于關(guān)系型數(shù)據(jù)庫,從持久化角度,關(guān)系型數(shù)據(jù)庫優(yōu)于 NoSQL 數(shù)據(jù)庫。
專欄最開始提到了 CAP 理論,從 CAP 的角度,NoSQL 數(shù)據(jù)庫一般提供弱一致性的保證,實現(xiàn)最終一致性,也就是關(guān)系型數(shù)據(jù)庫強調(diào) CP 模型,而 NoSQL 關(guān)注的是 AP 模型,同時應(yīng)用 NoSQL 和關(guān)系型數(shù)據(jù)庫,可以滿足高性能的基礎(chǔ)上,同時保證數(shù)據(jù)可靠性。
NoSQL 數(shù)據(jù)庫應(yīng)用
非關(guān)系型數(shù)據(jù)庫有很多類型,應(yīng)用的側(cè)重點也不同,可以從以下幾個角度進(jìn)行分類。
Key-Value 數(shù)據(jù)庫
Key-Value 存儲就是我們熟悉的 Map 結(jié)構(gòu),支持高性能的通過 Key 定位和存儲。通常用來實現(xiàn)緩存等應(yīng)用,典型的有 Redis 和 Memcached。
以 Redis 為例,作為應(yīng)用最多的非關(guān)系型數(shù)據(jù)庫之一,Redis 可以說是日常工作中的一把瑞士軍刀。
從性能的角度,為了提高讀寫效率,Redis 在最開始的版本中一直使用單線程模型,避免上下文切換和線程競爭資源,并且采用了 IO 多路復(fù)用的技術(shù),提升了性能,另外在最近的版本更新中,Redis也開始支持多線程處理,感興趣的同學(xué)可以查看相關(guān)的資料了解。
從存儲結(jié)構(gòu)的角度,Redis 支持多種數(shù)據(jù)結(jié)構(gòu),得益于這些,Redis 有豐富的應(yīng)用場景,并且針對不同的數(shù)據(jù)規(guī)模等,Redis 采取多種內(nèi)存優(yōu)化方式,盡量減少內(nèi)存占用。比如,List 結(jié)構(gòu)內(nèi)部有壓縮列表和雙向鏈表兩種實現(xiàn),在數(shù)據(jù)規(guī)模較小時采用 ZipList 實現(xiàn),特別是在新的版本更新中,又添加了 QuickList 的實現(xiàn),減少內(nèi)存的消耗。
從高可用的角度,作為一個內(nèi)存數(shù)據(jù)庫,Redis實現(xiàn)了AOF和RDB的數(shù)據(jù)持久化機制,另外,Redis支持了多種集群方式,包括主從同步,Sentinel和Redis Cluster等機制,提高了整體的數(shù)據(jù)安全和高可用保障。
文檔型數(shù)據(jù)庫
文檔型數(shù)據(jù)庫可以存儲結(jié)構(gòu)化的文檔,比如 JSON 或者 XML,從這個角度上看,文檔型數(shù)據(jù)庫比較接近關(guān)系型數(shù)據(jù)庫。但是對比關(guān)系型數(shù)據(jù)庫,文檔性數(shù)據(jù)庫中不需要預(yù)先定義表結(jié)構(gòu),并且可以支持文檔之間的嵌套,典型的比如 MongoDB,這一點和關(guān)系型數(shù)據(jù)庫有很大的不同。
以 MongoDB 為例,采用了基于 JSON 擴(kuò)展的 BSON 存儲結(jié)構(gòu),可以進(jìn)行自我描述,這種靈活的文檔類型,特別適合應(yīng)用在內(nèi)容管理系統(tǒng)等業(yè)務(wù)中。MongoDB 還具備非常優(yōu)秀的擴(kuò)展能力,對分片等集群部署的支持非常全面,可以快速擴(kuò)展集群規(guī)模。
列存儲數(shù)據(jù)庫
列式數(shù)據(jù)庫被用來存儲海量數(shù)據(jù),比如 Cassandra、HBase 等,特點是大數(shù)據(jù)量下讀寫速度較快、可擴(kuò)展性強,更容易進(jìn)行分布式部署。
以 HBase 為例,HBase 支持海量數(shù)據(jù)的讀寫,特別是寫入操作,可以支持 TB 級的數(shù)據(jù)量。列式數(shù)據(jù)庫通常不支持事務(wù)和各種索引優(yōu)化,比如 HBase 使用 LSM 樹組織數(shù)據(jù),對比 MySQL 的 B+ 樹,在高并發(fā)寫入時有更好的性能。
圖形數(shù)據(jù)庫
在一些特定的應(yīng)用場景可以應(yīng)用特殊的數(shù)據(jù)庫,比如圖形數(shù)據(jù)庫。在學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)時我們知道,社交網(wǎng)絡(luò)中的用戶關(guān)系可以使用圖來存儲,于是誕生了一些圖形數(shù)據(jù)庫,可以方便地操作圖結(jié)構(gòu)的相關(guān)算法,比如最短路徑、關(guān)系查找等。
圖形數(shù)據(jù)庫在一般的工程開發(fā)中應(yīng)用較少,感興趣的同學(xué)可以去了解一下。
總結(jié)
這一課時分享了 NoSQL 數(shù)據(jù)庫相關(guān)的知識點,包括關(guān)系型數(shù)據(jù)庫和非關(guān)系型數(shù)據(jù)庫的對比,分析了常見 NoSQL 數(shù)據(jù)庫的分類和應(yīng)用特性。
大多數(shù)場景下,NoSQL 數(shù)據(jù)庫是配合關(guān)系型數(shù)據(jù)庫一起使用的,這就涉及了不同存儲之間的同步問題,比如緩存和數(shù)據(jù)庫的同步等,針對這個問題,會在緩存模塊展開介紹?,F(xiàn)在你可以結(jié)合自己的項目實踐,思考下應(yīng)用過哪些非關(guān)系型數(shù)據(jù)庫,以及使用了哪些對應(yīng)特性,如何配合關(guān)系型數(shù)據(jù)庫等,歡迎留言分享。