日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

前期不做分庫(kù)分表設(shè)計(jì),數(shù)據(jù)上億,讓我重構(gòu)!領(lǐng)導(dǎo):做不好,就辭職

 king9413 2019-08-31

據(jù)說(shuō)是阿里 P8 級(jí)高級(jí)架構(gòu)師吐血總結(jié)的一份 Java 核心知識(shí).pdf, 內(nèi)容覆蓋很廣,Java 核心基礎(chǔ)、Java 多線(xiàn)程、高并發(fā)、Spring、微服務(wù)、Netty 與 RPC、Zookeeper、Kafka、RabbitMQ、Habase、設(shè)計(jì)模式、負(fù)載均衡、分布式緩存、Hadoop、Spark、Storm、云計(jì)算等。

另外,附送 100G 學(xué)習(xí)、面試視頻文檔喲~

獲取方式:【關(guān)注 轉(zhuǎn)發(fā)】后,私信我,回復(fù)關(guān)鍵字【資源】,即可免費(fèi)無(wú)套路獲取哦~

以下是資源的部分目錄以及內(nèi)容截圖:

前期不做分庫(kù)分表設(shè)計(jì),數(shù)據(jù)上億,讓我重構(gòu)!領(lǐng)導(dǎo):做不好,就辭職

前期不做分庫(kù)分表設(shè)計(jì),數(shù)據(jù)上億,讓我重構(gòu)!領(lǐng)導(dǎo):做不好,就辭職

前期不做分庫(kù)分表設(shè)計(jì),數(shù)據(jù)上億,讓我重構(gòu)!領(lǐng)導(dǎo):做不好,就辭職

前期不做分庫(kù)分表設(shè)計(jì),數(shù)據(jù)上億,讓我重構(gòu)!領(lǐng)導(dǎo):做不好,就辭職

前期不做分庫(kù)分表設(shè)計(jì),數(shù)據(jù)上億,讓我重構(gòu)!領(lǐng)導(dǎo):做不好,就辭職

重要的事再說(shuō)一遍,獲取方式:【關(guān)注 轉(zhuǎn)發(fā)】后,私信我,回復(fù)關(guān)鍵字【資源】,即可免費(fèi)無(wú)套路獲取哦~

正文開(kāi)始,前言

前期不做分庫(kù)分表設(shè)計(jì),數(shù)據(jù)上億,讓我重構(gòu)!領(lǐng)導(dǎo):做不好,就辭職

背景

前不久發(fā)過(guò)兩篇關(guān)于分表的文章:

  • 一次分表踩坑實(shí)踐的探討
  • 分表后需要注意的二三事

從標(biāo)題可以看得出來(lái),當(dāng)時(shí)我們只做了分表;還是由于業(yè)務(wù)發(fā)展,截止到現(xiàn)在也做了分庫(kù),目前看來(lái)都還比較順利,所以借著腦子還記得清楚來(lái)一次復(fù)盤(pán)。

先來(lái)回顧下整個(gè)分庫(kù)分表的流程如下:

前期不做分庫(kù)分表設(shè)計(jì),數(shù)據(jù)上億,讓我重構(gòu)!領(lǐng)導(dǎo):做不好,就辭職

整個(gè)過(guò)程也很好理解,基本符合大部分公司的一個(gè)發(fā)展方向。

很少會(huì)有業(yè)務(wù)一開(kāi)始就會(huì)設(shè)計(jì)為分庫(kù)分表,雖說(shuō)這樣會(huì)減少后續(xù)的坑,但部分公司剛開(kāi)始都是以業(yè)務(wù)為主。

直到業(yè)務(wù)發(fā)展到單表無(wú)法支撐時(shí),自然而然會(huì)考慮分表甚至分庫(kù)的事情。

于是本篇會(huì)作一次總結(jié),之前提過(guò)的內(nèi)容可能會(huì)再重復(fù)一次。

分表

首先討論下什么樣的情況下適合分表?

根據(jù)我的經(jīng)驗(yàn)來(lái)看,當(dāng)某張表的數(shù)據(jù)量已經(jīng)達(dá)到千萬(wàn)甚至上億,同時(shí)日增數(shù)據(jù)量在 2% 以上。

當(dāng)然這些數(shù)字并不是絕對(duì)的,最重要的還是對(duì)這張表的寫(xiě)入和查詢(xún)都已經(jīng)影響到正常業(yè)務(wù)執(zhí)行,比如查詢(xún)速度明顯下降,數(shù)據(jù)庫(kù)整體 IO 居高不下等。

而談到分表時(shí)我們著重討論的還是水平分表;

前期不做分庫(kù)分表設(shè)計(jì),數(shù)據(jù)上億,讓我重構(gòu)!領(lǐng)導(dǎo):做不好,就辭職

也就是將一張大表數(shù)據(jù)通過(guò)某種路由算法將數(shù)據(jù)盡可能的均勻分配到 N 張小表中。

Range

而分表策略也有好幾種,分別適用不同的場(chǎng)景。

首先第一種是按照范圍劃分,比如我們可以將某張表的創(chuàng)建時(shí)間按照日期劃分存為月表;也可以將某張表的主鍵按照范圍劃分,比如 【1~10000】在一張表,【10001~20000】在一張表,以此類(lèi)推。

前期不做分庫(kù)分表設(shè)計(jì),數(shù)據(jù)上億,讓我重構(gòu)!領(lǐng)導(dǎo):做不好,就辭職

這樣的分表適合需要對(duì)數(shù)據(jù)做歸檔處理,比如系統(tǒng)默認(rèn)只提供近三個(gè)月歷史數(shù)據(jù)的查詢(xún)功能,這樣也方便操作;只需要把三月之前的數(shù)據(jù)單獨(dú)移走備份保存即可)。

這個(gè)方案有好處也有弊端:

  • 好處是自帶水平擴(kuò)展,不需要過(guò)多干預(yù)。
  • 缺點(diǎn)是可能會(huì)出現(xiàn)數(shù)據(jù)不均勻的情況(比如某個(gè)月請(qǐng)求暴增)。

Hash

按照日期這樣的范圍分表固然簡(jiǎn)單,但適用范圍還是比較窄;畢竟我們大部分的數(shù)據(jù)查詢(xún)都不想帶上時(shí)間。

比如某個(gè)用戶(hù)想查詢(xún)他產(chǎn)生的所有訂單信息,這是很常見(jiàn)的需求。

于是我們分表的維度就得改改,分表算法可以采用主流的 hash mod 的組合。

這是一個(gè)經(jīng)典的算法,大名鼎鼎的 HashMap 也是這樣來(lái)存儲(chǔ)數(shù)據(jù)。

假設(shè)我們這里將原有的一張大表訂單信息分為 64 張分表:

前期不做分庫(kù)分表設(shè)計(jì),數(shù)據(jù)上億,讓我重構(gòu)!領(lǐng)導(dǎo):做不好,就辭職

這里的 hash 便是將我們需要分表的字段進(jìn)行一次散列運(yùn)算,使得經(jīng)過(guò)散列的數(shù)據(jù)盡可能的均勻并且不重復(fù)。

當(dāng)然如果本身這個(gè)字段就是一個(gè)整形并且不重復(fù)也可以省略這個(gè)步驟,直接進(jìn)行 Mod 得到分表下標(biāo)即可。

分表數(shù)量選擇

至于這里的分表數(shù)量(64)也是有講究的,具體設(shè)為多少這個(gè)沒(méi)有標(biāo)準(zhǔn)值,需要根據(jù)自身業(yè)務(wù)發(fā)展,數(shù)據(jù)增量進(jìn)行預(yù)估。

根據(jù)我個(gè)人的經(jīng)驗(yàn)來(lái)看,至少需要保證分好之后的小表在業(yè)務(wù)發(fā)展的幾年之內(nèi)都不會(huì)出現(xiàn)單表數(shù)據(jù)量過(guò)大(比如達(dá)到千萬(wàn)級(jí))。

我更傾向于在數(shù)據(jù)庫(kù)可接受的范圍內(nèi)盡可能的增大這個(gè)分表數(shù),畢竟如果后續(xù)小表也達(dá)到瓶頸需要再進(jìn)行一次分表擴(kuò)容,那是非常痛苦的。

目前筆者還沒(méi)經(jīng)歷這一步,所以本文沒(méi)有相關(guān)介紹。

但是這個(gè)數(shù)量又不是瞎選的,和 HashMap 一樣,也建議得是 2^n,這樣可以方便在擴(kuò)容的時(shí)盡可能的少遷移數(shù)據(jù)。

Range Hash

當(dāng)然還有一種思路, Range 和 Hash 是否可以混用。

比如我們一開(kāi)始采用的是 Hash 分表,但是數(shù)據(jù)增長(zhǎng)巨大,導(dǎo)致每張分表數(shù)據(jù)很快達(dá)到瓶頸,這樣就不得不再做擴(kuò)容,比如由 64 張表擴(kuò)容到 256 張。

但擴(kuò)容時(shí)想要做到不停機(jī)遷移數(shù)據(jù)非常困難,即便是停機(jī),那停多久呢?也不好說(shuō)。

所以我們是否可以在 Mod 分表的基礎(chǔ)上再分為月表,借助于 Range 自身的擴(kuò)展性就不用考慮后續(xù)數(shù)據(jù)遷移的事情了。

前期不做分庫(kù)分表設(shè)計(jì),數(shù)據(jù)上億,讓我重構(gòu)!領(lǐng)導(dǎo):做不好,就辭職

這種方式理論可行,但我沒(méi)有實(shí)際用過(guò),給大家的思路做個(gè)參考吧。

煩人的數(shù)據(jù)遷移

分表規(guī)則弄好后其實(shí)只是完成了分表的第一步,真正麻煩的是數(shù)據(jù)遷移,或者說(shuō)是如何做到對(duì)業(yè)務(wù)影響最小的數(shù)據(jù)遷移。

除非是一開(kāi)始就做了分表,所以數(shù)據(jù)遷移這一步驟肯定是跑不掉的。

下面整理下目前我們的做法供大家參考:

  1. 一旦分表上線(xiàn)后所有的數(shù)據(jù)寫(xiě)入、查詢(xún)都是針對(duì)于分表的,所以原有大表內(nèi)的數(shù)據(jù)必須得遷移到分表里,不然對(duì)業(yè)務(wù)的影響極大。
  2. 我們估算了對(duì)一張 2 億左右的表進(jìn)行遷移,自己寫(xiě)的遷移程序,大概需要花 4~5 天的時(shí)間才能完成遷移。
  3. 意味著這段時(shí)間內(nèi),以前的數(shù)據(jù)對(duì)用戶(hù)是不可見(jiàn)的,顯然這樣業(yè)務(wù)不能接受。
  4. 于是我們做了一個(gè)兼容處理:分表改造上線(xiàn)后,所有新產(chǎn)生的數(shù)據(jù)寫(xiě)入分表,但對(duì)歷史數(shù)據(jù)的操作還走老表,這樣就少了數(shù)據(jù)遷移這一步驟。
  5. 只是需要在操作數(shù)據(jù)之前做一次路由判斷,當(dāng)新數(shù)據(jù)產(chǎn)生的足夠多時(shí)(我們是兩個(gè)月時(shí)間),幾乎所有的操作都是針對(duì)于分表,再?gòu)膸?kù)啟動(dòng)數(shù)據(jù)遷移,數(shù)據(jù)遷移完畢后將原有的路由判斷去掉。
  6. 最后所有的數(shù)據(jù)都從分表產(chǎn)生和寫(xiě)入。

至此整個(gè)分表操作完成。

前期不做分庫(kù)分表設(shè)計(jì),數(shù)據(jù)上億,讓我重構(gòu)!領(lǐng)導(dǎo):做不好,就辭職

前期不做分庫(kù)分表設(shè)計(jì),數(shù)據(jù)上億,讓我重構(gòu)!領(lǐng)導(dǎo):做不好,就辭職

業(yè)務(wù)兼容

同時(shí)分表之后還需要兼容其他業(yè)務(wù);比如原有的報(bào)表業(yè)務(wù)、分頁(yè)查詢(xún)等,現(xiàn)在來(lái)看看我們是如何處理的。

報(bào)表

首先是報(bào)表,沒(méi)分表之前之間查詢(xún)一張表就搞定了,現(xiàn)在不同,由一張表變?yōu)?N 張表。

所以原有的查詢(xún)要改為遍歷所有的分表,考慮到性能可以利用多線(xiàn)程并發(fā)查詢(xún)分表數(shù)據(jù)然后匯總。

不過(guò)只依靠 Java 來(lái)對(duì)這么大量的數(shù)據(jù)做統(tǒng)計(jì)分析還是不現(xiàn)實(shí),剛開(kāi)始可以應(yīng)付過(guò)去,后續(xù)還得用上大數(shù)據(jù)平臺(tái)來(lái)處理。

查詢(xún)

再一個(gè)是查詢(xún),原有的分頁(yè)查詢(xún)肯定是不能用了,畢竟對(duì)上億的數(shù)據(jù)分頁(yè)其實(shí)沒(méi)什么意義。

只能提供通過(guò)分表字段的查詢(xún),比如是按照訂單 ID 分表,那查詢(xún)條件就得帶上這個(gè)字段,不然就會(huì)涉及到遍歷所有表。

這也是所有分表之后都會(huì)遇到的一個(gè)問(wèn)題,除非不用 MySQL 這類(lèi)關(guān)系型數(shù)據(jù)庫(kù)。

分庫(kù)

分表完成后可以解決單表的壓力,但數(shù)據(jù)庫(kù)本身的壓力卻沒(méi)有下降。

我們?cè)谕瓿煞直碇蟮囊粋€(gè)月內(nèi)又由于數(shù)據(jù)庫(kù)里“其他表”的寫(xiě)入導(dǎo)致整個(gè)數(shù)據(jù)庫(kù) IO 增加,而且這些“其他表”還和業(yè)務(wù)關(guān)系不大。

也就是說(shuō)一些可有可無(wú)的數(shù)據(jù)導(dǎo)致了整體業(yè)務(wù)受影響,這是非常不劃算的事情。

于是我們便把這幾張表單獨(dú)移到一個(gè)新的數(shù)據(jù)庫(kù)中,完全和現(xiàn)有的業(yè)務(wù)隔離開(kāi)來(lái)。

這樣就會(huì)涉及到幾個(gè)改造:

  1. 應(yīng)用自身對(duì)這些數(shù)據(jù)的查詢(xún)、寫(xiě)入都要改為調(diào)用一個(gè)獨(dú)立的 Dubbo 服務(wù),由這個(gè)服務(wù)對(duì)遷移的表進(jìn)行操作。
  2. 暫時(shí)不做數(shù)據(jù)遷移,所以查詢(xún)時(shí)也得按照分表那樣做一個(gè)兼容,如果查詢(xún)老數(shù)據(jù)就要在當(dāng)前庫(kù)查詢(xún),新數(shù)據(jù)就要調(diào)用 Dubbo 接口進(jìn)行查詢(xún)。
  3. 對(duì)這些表的一些關(guān)聯(lián)查詢(xún)也得改造為查詢(xún) Dubbo 接口,在內(nèi)存中進(jìn)行拼接即可。
  4. 如果數(shù)據(jù)量確實(shí)很大,也可將同步的 Dubbo 接口換為寫(xiě)入消息隊(duì)列來(lái)提高吞吐量。

目前我們將這類(lèi)數(shù)據(jù)量巨大但對(duì)業(yè)務(wù)不太影響的表單獨(dú)遷到一個(gè)庫(kù)后,數(shù)據(jù)庫(kù)的整體 IO 下降明顯,業(yè)務(wù)也恢復(fù)正常。

總結(jié)

最后我們還需要做一步歷史數(shù)據(jù)歸檔的操作,將 N 個(gè)月之前的數(shù)據(jù)要定期遷移到 HBASE 之類(lèi)存儲(chǔ),保證 MySQL 中的數(shù)據(jù)一直保持在一個(gè)可接受的范圍。

而歸檔數(shù)據(jù)的查詢(xún)便依賴(lài)于大數(shù)據(jù)提供服務(wù)。

本次分庫(kù)分表是一次非常難得的實(shí)踐操作,網(wǎng)上大部分的資料都是在汽車(chē)出廠(chǎng)前就換好了輪胎。

而我們大部分碰到的場(chǎng)景都是要對(duì)高速路上跑著的車(chē)子換胎,一不小心就“車(chē)毀人亡”。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀(guān)點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多