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