線上高并發(fā)應(yīng)用重構(gòu)(寫)填坑經(jīng)驗分享(一)

今年在公司重構(gòu)(寫)了一個老項目浪讳,踩了無數(shù)的坑。

中間好幾次遇到問題淹遵,甚至感覺項目可能要失敗了,好在最后終于成功上線了济炎。

雖然被坑的不要不要的辐真,但也從中領(lǐng)悟到了不少東西,在這里記錄一下,順便分享給大家樂呵樂呵倘感。

先簡單介紹下項目,一個面向C端用戶的服務(wù)淤年,主要提供包括動態(tài)蜡豹、評論、圈子弄诲、好友、關(guān)注齐遵、Feed等常見的社區(qū)功能,另外還有其他一些個性化的功能拓哟。

日活比較高伶授,整個服務(wù)QPS上萬。高頻業(yè)務(wù)违诗,單個接口QPS上千景图。單項業(yè)務(wù)數(shù)據(jù)量過億,比如評論挚币。

圖1.接口qps監(jiān)控圖

在上述高并發(fā)妆毕、海量數(shù)據(jù)的情況下,整個系統(tǒng)設(shè)計時需要注意的坑笛粘,和我總結(jié)的一些經(jīng)驗:

數(shù)據(jù)庫層面

MySQL分庫分表

因為是重寫整個項目薪前,包括重新設(shè)計底層數(shù)據(jù)庫,必然要考慮到分庫分表示括。

最初在網(wǎng)上參考了一些分庫分表的原則,實際操作中鳍侣,發(fā)現(xiàn)大部分資料都有些縹緲吼拥。

如果是簡單的應(yīng)用怎么分表,甚至不分都可以惑折。所以這些原則你也不能說它是錯的,但在你最需要參考的時候唬复,這些原則往往不夠深入。

分享下我個人總結(jié)的一些經(jīng)驗:

先說分庫, 分庫的主要目標(biāo)棘捣,應(yīng)該是緩解主庫(Master)的壓力休建。

絕大部分服務(wù)都是讀多寫少,在讀寫分離茵烈,1主1備N從的情況下砌些,即便為了保證一致性,部分讀請求路由到主庫存璃,主庫壓力依舊很低纵东。

通過監(jiān)控服務(wù)的寫請求量和數(shù)據(jù)庫服務(wù)器的CPU壓力等性能指標(biāo),只要主庫壓力不大偎球,就沒必要分庫。讀庫如果壓力大袍冷,直接加從庫實例即可猫牡。

一種極端的情況,就是分表數(shù)量過多了,一個庫里表數(shù)量遞增褂痰,成萬上億了,那還是分庫的好归薛。

還有一點,從運維的角度考慮习贫,單庫冷備千元,數(shù)據(jù)不應(yīng)該超過500GB。如果單庫數(shù)據(jù)量達(dá)到1個TB幸海,運維也不好備份,為了正常備份也要分庫袜硫。

圖2.數(shù)據(jù)庫監(jiān)控圖(圖中藍(lán)色線條代表主庫挡篓,基本上是趴著不動躺平的)

再說分表, 在請求量不大 或 數(shù)據(jù)量不大的情況下官研,分不分表都無所謂。

考慮mysql的性能阀参、樹的深度等,可以簡單的認(rèn)為單表500W左右即可杏瞻。

但實際中往往需要結(jié)合具體的業(yè)務(wù)設(shè)計和查詢場景衙荐。

比如,1張幾千萬數(shù)據(jù)量的訂單表砌函,如果業(yè)務(wù)上溜族,只需要根據(jù)主鍵或唯一索引,每次查詢一條記錄仍劈,那么不分表也是完全可行的寡壮。

但有時出于運維需要讹弯,分表會更方便一些这溅,比如研發(fā)人員可能會想手寫一些SQL上去進(jìn)行一些范圍查詢,為排查問題提供一些方便臭胜。(這里說的方便是指相對單表幾千萬对竣,如果查詢字段沒有索引,范圍查詢基本不可用否纬。當(dāng)然從操作步驟上看临燃,肯定比查1個表繁瑣了)

特別需要注意的是,如果一項業(yè)務(wù)數(shù)據(jù)需要高頻的用到 count語句查詢總數(shù) 或 order by進(jìn)行排序膜廊,我建議分的表越多越好,管他3721先分1000張表再說蹬跃。

多分表的好處就是铆铆,只要表中的數(shù)據(jù)量足夠少,即便你索引設(shè)計的不好翁都,甚至查詢完全不走索引谅猾,也不容易產(chǎn)生慢查詢。哈哈哈坐搔!

小結(jié):這次重構(gòu)就被老系統(tǒng)的1000張表給坑了敬矩,因為每張表只有幾萬條數(shù)據(jù),我覺得太浪費了, 想當(dāng)然的縮到了20張表占锯。

但又沒有很好的去分析查詢場景缩筛,設(shè)計索引。導(dǎo)致上線時瞎抛,只放了1%的量,就崩了胎撤,看監(jiān)控全部都是慢查詢断凶。

當(dāng)然,最終我是通過優(yōu)化索引來解決慢查詢肿男,而不是加分表數(shù)量却嗡。但在有些情況下,這也是一種思路如庭。

MySQL索引撼港、字段設(shè)計

之前自己設(shè)計表,總喜歡加些固定字段哟楷,比如create_time, create_user, is_delete等否灾,因為運維方便。

重構(gòu)了這個系統(tǒng)之后發(fā)現(xiàn)墨技,在高并發(fā)海量數(shù)據(jù)的情況下扣汪,性能是首要問題,有時候多加這些字段反而成了負(fù)擔(dān)崭别。(當(dāng)然,大部分情況下舞痰,create_time還是必要的)

字段能少則少,名字能短則短玷禽,類型能用tinyint就不要用int呀打。

索引這塊查詢低頻少量數(shù)據(jù)無所謂,高頻海量數(shù)據(jù)務(wù)必所有查詢走索引撩银。
再看一些實際例子,
1. is_delete 字段(邏輯刪除)
假設(shè)以評論為例豺憔,單表500w,單條動態(tài)下平均上萬條評論咪啡。
業(yè)務(wù)場景中要查詢動態(tài)下的所有評論暮屡,where 子句要加上條件 is_delete = 0。
如果查詢出符合條件的結(jié)果集准夷,有幾萬甚至十幾萬條莺掠,不把 is_delete 字段加到聯(lián)合索引中,這必將是一條慢查詢楔绞,再加上高并發(fā)唇兑,只要幾百的qps,很容易把服務(wù)打崩蔫耽。
每個查詢加上這么一個條件又有點畫蛇添足留夜,除非運維需要图甜,基本上不會有業(yè)務(wù)要查詢 is_delete = 1的情況鳖眼。
索性直接物理刪除具帮,再加個歸檔表低斋,要找回時,去歸檔表里找掘猿。
這樣就不用在每個聯(lián)合索引里多加一個字段了唇跨。
2. tinyint 和 int
tinyint 主要用于一些狀態(tài)標(biāo)志位,比如 審核狀態(tài):0-未審核 1-審核通過 2-審核未通過改橘。
使用tinyint 一是節(jié)約空間玉控,二是方便識別,一看就知道是標(biāo)志位碌识。
另外這種標(biāo)志位經(jīng)常出現(xiàn)在查詢條件中虱而,但又不會單獨作為查詢條件,因此建立索引時魁瞪,必然是在聯(lián)合索引中出現(xiàn)惠呼。
而聯(lián)合索引是有長度限制的,雖然大部分時候都不會遇到趟畏,但還是值得注意滩租。
有的人標(biāo)志位喜歡用byte利朵,但在代碼里要轉(zhuǎn)型就很蛋疼了猎莲。
3.聯(lián)合索引的設(shè)計
就一個原則:查詢條件里有的,都加進(jìn)去樟遣。
除了要把 where 子句中的條件字段加進(jìn)去外身笤,在有order by 的情況下,還要把 order by 的字段加到最后液荸。
比如:查詢動態(tài)id是123,狀態(tài)是審核通過且上線的20條評論娇钱,按時間倒序排列伤柄。
select * from comment where news_id = 123 and audit_status = 1 and online_status = 1 order by ctime desc limit 20
那我們應(yīng)該建立聯(lián)合索引 (news_id, audit_status, online_status, ctime)
注意:在網(wǎng)上參考資料時,很多都說索引的建立原則文搂,字段的區(qū)分度要高适刀。
個人感覺這個原則并沒什么道理,至少在建立聯(lián)合索引時不適用煤蹭。
在建立單一索引時蔗彤,也沒有想到適用的具體場景。
比如有單表5千萬條身份信息疯兼,其中20條gender=1然遏,5千萬條gender=0。
如果你就是要查詢gender=1的列表吧彪,如果不在gender列建立索引,即便只有20條數(shù)據(jù)姨裸,也必然是個慢查詢秧倾。 小結(jié):索引的建立,必須針對具體的查詢語句傀缩。結(jié)合實際查詢場景那先,去考慮如何創(chuàng)建索引。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末赡艰,一起剝皮案震驚了整個濱河市售淡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖揖闸,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件揍堕,死亡現(xiàn)場離奇詭異,居然都是意外死亡汤纸,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門楞慈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人囊蓝,你說我怎么就攤上這事∫槎瑁” “怎么了?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵乡恕,是天一觀的道長。 經(jīng)常有香客問我傲宜,道長,這世上最難降的妖魔是什么函卒? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任辆憔,我火速辦了婚禮,結(jié)果婚禮上报嵌,老公的妹妹穿的比我還像新娘虱咧。我一直安慰自己锚国,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布血筑。 她就那樣靜靜地躺著,像睡著了一般车伞。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上另玖,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機(jī)與錄音日矫,去河邊找鬼。 笑死哪轿,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的窃诉。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼珊膜,長吁一口氣:“原來是場噩夢啊……” “哼宣脉!你這毒婦竟也來了车柠?” 一聲冷哼從身側(cè)響起塑猖,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎塑陵,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蜡励,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年兼都,在試婚紗的時候發(fā)現(xiàn)自己被綠了稽寒。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片俯抖。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡瓦胎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出搔啊,到底是詐尸還是另有隱情,我是刑警寧澤负芋,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站莽龟,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏毯盈。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一搂赋、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧基公,春花似錦、人聲如沸轰豆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽掌挚。三九已至菩咨,卻和暖如春吠式,著一層夾襖步出監(jiān)牢的瞬間抽米,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工是目, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人懊纳。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓亡容,卻偏偏與公主長得像嗤疯,于是被迫代替她去往敵國和親闺兢。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,037評論 2 355

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