|
《大數(shù)據(jù)量下,58同城mysql實(shí)踐》 WOT(World Of Tech)2015,互聯(lián)網(wǎng)運(yùn)維與開發(fā)者大會(huì)將在北京舉行,會(huì)上58同城將分享《大數(shù)據(jù)量下,58同城mysql實(shí)戰(zhàn)》的主題,干貨分享?yè)屜瓤础?/span> 零、分享提綱 1)基本概念 2)常見問(wèn)題及解決思路 3)拆庫(kù)實(shí)戰(zhàn) 4)拆庫(kù)后業(yè)務(wù)實(shí)戰(zhàn) 5)總結(jié) 一、基本概念 大數(shù)據(jù)量下,搞mysql,以下概念需要先達(dá)成一致 1)單庫(kù),不多說(shuō)了,就是一個(gè)庫(kù)
二、大數(shù)據(jù)量下,mysql常見問(wèn)題及解決思路 1)常見問(wèn)題 如何保證可用性? 各色各異的讀寫比,怎么辦? 如何做無(wú)縫倒庫(kù),加字段,擴(kuò)容? 數(shù)據(jù)量大,怎么解決?
2.1)可用性解決思路:復(fù)制 讀庫(kù)可用性 從庫(kù)復(fù)制多個(gè),例如:1主2從 從庫(kù)掛了讀主庫(kù),例如:1主1從 寫庫(kù)可用性 雙主模式 “雙主”當(dāng)“主從”用 2.2)讀寫比解決思路-針對(duì)特性做設(shè)計(jì) 讀多些少場(chǎng)景:提升讀性能,3種常見方案: a)新建索引提高讀性能,什么小技巧? b)讀寫分離,增加從庫(kù)擴(kuò)展讀性能 c)增加緩存來(lái)擴(kuò)展讀性能 a)b)c)方案存在什么問(wèn)題? 如何解決這些問(wèn)題? 讀寫相近場(chǎng)景:不要使用緩存,考慮水平切分 寫多讀少場(chǎng)景:不要使用緩存,考慮水平切分 2.3)無(wú)縫倒庫(kù)[擴(kuò)容,增加字段,數(shù)據(jù)遷移] 追日志方案 a)記錄寫日志
c)倒庫(kù)完畢 d)追日志 e)追日志完畢+數(shù)據(jù)校驗(yàn) f)切庫(kù) 雙寫方案
b)倒庫(kù) c)倒庫(kù)完畢+數(shù)據(jù)校驗(yàn) d)切庫(kù) 2.4)數(shù)據(jù)量大解決思路:拆庫(kù) 三、58同城數(shù)據(jù)庫(kù)拆庫(kù)實(shí)戰(zhàn) 四類場(chǎng)景覆蓋99%拆庫(kù)業(yè)務(wù) a)“單key”場(chǎng)景,用戶庫(kù)如何拆分: user(uid, XXOO) b)“1對(duì)多”場(chǎng)景,帖子庫(kù)如何拆分: tiezi(tid, uid, XXOO) c)“多對(duì)多”場(chǎng)景,好友庫(kù)如何拆分: friend(uid, friend_uid, XXOO) d)“多key”場(chǎng)景,訂單庫(kù)如何拆分:order(oid, buyer_id, seller_id, XXOO) 1)用戶庫(kù)如何拆分 用戶庫(kù),10億數(shù)據(jù)量 user(uid, uname, passwd, age, sex, create_time); 業(yè)務(wù)需求如下 a)1%登錄請(qǐng)求 => where uname=XXX and passwd=XXX b)99%查詢請(qǐng)求 => where uid=XXX 結(jié)論:“單key”場(chǎng)景使用“單key”拆庫(kù) 2)帖子庫(kù)如何拆分 帖子庫(kù),15億數(shù)據(jù)量 tiezi(tid, uid, title, content, time); 業(yè)務(wù)需求如下 a)查詢帖子詳情(90%請(qǐng)求) SELECT * FROM tiezi WHERE tid=$tid b)查詢用戶所有發(fā)帖(10%請(qǐng)求) SELECT * FROM tiezi WHERE uid=$uid 結(jié)論:“1對(duì)多”場(chǎng)景使用“1”分庫(kù),例如帖子庫(kù)1個(gè)uid對(duì)應(yīng)多個(gè)tid,則使用uid分庫(kù),tid生成時(shí)加入分庫(kù)標(biāo)記 3)好友庫(kù)如何拆分 好友庫(kù),1億數(shù)據(jù)量 friend(uid, friend_uid, nick, memo, XXOO); 業(yè)務(wù)需求如下 a)查詢我的好友(50%請(qǐng)求) => 用于界面展示 SELECT friend_uid FROM friend WHERE uid=$my_uid b)查詢加我為好友的用戶(50%請(qǐng)求) => 用戶反向通知 SELECT uid FROM friend WHERE friend_uid=$my_uid 結(jié)論:“多對(duì)多”場(chǎng)景,使用數(shù)據(jù)冗余方案,多份數(shù)據(jù)使用多種分庫(kù)手段 4)訂單庫(kù)如何拆分 訂單庫(kù),10億數(shù)據(jù)量 order(oid, buyer_id, seller_id, order_info, XXOO); 業(yè)務(wù)需求如下 a)查詢訂單信息(80%請(qǐng)求) SELECT * FROM order WHERE oid=$oid b)查詢我買的東東(19%請(qǐng)求) SELECT * FROM order WHERE buyer_id=$my_uid c)查詢我賣出的東東(1%請(qǐng)求) SELECT * FROM order WHERE seller_id=$my_uid 結(jié)論:“多key”場(chǎng)景一般有兩種方案 a)方案一,使用2和3綜合的方案 b)方案二,1%的請(qǐng)求采用多庫(kù)查詢 四、分庫(kù)后業(yè)務(wù)實(shí)戰(zhàn) 分庫(kù)后出現(xiàn)的問(wèn)題:?jiǎn)螏?kù)時(shí)mysql的SQL功能不再支持了 1)海量數(shù)據(jù)下,mysql的SQL怎么玩 不會(huì)這么玩 a)各種聯(lián)合查詢 b)子查詢 c)觸發(fā)器 d)用戶自定義函數(shù) e)“事務(wù)”都用的很少 原因:對(duì)數(shù)據(jù)庫(kù)性能影響極大 2)分庫(kù)后,IN查詢?cè)趺赐?/strong> 用戶庫(kù)如何進(jìn)行uid的IN查詢 user(uid, uname, passwd, age, sex, photo, create_time, ...); Partition key:uid 查詢需求:IN查詢:WHERE uid IN(1,2,3,4,5,6)
方案一:直接分發(fā) 方案二:拼裝成不同SQL,定位不同的庫(kù) 3)分庫(kù)后,非Partition key的查詢?cè)趺赐?/strong> 方案一:業(yè)務(wù)方不關(guān)心數(shù)據(jù)來(lái)自哪個(gè)庫(kù),可以只定位一個(gè)庫(kù) 例如:有頭像的用戶查詢 方案二:結(jié)果集只有一條數(shù)據(jù),業(yè)務(wù)層做分發(fā),只有一條記錄返回就返回 例如:用戶登錄時(shí),使用userName和passwd的查詢 4)分庫(kù)后,夸庫(kù)分頁(yè)怎么玩? 問(wèn)題的提出與抽象:ORDER BY xxx OFFSET xxx LIMIT xxx a)按時(shí)間排序 b)每頁(yè)100條記錄 c)取第100頁(yè)的記錄 單機(jī)方案 ORDER BY time OFFSET 10000 LIMIT 100 分庫(kù)后的難題:如何確認(rèn)全局偏移量 分庫(kù)后傳統(tǒng)解決方案,查詢改寫+內(nèi)存排序 a)ORDER BY time OFFSET 0 LIMIT 10000+100 b)對(duì)20200條記錄進(jìn)行排序 c)返回第10000至10100條記錄 優(yōu)化方案一:增加輔助id,以減少查詢量 a)技術(shù)上,引入特殊id,作為查詢條件(或者帶入上一頁(yè)的排序條件) b)業(yè)務(wù)上,盡量禁止跨頁(yè)查詢 單庫(kù)情況
b)得到第一頁(yè)的max(id)=123(一般是最后一條記錄) c)第二頁(yè),帶上id>123查詢:WHERE id>123 LIMIT 100 多庫(kù)情況
a)將WHERE id>xxx LIMIT 100分發(fā) b)將300條結(jié)果排序 c)返回前100條 優(yōu)點(diǎn):避免了全局排序,只對(duì)小量記錄進(jìn)行排序 優(yōu)化方案二:模糊查詢 a)業(yè)務(wù)上:禁止查詢XX頁(yè)之后的數(shù)據(jù) b)業(yè)務(wù)上:允許模糊返回 => 第100頁(yè)數(shù)據(jù)的精確性真這么重要么? 優(yōu)化方案三:終極方案,查詢改寫與兩段查詢 方案一和方案二在業(yè)務(wù)上都有所折衷,前者不允許跨頁(yè)查詢,后者數(shù)據(jù)精度有損失,解決夸庫(kù)分頁(yè)問(wèn)題的終極方案是,將order by + offset + limit進(jìn)行查詢改寫,分兩段查詢。 由于wot2015大會(huì)時(shí)間優(yōu)先,這個(gè)方案待到dtcc2015數(shù)據(jù)庫(kù)大會(huì)上,58同城的架構(gòu)師再與大家細(xì)講 五、總結(jié) 《概念》 單庫(kù)、分片、復(fù)制、分組 《常見問(wèn)題及解決思路》 1)可用性,解決思路是冗余(復(fù)制) 2)讀寫比 2.1)讀多些少:用從庫(kù),緩存,索引來(lái)提高讀性能 2.2)業(yè)務(wù)層控制強(qiáng)制讀主來(lái)解決從庫(kù)不一致問(wèn)題 2.3)雙淘汰來(lái)解決緩存不一致問(wèn)題 2.4)讀寫相近,寫多讀少:不要使用緩存,該怎么整怎么整 3)無(wú)縫導(dǎo)庫(kù) 3.1)寫日志追數(shù)據(jù) 3.2)雙寫 4)數(shù)據(jù)量大,解決思路是分片(拆庫(kù)) 《四大類拆庫(kù)思路》 1)用戶庫(kù),“單key”場(chǎng)景使用“單key”拆庫(kù) 2)帖子庫(kù),“1對(duì)多”場(chǎng)景使用“1”分庫(kù),例如帖子庫(kù)1個(gè)uid對(duì)應(yīng)多個(gè)tid,則使用uid分庫(kù),tid生成時(shí)加入分庫(kù)標(biāo)記 3)好友庫(kù),“多對(duì)多”場(chǎng)景,使用數(shù)據(jù)冗余方案,多份數(shù)據(jù)使用多種分庫(kù)手段 4)訂單庫(kù),“多key”場(chǎng)景一般有兩種方案 4.1)方案一,使用2和3綜合的方案 4.2)方案二,1%的請(qǐng)求采用多庫(kù)查詢 《拆庫(kù)后業(yè)務(wù)實(shí)戰(zhàn)》 1)不這么玩:聯(lián)合查詢、子查詢、觸發(fā)器、用戶自定義函數(shù)、夸庫(kù)事務(wù) 2)IN查詢?cè)趺赐?/p> 2.1)分發(fā)MR 2.2)拼裝成不同SQL語(yǔ)句 3)非partition key查詢?cè)趺赐?/p> 3.1)定位一個(gè)庫(kù) 3.2)分發(fā)MR 4)夸庫(kù)分頁(yè)怎么玩 4.1)修改sql語(yǔ)句,服務(wù)內(nèi)排序 4.2)引入特殊id,減少返回?cái)?shù)量 4.3)業(yè)務(wù)優(yōu)化,禁止跨頁(yè)查詢,允許模糊查詢 4.4)終極方案,dtcc2015數(shù)據(jù)庫(kù)大會(huì)揭曉 【完】 回復(fù)【mongo】,閱讀《一分鐘了解mongoDB》 回復(fù)【leveldb】,閱讀《Google-levelDB簡(jiǎn)介》 回復(fù)【join】,閱讀《兩幅圖秒懂sql中的join》 回復(fù)【mysql】,閱讀《mysql數(shù)據(jù)庫(kù)中間件》 回復(fù)【趕集】,閱讀《趕集mysql軍規(guī)》 回復(fù)【同城】,閱讀《58同城mysql實(shí)戰(zhàn)》(火) 小游戲: 回大于10的整數(shù),返回隨機(jī)好文(試試看喲,猜猜怎么實(shí)現(xiàn)的?) 我是做數(shù)據(jù)庫(kù)的,各位兄弟幫忙轉(zhuǎn)發(fā)一下哈。 |
|
|