Mysql分表查詢海量數據和解決方案


眾所周知數據庫的管理往往離不開各種的數據優化,而要想進行優化通常我們都是通過參數來完成優化的。那么到底這些參數有哪些呢?為此在本篇文章中課課家筆者就為大家簡單介紹MySQL,以供大家參考參考,希望能幫助到大家。

Mysql分表查詢海量數據和解決方案_Mysql_大數據_數據庫_課課家
  1) 分布式DB水平切分中用到的主要關鍵技術:分庫,分表,M-S,集群,負載均衡
  2) 需求分析:一個大型互聯網應用每天幾十億的PV對DB造成了相當高的負載,對系統的穩定性的擴展性帶來極大挑戰。
  3) 現有解決方式:通過數據切分提高網站性能,橫向擴展數據層
  水平切分DB,有效降低了單台機器的負載,也減小了宕機的可能性。
  集群方案:解決DB宕機帶來的單點DB不能訪問問題。
  讀寫分離策略:極大限度提高了應用中Read數據的速度和並發量。
  典型例子:Taobao,Alibaba,Tencent,它們大都實現了自己的分布式數據訪問層(DDAL)。Taobao的基於ibatis和spring的的分布式數據訪問層,已有多年的應用,運行效率和生產實效性得到了開發人員和用戶的肯定。
  水平切分需要考慮的后續問題:分庫后路由規則的選擇和制定,以及后期擴展。如,如何以最少的數據遷移達到最大容量的擴展。因些路由表分規則以及負載均衡的考慮很重要。
  4)對於DB切分,實質上就是數據切分。下面從What, Why, How三個方面來講述。
  What?什么是數據切分?
  具體將有什么樣的切分方式呢和路由方式呢?舉個簡單的例子:我們針對一個應用中的日志來說明,比如日志文章(article)表有如下字段:
  article_id(int),title(varchar(128)),content(varchar(1024)),user_id(int)
  面對這樣的一個表,我們怎樣切分呢?怎樣將這樣的數據分布到不同的數據庫中的表中去呢?其實分析blog的應用,我們不難得出這樣的結論:blog的應用中,用戶分為兩種:瀏覽者和blog的主人。瀏覽者瀏覽某個blog,實際上是在一個特定的用戶的blog下進行瀏覽的,而blog的主人管理自己的blog,也同樣是在特定的用戶blog下進行操作的(在自己的空間下)。所謂的特定的用戶,用數據庫的字段表示就是“user_id”。就是這個“user_id”,它就是我們需要的分庫的依據和規則的基礎。我們可以這樣做,將user_id為1~10000的所有的文章信息放入DB1中的article表中,將user_id為10001~20000的所有文章信息放入DB2中的article表中,以此類推,一直到DBn。這樣一來,文章數據就很自然的被分到了各個數據庫中,達到了數據切分的目的。接下來要解決的問題就是怎樣找到具體的數據庫呢?其實問題也是簡單明顯的,既然分庫的時候我們用到了區分字段user_id,那么很自然,數據庫路由的過程當然還是少不了user_id的。考慮一下我們剛才呈現的blog應用,不管是訪問別人的blog還是管理自己的blog,總之我都要知道這個blog的用戶是誰吧,也就是我們知道了這個blog的user_id,就利用這個user_id,利用分庫時候的規則,反過來定位具體的數據庫,比如user_id是234,利用該才的規則,就應該定位到DB1,假如user_id是12343,利用該才的規則,就應該定位到DB2。以此類推,利用分庫的規則,反向的路由到具體的DB,這個過程我們稱之為“DB路由”。
  當然考慮到數據切分的DB設計必然是非常規,不正統的DB設計。那么什么樣的DB設計是正統的DB設計呢?
  我們平常規規矩矩用的基本都是。平常我們會自覺的按照范式來設計我們的數據庫,負載高點可能考慮使用相關的Replication機制來提高讀寫的吞吐和性能,這可能已經可以滿足很多需求,但這套機制自身的缺陷還是比較顯而易見的。上面提到的“自覺的按照范式設計”。考慮到數據切分的DB設計,將違背這個通常的規矩和約束,為了切分,我們不得不在數據庫的表中出現冗余字段,用作區分字段或者叫做分庫的標記字段,比如上面的article的例子中的user_id這樣的字段(當然,剛才的例子並沒有很好的體現出user_id的冗余性,因為user_id這個字段即使就是不分庫,也是要出現的,算是我們撿了便宜吧)。當然冗余字段的出現並不只是在分庫的場景下才出現的,在很多大型應用中,冗余也是必須的,這個涉及到高效DB的設計。
  Mysql實現海量海量數據存儲查詢時,主要有幾個關鍵點,分表,分庫,集群,M-S,負載均衡。
  其中分庫分表是很重要的一點。分庫是如何將海量的MySQL數據放到不同的服務器中,分表則是在分庫基礎上對數據現進行邏輯上的划分。

眾所周知數據庫的管理往往離不開各種的數據優化,而要想進行優化通常我們都是通過參數來完成優化的。那么到底這些參數有哪些呢?為此在本篇文章中課課家筆者就為大家簡單介紹MySQL,以供大家參考參考,希望能幫助到大家。
  數據划分可有多種方式,找到一個主鍵后,可以按號段分,也可以Hash取模分,也可以選擇在認證庫中保存DB配置。具體如何選擇具體情況具體分析。
  划分后,就是后期的查找和維護工作了。為了實現快速查找,得有一個高效的查找機制,這里可以選擇建索引的方法,並充分借鑒已有的成熟的路由技術。同時,增減數據時,還要考慮到索引的維護,數據遷移時,數據的重新分攤也是一個要考慮的問題。下面具體分析數據變更的情形:
  大型應用中Mysql經常碰到數據無限擴充的情況。常用解決方案如下:
  MySQL master/slave: 只適合大量讀的情形,未必適合海量數據。
  MySQL cluster: 提供的可能不是大家想要那種功能。
  MySQL proxy: MySQL master/slave配合
  MySQL 5.1 partition: 只是將一個表存儲上邏輯分開,部分改善了性能,但是可擴展性仍然是問題。
  MySQL對於海量數據按應用邏輯分表分數據庫,通過程序來決定數據存放的表。但是
  跨區查詢是一個問題,當需要快速查找一個數據時你得准確知道那個數據存在哪個地方。為了達到這個目的,可以將分表邏輯放到中間層,這樣上層的應用則就簡單很多,也便於擴展。下面結合網上一個關於分表查詢很好的例子分析:
  Why?為什么要切分數據?
  1) 像Oracle這樣成熟穩定的DB可以支撐海量數據的存儲和查詢,但是價格不是所有人都承受得起。
  2) 負載高點時,Master-Slaver模式中存在瓶頸。現有技術中,在負載高點時使用相關的Replication機制來實現相關的讀寫的吞吐性能。這種機制存在兩個瓶頸:一是有效性依賴於讀操作的比例,這里Master往往會成為瓶頸所在,寫操作時需要一個順序隊列來執行,過載時Master會承受不住,Slaver的數據同步延遲也會很大,同時還會消耗CPU的計算能力,為write操作在Master上執行以后還是需要在每台slave機器上都跑一次。而Sharding可以輕松的將計算,存儲,I/O並行分發到多台機器上,這樣可以充分利用多台機器各種處理能力,同時可以避免單點失敗,提供系統的可用性,進行很好的錯誤隔離。
  3) 用免費的MySQL和廉價的Server甚至是PC做集群,達到小型機+大型商業DB的效果,減少大量的資金投入,降低運營成本,何樂而不為呢?
  How?如何切分數據?
  先對數據切分的方法和形式進行比較詳細的闡述和說明。
  數據切分可以是物理上的,對數據通過一系列的切分規則將數據分布到不同的DB服務器上,通過路由規則路由訪問特定的數據庫,這樣一來每次訪問面對的就不是單台服務器了,而是N台服務器,這樣就可以降低單台機器的負載壓力。
  數據切分也可以是數據庫內的,對數據通過一系列的切分規則,將數據分布到一個數據庫的不同表中,比如將article分為article_001,article_002等子表,若干個子表水平拼合有組成了邏輯上一個完整的article表,這樣做的目的其實也是很簡單的。舉個例子說明,比如article表中現在有5000w條數據,此時我們需要在這個表中增加(insert)一條新的數據,insert完畢后,數據庫會針對這張表重新建立索引,5000w行數據建立索引的系統開銷還是不容忽視的。但是反過來,假如我們將這個表分成100個table呢,從article_001一直到article_100,5000w行數據平均下來,每個子表里邊就只有50萬行數據,這時候我們向一張只有50w行數據的table中insert數據后建立索引的時間就會呈數量級的下降,極大了提高了DB的運行時效率,提高了DB的並發量。當然分表的好處還不知這些,還有諸如寫操作的鎖操作等,都會帶來很多顯然的好處。
  綜上,分庫降低了單點機器的負載;分表,提高了數據操作的效率,尤其是Write操作的效率。
  上文中提到,要想做到數據的水平切分,在每一個表中都要有相冗余字符作為切分依據和標記字段,通常的應用中我們選用user_id作為區分字段,基於此就有如下三種分庫的方式和規則:(當然還可以有其他的方式)

眾所周知數據庫的管理往往離不開各種的數據優化,而要想進行優化通常我們都是通過參數來完成優化的。那么到底這些參數有哪些呢?為此在本篇文章中課課家筆者就為大家簡單介紹MySQL,以供大家參考參考,希望能幫助到大家。
  按號段分:
  (1) user_id為區分,1~1000的對應DB1,1001~2000的對應DB2,以此類推;
  優點:可部分遷移
  缺點:數據分布不均
  (2) hash取模分:
  對user_id進行hash(或者如果user_id是數值型的話直接使用user_id的值也可),然后用一個特定的數字,比如應用中需要將一個數據庫切分成4個數據庫的話,我們就用4這個數字對user_id的hash值進行取模運算,也就是user_id%4,這樣的話每次運算就有四種可能:結果為1的時候對應DB1;結果為2的時候對應DB2;結果為3的時候對應DB3;結果為0的時候對應DB4,這樣一來就非常均勻的將數據分配到4個DB中。
  優點:數據分布均勻
  缺點:數據遷移的時候麻煩,不能按照機器性能分攤數據
  (3) 在認證庫中保存數據庫配置
  就是建立一個DB,這個DB單獨保存user_id到DB的映射關系,每次訪問數據庫的時候都要先查詢一次這個數據庫,以得到具體的DB信息,然后才能進行我們需要的查詢操作。
  優點:靈活性強,一對一關系
  缺點:每次查詢之前都要多一次查詢,性能大打折扣
  以上就是通常的開發中我們選擇的三種方式,有些復雜的項目中可能會混合使用這三種
  方式。
  4) 接下來對分布式數據庫解決海量數據的存訪問題做進一步介紹
  分布式數據方案提供功能如下:
  (1)提供分庫規則和路由規則(RouteRule簡稱RR),將上面的說明中提到的三中切分規則直接內嵌入本系統,具體的嵌入方式在接下來的內容中進行詳細的說明和論述;
  (2)引入集群(Group)的概念,解決容錯性的問題,保證數據的高可用性;
  (3)引入負載均衡策略(LoadBalancePolicy簡稱LB);
  (4)引入集群節點可用性探測機制,對單點機器的可用性進行定時的偵測,以保證LB策略的正確實施,以確保系統的高度穩定性;
  (5)引入讀/寫分離,提高數據的查詢速度;
  5)MySQL partition
  MySQL 5.1 的 partition 功能由於單張表的數據跨文件,批量查詢時候同樣存在上述問題,不過它是在 MySQL 內部實現的,不需要外部調用者關心。其查詢實現的原理應該大致類似。但 partition 只解決了 IO 的瓶頸,並不能解決 CPU 計算的瓶頸,因此無法代替傳統的手工分表方式。
  對於這個問題還有許多其他方法,學網絡的應該很熟悉DNS的兩種查詢方法:遞歸方式和迭代方式。這些思路也可以應用到數據庫查詢中來並應用。如,HSCALE分表分數據庫的思路:HSCALE是在MySQL proxy的基礎上,在MySQL proxy的層面將上層的請求分配到實際的表上。實際的原理是通過攔截SQL進行替換和服務器重定向再將SQL傳遞到目標服務器上。它的分表算法可以由自定義的Lua腳本來實現,非常靈活。目前已經能支持同數據庫分表,跨數據庫的實現也將增加,因為在MySQL proxy的框架下,這並不是很困難的事情。使用HSCALE有2個開銷,一是網絡層面的,、MySQL proxy對每個SQL會增加0.0 ms級的網絡延遲,如果增加了HSCALE, 則會增加0. ms級延遲。第2個開銷則是MySQL proxy, Lua, SQL解析,HSCALE算法等造成。現在的版本或許不是很成熟,但是在原理上基本上沒多大障礙,發展下去將是一個不錯的選擇。
  以上就是關於大數據的知識點了。喜歡的可以分享給你的朋友,也可以點贊噢~更多內容,就在課課家!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM