11.21 NoSql數據庫,是怎麼解決我們高併發場景下MySql表現的不足

通過前面幾天的學習,我們在面對高併發流量時,為了應對大量讀寫請求,特此將我們的普通存儲系統開發成了一套分佈式存儲系統。主要基於讀寫分離主從複製以及數據分庫分表實現的。不清楚的可以再回去看看啊 ,

後來又有朋友問我,如果他們的業務還在繼續增長,都成國內獨角獸的行業了,之前動態分的1024個庫表每個表都達到了億級別的,那時,各方面又出現了各種性能瓶頸了,還需要再分庫分表嗎?如果你的感受業務都達到了這種維度,那這個時候,我就建議不要再去繼續折騰分庫分表了,我們用NoSql數據庫去緩解我們現有系統的新能瓶頸,並不是直接替換哈。這種情況下我們應該怎麼做呢?今天我們就來講一講NoSql數據庫和我們現有關係型數據庫怎麼協作來為我們業務服務。

什麼是NoSql

NoSQL(NoSQL = Not Only SQL ),意即"不僅僅是SQL",指的是非關係型的數據庫。NoSQL有時也稱作Not Only SQL的縮寫,是對不同於傳統的關係型數據庫的數據庫管理系統的統稱。

NoSQL用於超大規模數據的存儲。(例如谷歌或Facebook每天為他們的用戶收集萬億比特的數據)。這些類型的數據存儲不需要固定的模式,無需多餘操作就可以橫向擴展。那NoSql發展到現在都有哪有比較成熟的且常用的類型呢,下面我來簡單列舉下我們日常開發中接觸比較多的NoSql:

  • Redis :基於KV存儲結構,由於是使用內存存儲,所以讀寫性能都極高,也是高於現在的關係型數據庫的。一般如果我們業務中對性能要求比較高的話,就可以使用redis。
  • Hbase:列式存儲數據庫,和我們以行為單位的關係型數據庫不一樣,它是採取列式存儲的,通過id查詢速度很快,一般我們的大量離線任務數據就可以存在這裡
  • MongoDB:文檔型數據庫,像一個json對象,其優點就是字段可以隨意更換和增加,比如,我們一個複雜業務中可能會頻繁的增加字段,而且還很多且期初並不能完全知道有哪些字段,這種的存儲業務MongoDB這種文檔型數據庫非常方便。

為什麼要使用NoSql呢?

NoSql的出現解決了我們現有數據庫的很多不足之處,例如:

  • 解決了關係型數據庫在面對大數據量下各種擴容麻煩的問題
  • 解決了關係型數據庫在性能上表現的不足問題
  • 其不用變更原有的數據結構。

你可能會疑問,那NoSql既然這麼多優點,那我們直接都換成NoSql的得了,不要關係型數據庫mysql這樣的了。我並不推薦這麼幹,其實在我們實際開發中,像MySQL這類的關係型數據庫擁有強大的事務以及SQL查詢能力,這些是nosql尚不能帶給我們的,我們需要關係型數據庫的特性才能滿足我們的業務需求,其次,你引入nosql的數據庫還需要我們的運維人員對其熟悉才能很好的為我們業務服務。所以,NoSql和關係型數據庫是互補的關係,它可以用來解決我們現有數據庫的不足,從而使得我們業務向著更好的良態去發展。接下來,我們看看該怎麼使用NoSql來對我們的關係型數據庫進行

互補

使用NoSql來提升寫入性能

我們知道我們的關係型數據庫數據是存在磁盤上的,其中訪問磁盤有兩種方式:順序IO以及隨機IO。如果是隨機IO訪問則會進行磁盤尋道,這個是相當耗時的,一般的,這種隨機IO訪問磁盤要比順序IO慢很多很多。所以,這裡要想提高我們寫入性能的話就需要儘量減少磁盤的隨機IO.

比如,我們的MySql的InnoDB存儲引擎,它更新binlog相關的操作則是在做順序IO,而更新數據文件以及更新索引文件則是在做隨機IO。這裡我解釋下,怕有些朋友看不懂,因為日誌文件是在後面追加的,所以是順序IO,而更新數據是需要先找到位置的,所以是隨機IO。儘管MySql在這塊做了很大的優化,比如WAL啊,寫入的時候先寫內存啊,但是還是會出現隨機IO。

引入NoSQL數據庫如何來解決這種問題

大部分NoSQl數據庫是基於LSM

樹的存儲引擎,那這個LSM樹(Log-Structured Merge Tree)算法比我們MySql的B+ 樹在提升寫性能上有什麼優越呢?下面我們就來看看LSM樹是怎麼做的。

任何事物一方面的優越都是犧牲其中的某些其他方面所帶來的的,LSM樹同樣是,它是犧牲了一定的讀性能來提高寫入的性能的,像Hbase、LevelDB以及Cassandra都是基於這種算法來實現的存儲引擎,具體是怎麼做的呢?

  1. 在寫入數據的時候,首先寫入到一個叫MemTable的內存結構中,其中MemTable中數據是按照寫入的key來排序的。
  2. 同時通過寫Write Ahead Log的方式將數據備份一份到磁盤上,防止數據丟失。
  3. 當MemTable數據增加到一定的量級之後,就會被刷新成一個新的文件SSTable(Sorted String Table)。
  4. 當SSTable文件達到一定數量之後,就將他們進行合併操作,為了減少文件的數量,這個過程速度很快,因為每個SSTable都是有序的。
  5. 當我們需要從LSM中讀取數據的時候,我們首先讀取MemTable數據,如果讀取不到,再去讀取SSTable數據,查找效率很高,因為存儲數據是有序的,由於我們有多個SSTable文件,所以我們讀取的效率要低於B+數的索引。
NoSql數據庫,是怎麼解決我們高併發場景下MySql表現的不足

所以,現在我們就知道了NoSql數據庫對於關係型數據庫讀寫性能的缺陷進行了互補。

引用NoSql提供存儲服務

現在有這麼一個場景,我在電商網站需要根據某一商品的其中特點去查詢出,比如,現在我現在要搜一個華為手機,然後想買我合適尺寸的。這裡你應該怎麼來查詢呢,在傳統的關係型數據庫中應該是這樣的“select * from t_product where name like '華為%'”,其實,這樣是用不到我們的name索引的,只有%華為才能用上我們的name索引,而且上面那麼的條件搜索,我難道都使用like嗎?顯然這是不可取的,那這個時候,我這裡建議上Elasticsearch。目前,我們公司的酒店搜索就是使用ES的。ES是基於“倒排索引”來實現的,下面我給大家科普下什麼是倒排索引

倒排索引意思就是在我們所需要的數據列中進行分詞,然後將分詞和我們的記錄ID行程映射關係,如下圖:

NoSql數據庫,是怎麼解決我們高併發場景下MySql表現的不足

首先,我們將我們的商品名稱進行分詞,然後在和商品ID建立映射關係,如下圖所示:

NoSql數據庫,是怎麼解決我們高併發場景下MySql表現的不足

好,當用戶搜索(電冰箱)的時候,我們就給他展示商品ID為1和3的商品:西門子電冰箱和電冰箱。

所以,當我們業務中需要大量全文搜索的需求的時候,我們就可以直接使用Elasticsearch這個NoSql數據庫

NoSql如何可擴展

我們前面開發了一套基於分庫分表的分佈式存儲系統,但是當我們的業務持續猛增的話,我們的這套存儲系統可能在擴展上比較費力。然而,我們如果採用MongoDB來接管,那就方便很多了,比如我們酒店的評論量,每天都增長巨快,MongoDB天生容易支撐可擴展。它具體表現有三個方面:

1,副本集Replica,副本的概念大家應該很明白了,就是冗餘多份數據保證數據不丟失的,就和我們前面的主從分離是一個意思。不僅提供讀服務還提供了寫服務。

2,分片Shard,意思就是將數據分到不同的片上進行存儲,聯繫我們的分庫分表就好理解了,對於Sharding我們來說下他的工作原理:

  • MongoDB sharding 一共有三個角色:Shard Server、Config Server、Router Server
  • Shard Server是獨立的Mongod 進程,真正存數據的地方
  • Config Server 也是一組Mongod進程,存儲元數據的地方,比如那個數據在哪個分片上,這些config中都有
  • Router Server 不存儲數據,是一個路由,通過他路由到合適的Shard Server。

即我們來請求的時候,首先到達我們的路由層Router Server,然後路由查Config Server,看數據再哪個Shard 上,最後就直接能到正確的Shard Server 上。

3,負載均衡,MongoDB發現各個Shard Server數據分配不均的話,就會Balancer 進程對數據做重新的分配。如果擴容的時候,直接增加Shard Server就行了,數據會自動分到新的Shard上去。

所以,NoSql 的MongoDB就很好了彌補了我們分庫分表太大的業務擴容難的問題。

總結,今天我們分享了NoSql數據庫可以幫助我們更好的面對大數據量和高性能,主要講到了採用順序IO訪問磁盤以提高讀寫性能,全文檢索代替我們複雜且性能低下的like操作,同時,天然的高擴展解決後期大數據擴容難的問題。但是,NoSql並不是說直接能替換我們的MySQL,他們是互補的關係。如果大家喜歡,或者對大家有幫助,就關注我,我會一直分享業界流行技術方案,我們共同學習共同進步。

下一篇預告:聊聊緩存

java高併發、高級面試、分佈式、微服務、人工智能以及Python等各大互聯網專題,關注wx公眾號【架構師修煉】專屬資料點擊菜單“成神之路” 你會感謝我的


分享到:


相關文章: