兩次不同的分表實踐總結

有幸在兩家不同的公司不同程度的參與了涉及分表的項目课蔬,其背景烁峭、分表方式容客、結果均有不同秕铛,根據(jù)自己的實際感受進行了簡單的總結歸納约郁,形成此文,如有不正之處但两,歡迎各位看客指正

先說幾點自己的總結

1.為什么要分表? 及分表時機

我們都知道鬓梅,當表數(shù)據(jù)量達到一定程度后,就會有慢查出現(xiàn)谨湘。根據(jù)自己對項目的感受和觀察來看绽快,當一個表的字段不算特別多,且索引合理紧阔,大部分sql合理(少回表坊罢、盡可能不聯(lián)表或少聯(lián)表等等)的情況下,一個表的數(shù)據(jù)量可能到2000W到3000W左右就可能需要考慮分表了擅耽,到了5000W上下活孩,分表可能就已經(jīng)到了迫不及待的地步了。不過具體這個區(qū)間乖仇,也是根據(jù)自己的感受估計的憾儒,實際上參與的兩次分表均達到了5000W以上的數(shù)據(jù)量询兴,甚至第一次進行分表時數(shù)據(jù)量已經(jīng)達到三四億(除了用id查,其他的條件查詢似乎都查不動的地步)


2.分表的方式起趾?

一般情況下诗舰,有根據(jù)業(yè)務參數(shù)(例如用戶id或其他業(yè)務id)哈希或者取模的方式來分表,或者根據(jù)時間來分表例如年训裆、月眶根、周,恰好自己這兩次分表一次是按用戶id取模分表的边琉,另一次是按月分表的汛闸。具體如何選擇,感覺并無絕對的對錯艺骂,按自己總結來看主要需要考慮以下幾點:

  • 分表后數(shù)據(jù)能較為均勻的分散到分表中
  • 便于兼容查詢
  • 從業(yè)務的角度來思考清晰合理诸老,便于以后業(yè)務擴展
  • 盡量減少需要跨表merge
  • 如果能通過分表來把數(shù)據(jù)的冷熱區(qū)分開就更好了
  • 數(shù)據(jù)維護成本

其實兩次分表的操作在分表方式的選擇上,都是經(jīng)過一定考慮的钳恕,但后來也確實發(fā)現(xiàn)遇到了一些問題别伏,后文詳細贅述


3.關于分表后上線,及數(shù)據(jù)遷移的問題

感覺自己兩次分表經(jīng)歷在這塊都算是做的比較好的忧额,幾乎都做到了不停服或盡量少停服上線(第一次停了約1小時厘肮,第二次用戶完全無感,主要是追數(shù)據(jù)的方式不同導致的睦番,后文贅述具體情況)类茂,就是在數(shù)據(jù)字典中增加了業(yè)務開關(配置中心直接修改,不需要發(fā)版)托嚣,主要是讀開關和寫開關巩检,實話講,第一次這個設計時是有人指導的示启,第二次感覺這個方式不錯兢哭,就直接沿用保留了相關開關設計,整體的上線流程如下:
1.先寫好查分表的程序夫嗓,是一個單獨的邏輯策略類迟螺,原來查大表的是另一個策略類,策略工廠中依據(jù)讀開關和寫開關來控制走哪套策略舍咖。
2.上線時默認雙寫矩父,讀老的大表,相當于查詢完全沒改排霉,只是數(shù)據(jù)寫入的時候多寫了一份
3.等待分表的數(shù)據(jù)和老表完全一致后窍株,切換讀開關,改成讀新的分表,這樣一旦有問題還能隨時切回老表夹姥,方便快速回滾
4.穩(wěn)定一段時間后(看具體情況杉武,可以一周,也可以一個月)辙售,若老的大表確實沒有維護需求了轻抱,可將寫開關改為只寫新的分表,并在下次版本發(fā)布時旦部,將讀開關和寫開關的邏輯下掉祈搜。


4.關于id發(fā)號器

最好是有單獨的id發(fā)號器,或者簡單點就用一個自增長的只有一個主鍵的數(shù)據(jù)庫表來做id發(fā)號器(實際兩次分表都是這么玩的)士八,如果是雪花算法或者其他的方式容燕,感覺要么id不是單調(diào)的,要么過于復雜了(個人感覺)


5.關于無法通過分表字段作為條件的查詢

個人想法還是盡量在選擇分表方式的時候能夠覆蓋C端的絕大多數(shù)查詢婚度,運營后臺或者其他偏B端的服務蘸秘,可以通過構建ES寬表等方式來查詢,實在無法覆蓋的蝗茁,可以考慮根據(jù)不同的業(yè)務參數(shù)分多套表醋虏。
實在不行的,再去考慮異構索引表哮翘,不是不能解決問題颈嚼,而是一旦異構索引表查出需要跨多張表去merge數(shù)據(jù)時,性能極差饭寺。這塊感覺也回到第二點分表方案的設計時需要考慮盡量減少跨表merge的問題了

具體回顧一下自己的兩次分表實踐

一.根據(jù)業(yè)務id(uid)取模分表

1.1經(jīng)歷概述

事項 具體方式/情況 解釋備注
業(yè)務背景 在線教育班課業(yè)務阻课,用戶課次表 用戶報班后,具體用戶每一節(jié)課的數(shù)據(jù)艰匙,冗余數(shù)據(jù)便于快速查詢限煞,避免查一次需要經(jīng)過多張表,且用戶報班后如果經(jīng)過調(diào)/退/換課有該表更好操作一些
分表前數(shù)據(jù)量 約4億
分表策略 根據(jù)用戶id取模分表 C端用戶查詢旬薯,基本都是學生基于uid查詢上課的課次
分表數(shù) 256張 shardingValue.getValue() % 256
分表框架 sharding-jdbc
潛在問題 部分查詢不是通過uid來查詢的 1.老師查的場景;

2.根據(jù)產(chǎn)品或班級查詢該班的學員時;
解決方式 易購索引表 將不帶uid的查詢條件晰骑,冗余一份和uid關聯(lián)異構索引表适秩,易購索引表當時還是采用的mysql表绊序,且由于數(shù)據(jù)量也很大,故也進行了分表秽荞,分32張
數(shù)據(jù)遷移 由于原表需要分256張骤公,易購索引表也需要分32張,且數(shù)據(jù)量較大扬跋,經(jīng)和DBA討論后阶捆,是由DBA寫的腳本程序來遷移同步 1.臨近上線時設定一個備份時間,將該備份時間之前的數(shù)據(jù),通過腳本初始化到新的兩套分表中

2.備份時間后的數(shù)據(jù)洒试,通過監(jiān)聽binlog時間追增量數(shù)據(jù)
上線方式 1.新的分表時獨立的項目去讀寫倍奢,原項目操作老表的地方,增加讀寫開關來切換操作的是老表還是新表

2.對新表的操作方式統(tǒng)一按發(fā)消息垒棋,或者調(diào)用新項目接口的方式來操作

3. 剛上線時業(yè)務開關切換寫老卒煞,讀老

4.執(zhí)行DBA的初始化腳本,初始化某備份時間前的數(shù)據(jù)到新的分表中

5.停服叼架,執(zhí)行DBA追增量數(shù)據(jù)的腳本畔裕,回溯從備份時間節(jié)點到停服的時間點中的binlog事件到新的分表中

6.一致后,開關切換到雙寫讀老表乖订,重啟服務

7.程序寫驗證無問題后扮饶,開關切換雙寫讀新

8.回歸驗證無問題,且確認新服務穩(wěn)定后乍构,開關切換寫新讀新

9.下次上線時下線開關邏輯代碼
由于是通過回溯binlog事件的方式追數(shù)據(jù)甜无,故在追增量數(shù)據(jù)時只能停服,否則一直會產(chǎn)生新的binlog事件
分表結果 1.分表前基本除id外已經(jīng)完全查不動了哥遮;分表后對于通過單個uid的查詢能快速查詢

2. 非uid查詢條件的毫蚓,在經(jīng)過易購索引表拿到uid后,也能正常查詢昔善,但一旦拿到的uid分散在N個分表中元潘,存在較大性能問題

3.批量uid查詢?nèi)绻稚⒃诙鄠€分表中也存在較大性能問題

4.由于八成以上的場景確實是根據(jù)單個uid的查詢箫攀,故一定程度上也解決或者緩解了最初完全查不動的問題川尖,但總體來講只能說勉強完成了最初期望的五六成吧

5.后續(xù)進一步分析業(yè)務后,從需求和業(yè)務邏輯上優(yōu)化江咳,取消了用戶課次表的維護
遇到的關鍵問題在于返咱,sharding-jdbc的多表路由和merge時存在較大的性能隱患钥庇,這點是一開始沒意識和考慮到的,這塊的相關資料例如這篇文章https://blog.csdn.net/D_19901719576/article/details/102925945
參與角色/程度 1.在他人的指導下咖摹,參與方案設計時的討論
2.參與實際開發(fā)落地评姨,加上自己共計三個開發(fā),我和另一個開發(fā)新寫的分表項目和策略萤晴,還有一個開發(fā)改造的業(yè)務代碼調(diào)用處(新增業(yè)務開關切換)
自己是首次參與到分表項目中吐句,方案設計時還算踴躍,應該說會有一些自己的想法店读,但由于不確定正確性嗦枢,故僅討論時偶爾提出,但最終還是按大家一致的意見落地屯断,總體來講還算是不錯的經(jīng)歷

1.2后續(xù)自己的總結與思考

1.關于課次表的合理性的一些思考:
1.1 用戶課次表的冗余比較方便的操作用戶調(diào)課/換課/退課等文虏,但確實會導致用戶的課次數(shù)據(jù)一直增加侣诺,表會膨脹,且該表的數(shù)據(jù)可以由多個小表組合得出氧秘,故當時的分析后續(xù)是取消了該表的維護年鸳,直接從業(yè)務和邏輯上改成了多個小表拼接出大表結果;
1.2 但用戶課次數(shù)據(jù)丸相,尤其是上過的課阻星,是否應該記錄下來,自己始終存在疑惑已添。

2.如果保留用戶上課的數(shù)據(jù)妥箕,是否有其他的分表方式?
2.1大學里面學校上課時更舞,也存在每個人選的課不一樣畦幢,一個老師上課同時面對多個不同的班級(子班)的情況,但一個比較大的區(qū)別在于缆蝉,大學的課都是一個學期一個學期宇葱。如果按學季分表是否能更有效的支持后續(xù)的業(yè)務?未進行驗證刊头,且單個學季的數(shù)據(jù)量會不會也很大黍瞧,此點存疑。
2.2當時的課程類型分為小原杂、初印颤、高,及特定的課程類型(講座/免費課)等穿肄,如果按具體類型分表是否能更有效的支持后續(xù)的業(yè)務年局?未進行驗證,此點存疑咸产。
2.3針對不同的業(yè)務入?yún)⑹阜瘢床煌姆绞椒直恚∠悩嬎饕砟砸纾缋蠋焷聿橹苯影磘eacher_id分表僵朗,學生來查直接按uid分表?未進行驗證屑彻,此點存疑验庙。

二.按月分表

2.1經(jīng)歷概述

事項 具體方式/情況 解釋備注
業(yè)務背景 游戲互娛業(yè)務,用戶背包道具表/用戶道具消耗表 按用戶和道具記錄的流水酱酬,同一道具多次獲得是多條數(shù)據(jù)壶谒,使用/兌換也只改用的那條數(shù)據(jù)的狀態(tài)
分表前數(shù)據(jù)量 約5000萬
分表策略 1.根據(jù)數(shù)據(jù)產(chǎn)生時間,按月分表

2.根據(jù)用戶id,道具id膳沽,單獨異步維護一份統(tǒng)計表,來支持查總價值,總數(shù)等
1.流水表主要是按時間段或者用戶最近的獲得記錄等信息時需要用到

2.統(tǒng)計信息避免直接在流水表中做統(tǒng)計挑社,消息異步維護統(tǒng)計表陨界,直接查統(tǒng)計表就可以了

3.歷史數(shù)據(jù)實際用戶側很少會查詢,一定程度上按月分表有利于把存量不用的數(shù)據(jù)隔離開痛阻,查詢較多的近幾個月的數(shù)據(jù)相對獨立
分表數(shù) 每月一張,表名為XXXX_YYYYMM
分表框架 自己邏輯寫的查詢方法和路由方法
潛在問題 用戶道具記錄持續(xù)往前翻的時候有可能從當前的表查到了上一頁的表 數(shù)據(jù)拼接時容易出問題菌瘪,但并非完全無法解決
數(shù)據(jù)遷移 提前建好歷史到今年年底的所有分表

上線后定時任務按id從1到最新的逐步處理數(shù)據(jù),每處理500條更新一下已處理的游標阱当,每次都是從已處理游標后拿500條數(shù)據(jù)寫到分表中
定時任務的入?yún)⒔刂筰d作為參數(shù)俏扩,這樣通過更改游標和定時任務截止的id,未來也可以隨時通過該任務補償數(shù)據(jù)
上線方式 1.新的分表是獨立的策略去讀寫弊添,原項目操作老表的地方录淡,增加讀寫開關來切換操作的是老表還是新表

2. 剛上線時業(yè)務開關切換雙寫,讀老

3.將新表開始寫的id作為截止id的入?yún)⒂桶樱_始執(zhí)行同步數(shù)據(jù)的任務

4.等定時任務完全同步一致后嫉戚,切換開關讀新

5.持續(xù)觀察穩(wěn)定后,下次上線時下線開關邏輯代碼
分表結果 1.分表前部分查詢出現(xiàn)慢查澈圈;分表后同樣的業(yè)務功能查詢性能較好

2. 未停服彬檀,用戶基本無感
參與角色/程度 由于該項目是個老項目,需要優(yōu)化的大表多達十來個瞬女,討論時多人一起討論窍帝,最終幾個人分別拿了不同的表去分析各自的落地方案,具體到該表的分表基本是自己完整設計和落地 有了此前的分表經(jīng)歷后诽偷,對方案的部分細節(jié)設計時更為篤定盯桦,偶爾遇到拿不準的也會提出來和同事討論,最終基本由自己完整落地渤刃,也是一個很珍貴的精力
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
禁止轉載拥峦,如需轉載請通過簡信或評論聯(lián)系作者。
  • 序言:七十年代末卖子,一起剝皮案震驚了整個濱河市略号,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌洋闽,老刑警劉巖玄柠,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異诫舅,居然都是意外死亡羽利,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門刊懈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來这弧,“玉大人娃闲,你說我怎么就攤上這事∝依耍” “怎么了皇帮?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蛋辈。 經(jīng)常有香客問我属拾,道長,這世上最難降的妖魔是什么冷溶? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任渐白,我火速辦了婚禮,結果婚禮上逞频,老公的妹妹穿的比我還像新娘纯衍。我一直安慰自己,他們只是感情好虏劲,可當我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布托酸。 她就那樣靜靜地躺著,像睡著了一般柒巫。 火紅的嫁衣襯著肌膚如雪励堡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天堡掏,我揣著相機與錄音应结,去河邊找鬼。 笑死泉唁,一個胖子當著我的面吹牛鹅龄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播亭畜,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼扮休,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了拴鸵?” 一聲冷哼從身側響起玷坠,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎劲藐,沒想到半個月后八堡,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡聘芜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年兄渺,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片汰现。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡挂谍,死狀恐怖叔壤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情凳兵,我是刑警寧澤百新,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布企软,位于F島的核電站庐扫,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏仗哨。R本人自食惡果不足惜形庭,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望厌漂。 院中可真熱鬧萨醒,春花似錦、人聲如沸苇倡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽旨椒。三九已至晓褪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間综慎,已是汗流浹背涣仿。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留示惊,地道東北人好港。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像米罚,于是被迫代替她去往敵國和親钧汹。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容