<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      水平分庫分表的關鍵問題及解決思路

      在之前的文章中,我介紹了分庫分表的幾種表現形式和玩法,也重點介紹了垂直分庫所帶來的問題和解決方法。本篇中,我們將繼續聊聊水平分庫分表的一些技巧。

      分片技術的由來

      關系型數據庫本身比較容易成為系統性能瓶頸,單機存儲容量、連接數、處理能力等都很有限,數據庫本身的“有狀態性”導致了它并不像Web和應用服務器那么容易擴展。在互聯網行業海量數據和高并發訪問的考驗下,聰明的技術人員提出了分庫分表技術(有些地方也稱為Sharding、分片)。同時,流行的分布式系統中間件(例如MongoDB、ElasticSearch等)均自身友好支持Sharding,其原理和思想都是大同小異的。

      分布式全局唯一ID

      在很多中小項目中,我們往往直接使用數據庫自增特性來生成主鍵ID,這樣確實比較簡單。而在分庫分表的環境中,數據分布在不同的分片上,不能再借助數據庫自增長特性直接生成,否則會造成不同分片上的數據表主鍵會重復。簡單介紹下使用和了解過的幾種ID生成算法。

       

      1. Twitter的Snowflake(又名“雪花算法”)
      2. UUID/GUID(一般應用程序和數據庫均支持)
      3. MongoDB ObjectID(類似UUID的方式)
      4. Ticket Server(數據庫生存方式,Flickr采用的就是這種方式)
       

      常見分片規則和策略

      分片字段該如何選擇

      在開始分片之前,我們首先要確定分片字段(也可稱為“片鍵”)。很多常見的例子和場景中是采用ID或者時間字段進行拆分。這也并不絕對的,我的建議是結合實際業務,通過對系統中執行的sql語句進行統計分析,選擇出需要分片的那個表中最頻繁被使用,或者最重要的字段來作為分片字段。

      常見分片規則

      常見的分片策略有隨機分片和連續分片這兩種,如下圖所示:

       

      當需要使用分片字段進行范圍查找時,連續分片可以快速定位分片進行高效查詢,大多數情況下可以有效避免跨分片查詢的問題。后期如果想對整個分片集群擴容時,只需要添加節點即可,無需對其他分片的數據進行遷移。但是,連續分片也有可能存在數據熱點的問題,就像圖中按時間字段分片的例子,有些節點可能會被頻繁查詢壓力較大,熱數據節點就成為了整個集群的瓶頸。而有些節點可能存的是歷史數據,很少需要被查詢到。

      隨機分片其實并不是隨機的,也遵循一定規則。通常,我們會采用Hash取模的方式進行分片拆分,所以有些時候也被稱為離散分片。隨機分片的數據相對比較均勻,不容易出現熱點和并發訪問的瓶頸。但是,后期分片集群擴容起來需要遷移舊的數據。使用一致性Hash算法能夠很大程度的避免這個問題,所以很多中間件的分片集群都會采用一致性Hash算法。離散分片也很容易面臨跨分片查詢的復雜問題。

      數據遷移,容量規劃,擴容等問題

      很少有項目會在初期就開始考慮分片設計的,一般都是在業務高速發展面臨性能和存儲的瓶頸時才會提前準備。因此,不可避免的就需要考慮歷史數據遷移的問題。一般做法就是通過程序先讀出歷史數據,然后按照指定的分片規則再將數據寫入到各個分片節點中。

      此外,我們需要根據當前的數據量和QPS等進行容量規劃,綜合成本因素,推算出大概需要多少分片(一般建議單個分片上的單表數據量不要超過1000W)。

      如果是采用隨機分片,則需要考慮后期的擴容問題,相對會比較麻煩。如果是采用的范圍分片,只需要添加節點就可以自動擴容。

      跨分片技術問題

      跨分片的排序分頁

      一般來講,分頁時需要按照指定字段進行排序。當排序字段就是分片字段的時候,我們通過分片規則可以比較容易定位到指定的分片,而當排序字段非分片字段的時候,情況就會變得比較復雜了。為了最終結果的準確性,我們需要在不同的分片節點中將數據進行排序并返回,并將不同分片返回的結果集進行匯總和再次排序,最后再返回給用戶。如下圖所示:

      上面圖中所描述的只是最簡單的一種情況(取第一頁數據),看起來對性能的影響并不大。但是,如果想取出第10頁數據,情況又將變得復雜很多,如下圖所示:

      有些讀者可能并不太理解,為什么不能像獲取第一頁數據那樣簡單處理(排序取出前10條再合并、排序)。其實并不難理解,因為各分片節點中的數據可能是隨機的,為了排序的準確性,必須把所有分片節點的前N頁數據都排序好后做合并,最后再進行整體的排序。很顯然,這樣的操作是比較消耗資源的,用戶越往后翻頁,系統性能將會越差。

      跨分片的函數處理

      在使用Max、Min、Sum、Count之類的函數進行統計和計算的時候,需要先在每個分片數據源上執行相應的函數處理,然后再將各個結果集進行二次處理,最終再將處理結果返回。如下圖所示:

      跨分片join

      Join是關系型數據庫中最常用的特性,但是在分片集群中,join也變得非常復雜。應該盡量避免跨分片的join查詢(這種場景,比上面的跨分片分頁更加復雜,而且對性能的影響很大)。通常有以下幾種方式來避免:

      全局表

      全局表的概念之前在“垂直分庫”時提過?;舅枷胍恢?,就是把一些類似數據字典又可能會產生join查詢的表信息放到各分片中,從而避免跨分片的join。

      ER分片

      在關系型數據庫中,表之間往往存在一些關聯的關系。如果我們可以先確定好關聯關系,并將那些存在關聯關系的表記錄存放在同一個分片上,那么就能很好的避免跨分片join問題。在一對多關系的情況下,我們通常會選擇按照數據較多的那一方進行拆分。如下圖所示:

      這樣一來,Data Node1上面的訂單表與訂單詳細表就可以直接關聯,進行局部的join查詢了,Data Node2上也一樣?;贓R分片的這種方式,能夠有效避免大多數業務場景中的跨分片join問題。

      內存計算

      隨著spark內存計算的興起,理論上來講,很多跨數據源的操作問題看起來似乎都能夠得到解決。可以將數據丟給spark集群進行內存計算,最后將計算結果返回。

      跨分片事務問題

      跨分片事務也分布式事務,想要了解分布式事務,就需要了解“XA接口”和“兩階段提交”。值得提到的是,MySQL5.5x和5.6x中的xa支持是存在問題的,會導致主從數據不一致。直到5.7x版本中才得到修復。Java應用程序可以采用Atomikos框架來實現XA事務(J2EE中JTA)。感興趣的讀者可以自行參考《分布式事務一致性解決方案》,鏈接地址:

      http://www.infoq.com/cn/articles/solution-of-distributed-system-transaction-consistency

      我們的系統真的需要分庫分表嗎

      讀完上面內容,不禁引起有些讀者的思考,我們的系統是否需要分庫分表嗎?

      其實這點沒有明確的判斷標準,比較依賴實際業務情況和經驗判斷。依照筆者個人的經驗,一般MySQL單表1000W左右的數據是沒有問題的(前提是應用系統和數據庫等層面設計和優化的比較好)。當然,除了考慮當前的數據量和性能情況時,作為架構師,我們需要提前考慮系統半年到一年左右的業務增長情況,對數據庫服務器的QPS、連接數、容量等做合理評估和規劃,并提前做好相應的準備工作。如果單機無法滿足,且很難再從其他方面優化,那么說明是需要考慮分片的。這種情況可以先去掉數據庫中自增ID,為分片和后面的數據遷移工作提前做準備。

      很多人覺得“分庫分表”是宜早不宜遲,應該盡早進行,因為擔心越往后公司業務發展越快、系統越來越復雜、系統重構和擴展越困難…這種話聽起來是有那么一點道理,但我的觀點恰好相反,對于關系型數據庫來講,我認為“能不分片就別分片”,除非是系統真正需要,因為數據庫分片并非低成本或者免費的。

      這里筆者推薦一個比較靠譜的過渡技術–“表分區”。主流的關系型數據庫中基本都支持。不同的分區在邏輯上仍是一張表,但是物理上卻是分開的,能在一定程度上提高查詢性能,而且對應用程序透明,無需修改任何代碼。筆者曾經負責優化過一個系統,主業務表有大約8000W左右的數據,考慮到成本問題,當時就是采用“表分區”來做的,效果比較明顯,且系統運行的很穩定。

      小結

      最后,有很多讀者都想了解當前社區中有沒有開源免費的分庫分表解決方案,畢竟站在巨人的肩膀上能省力很多。當前主要有兩類解決方案:

      1. 基于應用程序層面的DDAL(分布式數據庫訪問層) 

        比較典型的就是淘寶半開源的TDDL,當當網開源的Sharding-JDBC等。分布式數據訪問層無需硬件投入,技術能力較強的大公司通常會選擇自研或參照開源框架進行二次開發和定制。對應用程序的侵入性一般較大,會增加技術成本和復雜度。通常僅支持特定編程語言平臺(Java平臺的居多),或者僅支持特定的數據庫和特定數據訪問框架技術(一般支持MySQL數據庫,JDBC、MyBatis、Hibernate等框架技術)。

      2. 數據庫中間件,比較典型的像mycat(在阿里開源的cobar基礎上做了很多優化和改進,屬于后起之秀,也支持很多新特性),基于Go語言實現kingSharding,比較老牌的Atlas(由360開源)等。這些中間件在互聯網企業中大量被使用。另外,MySQL 5.x企業版中官方提供的Fabric組件也號稱支持分片技術,不過國內使用的企業較少。 

        中間件也可以稱為“透明網關”,大名鼎鼎的mysql_proxy大概是該領域的鼻祖(由MySQL官方提供,僅限于實現“讀寫分離”)。中間件一般實現了特定數據庫的網絡通信協議,模擬一個真實的數據庫服務,屏蔽了后端真實的Server,應用程序通常直接連接中間件即可。而在執行SQL操作時,中間件會按照預先定義分片規則,對SQL語句進行解析、路由,并對結果集做二次計算再最終返回。引入數據庫中間件的技術成本更低,對應用程序來講侵入性幾乎沒有,可以滿足大部分的業務。增加了額外的硬件投入和運維成本,同時,中間件自身也存在性能瓶頸和單點故障問題,需要能夠保證中間件自身的高可用、可擴展。

      總之,不管是使用分布式數據訪問層還是數據庫中間件,都會帶來一定的成本和復雜度,也會有一定的性能影響。所以,還需讀者根據實際情況和業務發展需要慎重考慮和選擇。

      作者介紹

      丁浪,技術架構師。關注高并發、高可用的架構設計,對系統服務化、分庫分表、性能調優等方面有深入研究和豐富實踐經驗。熱衷于技術研究和分享。

      posted @ 2016-11-21 09:24  丁碼農  閱讀(18566)  評論(30)    收藏  舉報
      主站蜘蛛池模板: 亚洲av无码牛牛影视在线二区| 亚洲AV日韩AV激情亚洲| 麻豆一区二区三区蜜桃免费| 国内自拍网红在线综合一区| 宝贝腿开大点我添添公视频免| 国产在线国偷精品产拍| 人妻av一区二区三区av免费| 国产精品无码成人午夜电影| 色婷婷狠狠久久综合五月| 国产粉嫩区一区二区三区| 久久午夜无码鲁丝片直播午夜精品 | 慈溪市| 双乳奶水饱满少妇呻吟免费看| 成人拍拍拍无遮挡免费视频| 国产中文成人精品久久久| 久久国产精品不只是精品| 中文日韩在线一区二区| 久久永久视频| 亚洲中文字幕无码专区| 色偷偷亚洲女人天堂观看| 人妻丝袜AV中文系列先锋影音| jizz视频在线观看| 在线观看美女网站大全免费| 亚洲精品国产精品国在线| 色狠狠综合天天综合综合 | 中文字幕精品人妻丝袜| 乱码中字在线观看一二区| 精品一日韩美女性夜视频| 日韩精品 在线 国产 丝袜| 天堂网av最新版在线看| 日本一区二区三区在线 |观看| 久久人妻精品大屁股一区| 久久国产乱子精品免费女| 精品人妻一区二区| 强插少妇视频一区二区三区| 鲁大师在线视频播放免费观看 | 电影在线观看+伦理片| 亚洲丰满老熟女激情av| 国内不卡不区二区三区| 99亚洲男女激情在线观看| 综合久久av一区二区三区|