分表后需要注意的那些事儿
還是先來簡單回顧下上次提到了哪些內(nèi)容:
- 分表策略:哈希、時(shí)間歸檔等。
- 分表字段的選擇。
- 數(shù)據(jù)遷移方案。
而本篇文章的背景是在我們上線這段時(shí)間遇到的一些問題并嘗試解決的方案。
問題產(chǎn)生
之前提到在分表應(yīng)用上線前我們需要將原有表的數(shù)據(jù)遷移到新表中,這樣才能保證業(yè)務(wù)不受影響。
所以我們單獨(dú)寫了一個(gè)遷移應(yīng)用,它負(fù)責(zé)將大表中的數(shù)據(jù)遷移到 64 張分表,而再遷移過程中產(chǎn)生的數(shù)據(jù)畢竟是少數(shù),最后在上線當(dāng)晚再次遷移過去即可。
一切想的很美好,當(dāng)這個(gè)應(yīng)用上線后卻發(fā)現(xiàn)沒這么簡單。
數(shù)據(jù)庫負(fù)載升高
首先第一個(gè)問題是數(shù)據(jù)庫自己就頂不住了,在我們上這個(gè)遷移程序之前數(shù)據(jù)庫的壓力本身就比較大,這個(gè)應(yīng)用一上去就成了最后一根稻草。
最后導(dǎo)致的結(jié)果是:所有連接了數(shù)據(jù)庫的程序大部分的操作都出現(xiàn)超時(shí),獲取不到數(shù)據(jù)庫連接等一系列的異常。
最后沒辦法我們只能把這個(gè)應(yīng)用放到凌晨執(zhí)行,但其實(shí)后面觀察發(fā)現(xiàn)依然不行。
雖說凌晨的業(yè)務(wù)量下降,但依然有少部分的請求過來,也會出現(xiàn)各種數(shù)據(jù)庫異常。
再一個(gè)是遷移程序的效率也非常低下,按照這樣是速度,我們預(yù)估了一下遷移時(shí)間,大約需要 10 幾天才能把三張最大的表(3、4億的數(shù)據(jù))遷移到分表中。
于是我們換了一個(gè)方案,將這個(gè)遷移程序在從庫中運(yùn)行,最后再用運(yùn)維的方法將分表直接導(dǎo)入進(jìn)主庫。
因?yàn)閺膸斓膲毫σ戎鲙煨『芏?#xff0c;對業(yè)務(wù)的影響很小,同時(shí)遷移的效率也要快很多。
即便是這樣也花了一晚上+一個(gè)白天的時(shí)間才將一張 1億的數(shù)據(jù)遷移完成,但是業(yè)務(wù)上的壓力越來越大,數(shù)據(jù)量再不斷新增,這個(gè)效率依然不夠。
兼容方案
最終沒辦法只有想一個(gè)不遷移數(shù)據(jù)的方案,但是新產(chǎn)生的數(shù)據(jù)還是往分表里寫,至少保證大表的數(shù)據(jù)不再新增。
但這樣對于以前的數(shù)據(jù)咋辦呢?總不能不讓看了吧。
其實(shí)對于數(shù)據(jù)的操作無非就分為 增刪改查,就這四種操作來看看如何兼容。
新增
新增最簡單,所有的數(shù)據(jù)根據(jù)分表規(guī)則直接寫入新表,這樣可以保證老表的數(shù)據(jù)不再新增。
刪除
刪除就要比新增稍微復(fù)雜一些,比如用戶想要?jiǎng)h除他個(gè)人產(chǎn)生的一條信息(比如說是訂單數(shù)據(jù)),有可能這個(gè)數(shù)據(jù)在新表也可能在老表。
所以刪除時(shí)優(yōu)先刪除新表(畢竟新產(chǎn)生的數(shù)據(jù)訪問的頻次越高),如果刪除失敗再從老表刪除一次。
修改
而修改同理,同樣的會不確定數(shù)據(jù)存在于哪里,所以先要修改新表,失敗后再次修改老表。
查詢
查詢相對就要復(fù)雜一些了,因?yàn)檫@些大表的數(shù)據(jù)大部分都是存放一個(gè)用戶產(chǎn)生的多條記錄(比如一個(gè)用戶的訂單信息)。
這時(shí)在頁面上通常都會有分頁,并且按照時(shí)間進(jìn)行排序。
麻煩的地方就出在這里:既然是要分頁那就有可能出現(xiàn)要查詢一部分分表數(shù)據(jù)和原來的大表數(shù)據(jù)做組合。
所以這里的查詢其實(shí)分為三種情況。
- 首先查詢的時(shí)候要計(jì)算這個(gè)用戶所在分表中的數(shù)據(jù)可以分為幾頁。
- 第一步首先判斷當(dāng)前頁是否可以在分表中全部獲取,如果可以則直接從分表中取出數(shù)據(jù)返回(假設(shè)分頁中總共可以查詢 2 頁數(shù)據(jù),當(dāng)前為第 1 頁,那就全部取分表數(shù)據(jù))。
- 如果不可以就要判斷當(dāng)前頁數(shù)在分表中是否取不到任何一條數(shù)據(jù),如果是則直接取老表數(shù)據(jù)(比如現(xiàn)在要取第 5 頁的數(shù)據(jù),分表中一共才只有 2 頁數(shù)據(jù),所以第 5 頁數(shù)據(jù)只能全部從老表中獲取)。
- 但如果分表和老表都存在一部分?jǐn)?shù)據(jù)時(shí),則需要同時(shí)取兩張表然后做一個(gè)匯總再返回。
這種邏輯只適用于根據(jù)分表字段進(jìn)行查詢分頁的前提下
我想肯定會有朋友提出這樣是否會有性能問題?
同時(shí)如果在計(jì)算分表分頁數(shù)量時(shí)出現(xiàn)并發(fā)寫入的情況,導(dǎo)致分頁數(shù)量不準(zhǔn)從而對后續(xù)的查詢出現(xiàn)影響該怎么處理?
首先第一個(gè)性能問題:
其實(shí)這個(gè)要看怎么取舍,為了這樣的兼容目的其實(shí)會比常規(guī)查詢多出幾個(gè)步驟:
- 判斷當(dāng)前頁是否可以在分表中查詢。
- 當(dāng)新老表中都有數(shù)據(jù)時(shí)候需要額外多查詢一張大表。
第一個(gè)判斷邏輯其實(shí)是在內(nèi)存中計(jì)算,這個(gè)損耗我覺得完全可以忽略不計(jì)。
至于第二步確實(shí)會有損耗,畢竟多查了一張表。
但在分表之前所有的數(shù)據(jù)都是從老表中獲取的,當(dāng)時(shí)的業(yè)務(wù)也沒有出現(xiàn)問題;現(xiàn)在多的只是查詢分表而已,但分表的數(shù)據(jù)量肯定要比大表小的多,而且有索引,所以這個(gè)效率也不會慢多少。
而且根據(jù)局部性原理及用戶的使用習(xí)慣來看,老表中的數(shù)據(jù)很少會去查詢,隨著時(shí)間的推移所有的數(shù)據(jù)肯定都會從分表中獲取,逐漸老表就會成為歷史表。
而第二個(gè)并發(fā)帶來的問題我覺得影響也不大,一定要這個(gè)分頁準(zhǔn)的前提肯定得是加鎖了,但為了這樣一個(gè)不癢的小問題卻帶來性能的下降,我覺得是不劃算的。
而且后續(xù)我們也可以慢慢的將老表的數(shù)據(jù)遷移到新表,這樣就可以完全去掉這個(gè)兼容邏輯了,所有的數(shù)據(jù)都從分表中獲取。
總結(jié)
還是之前那句話,這里的各種操作、方法不適合所有人,畢竟脫離場景都是耍牛氓。
比如分表搞的早,業(yè)務(wù)上允許一定的時(shí)間將數(shù)據(jù)遷移到分表那就不會有這次的兼容處理。
甚至一開始業(yè)務(wù)規(guī)劃合理、團(tuán)隊(duì)架構(gòu)師看的長遠(yuǎn),一來就將關(guān)鍵數(shù)據(jù)分表存儲那根本就不會有數(shù)據(jù)遷移這個(gè)流程(大廠有經(jīng)驗(yàn)的團(tuán)隊(duì)可能,小公司小作坊都得靠自己摸索)。
這段期間也被數(shù)據(jù)庫折騰慘了,數(shù)據(jù)庫是最后一根稻草果然也不是瞎說的。
轉(zhuǎn)載于:https://www.cnblogs.com/CQqf2019/p/11014695.html
總結(jié)
以上是生活随笔為你收集整理的分表后需要注意的那些事儿的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CSS布局之脱离文档流详解——浮动、绝对
- 下一篇: 微信小程序的z-index在苹果ios无