單KEY業(yè)務(wù)岖常,數(shù)據(jù)庫水平切分架構(gòu)實(shí)踐

本文將以“用戶中心”為例,介紹“單KEY”類業(yè)務(wù)葫督,隨著數(shù)據(jù)量的逐步增大竭鞍,數(shù)據(jù)庫性能顯著降低,數(shù)據(jù)庫水平切分相關(guān)的架構(gòu)實(shí)踐:

如何來實(shí)施水平切分

水平切分后常見的問題

典型問題的優(yōu)化思路及實(shí)踐


一橄镜、用戶中心

用戶中心是一個(gè)非常常見的業(yè)務(wù)偎快,主要提供用戶注冊、登錄洽胶、信息查詢與修改的服務(wù)晒夹,其核心元數(shù)據(jù)為:

User(uid, login_name, passwd, sex, age, nickname, …)

其中:

uid為用戶ID,主鍵

login_name, passwd, sex, age, nickname, …等用戶屬性

數(shù)據(jù)庫設(shè)計(jì)上,一般來說在業(yè)務(wù)初期丐怯,單庫單表就能夠搞定這個(gè)需求喷好,典型的架構(gòu)設(shè)計(jì)為:

user-center:用戶中心服務(wù),對調(diào)用者提供友好的RPC接口

user-db:對用戶進(jìn)行數(shù)據(jù)存儲(chǔ)


二读跷、用戶中心水平切分方法

當(dāng)數(shù)據(jù)量越來越大時(shí)梗搅,需要對數(shù)據(jù)庫進(jìn)行水平切分,常見的水平切分算法有“范圍法”和“哈希法”效览。


范圍法无切,以用戶中心的業(yè)務(wù)主鍵uid為劃分依據(jù),將數(shù)據(jù)水平切分到兩個(gè)數(shù)據(jù)庫實(shí)例上去:

user-db1:存儲(chǔ)0到1千萬的uid數(shù)據(jù)

user-db2:存儲(chǔ)1到2千萬的uid數(shù)據(jù)


范圍法的優(yōu)點(diǎn)是:

切分策略簡單钦铺,根據(jù)uid开财,按照范圍禀酱,user- center很快能夠定位到數(shù)據(jù)在哪個(gè)庫上

擴(kuò)容簡單酸茴,如果容量不夠,只要增加user-db3即可

范圍法的不足是:

uid必須要滿足遞增的特性

數(shù)據(jù)量不均沼本,新增的user-db3噩峦,在初期的數(shù)據(jù)會(huì)比較少

請求量不均,一般來說抽兆,新注冊的用戶活躍度會(huì)比較高识补,故user-db2往往會(huì)比user-db1負(fù)載要高,導(dǎo)致服務(wù)器利用率不平衡


哈希法辫红,也是以用戶中心的業(yè)務(wù)主鍵uid為劃分依據(jù)凭涂,將數(shù)據(jù)水平切分到兩個(gè)數(shù)據(jù)庫實(shí)例上去:

user-db1:存儲(chǔ)uid取模得1的uid數(shù)據(jù)

user-db2:存儲(chǔ)uid取模得0的uid數(shù)據(jù)


哈希法的優(yōu)點(diǎn)是:

切分策略簡單,根據(jù)uid贴妻,按照hash切油,user-center很快能夠定位到數(shù)據(jù)在哪個(gè)庫上

數(shù)據(jù)量均衡,只要uid是均勻的名惩,數(shù)據(jù)在各個(gè)庫上的分布一定是均衡的

請求量均衡澎胡,只要uid是均勻的,負(fù)載在各個(gè)庫上的分布一定是均衡的

哈希法的不足是:

擴(kuò)容麻煩娩鹉,如果容量不夠攻谁,要增加一個(gè)庫,重新hash可能會(huì)導(dǎo)致數(shù)據(jù)遷移弯予,如何平滑的進(jìn)行數(shù)據(jù)遷移戚宦,是一個(gè)需要解決的問題


三、用戶中心水平切分后帶來的問題

使用uid來進(jìn)行水平切分之后锈嫩,整個(gè)用戶中心的業(yè)務(wù)訪問會(huì)遇到什么問題呢阁苞?


對于uid屬性上的查詢可以直接路由到庫困檩,假設(shè)訪問uid=124的數(shù)據(jù)祠挫,取模后能夠直接定位db-user1:


對于非uid屬性上的查詢那槽,例如login_name屬性上的查詢,就悲劇了:

假設(shè)訪問login_name=shenjian的數(shù)據(jù)等舔,由于不知道數(shù)據(jù)落在哪個(gè)庫上骚灸,往往需要遍歷所有庫,當(dāng)分庫數(shù)量多起來慌植,性能會(huì)顯著降低甚牲。


如何解決分庫后,非uid屬性上的查詢問題蝶柿,是后文要重點(diǎn)討論的內(nèi)容丈钙。


四、用戶中心非uid屬性查詢需求分析

任何脫離業(yè)務(wù)的架構(gòu)設(shè)計(jì)都是耍流氓交汤,在進(jìn)行架構(gòu)討論之前雏赦,先來對業(yè)務(wù)進(jìn)行簡要分析,看非uid屬性上有哪些查詢需求芙扎。


根據(jù)樓主這些年的架構(gòu)經(jīng)驗(yàn)星岗,用戶中心非uid屬性上經(jīng)常有兩類業(yè)務(wù)需求:

(1)用戶側(cè),前臺(tái)訪問戒洼,最典型的有兩類需求

用戶登錄:通過login_name/phone/email查詢用戶的實(shí)體俏橘,1%請求屬于這種類型

用戶信息查詢:登錄之后,通過uid來查詢用戶的實(shí)例圈浇,99%請求屬這種類型

用戶側(cè)的查詢基本上是單條記錄的查詢寥掐,訪問量較大,服務(wù)需要高可用磷蜀,并且對一致性的要求較高召耘。


(2)運(yùn)營側(cè),后臺(tái)訪問蠕搜,根據(jù)產(chǎn)品怎茫、運(yùn)營需求,訪問模式各異妓灌,按照年齡轨蛤、性別、頭像虫埂、登陸時(shí)間祥山、注冊時(shí)間來進(jìn)行查詢。

運(yùn)營側(cè)的查詢基本上是批量分頁的查詢掉伏,由于是內(nèi)部系統(tǒng)缝呕,訪問量很低澳窑,對可用性的要求不高,對一致性的要求也沒這么嚴(yán)格供常。


這兩類不同的業(yè)務(wù)需求摊聋,應(yīng)該使用什么樣的架構(gòu)方案來解決呢?


五栈暇、用戶中心水平切分架構(gòu)思路

用戶中心在數(shù)據(jù)量較大的情況下麻裁,使用uid進(jìn)行水平切分,對于非uid屬性上的查詢需求源祈,架構(gòu)設(shè)計(jì)的核心思路為:

針對用戶側(cè)煎源,應(yīng)該采用“建立非uid屬性到uid的映射關(guān)系”的架構(gòu)方案

針對運(yùn)營側(cè),應(yīng)該采用“前臺(tái)與后臺(tái)分離”的架構(gòu)方案


六香缺、用戶中心-用戶側(cè)最佳實(shí)踐

【索引表法】

思路:uid能直接定位到庫手销,login_name不能直接定位到庫,如果通過login_name能查詢到uid图张,問題解決

解決方案

建立一個(gè)索引表記錄login_name->uid的映射關(guān)系

用login_name來訪問時(shí)锋拖,先通過索引表查詢到uid,再定位相應(yīng)的庫

索引表屬性較少埂淮,可以容納非常多數(shù)據(jù)姑隅,一般不需要分庫

如果數(shù)據(jù)量過大,可以通過login_name來分庫

潛在不足:多一次數(shù)據(jù)庫查詢倔撞,性能下降一倍


【緩存映射法】

思路:訪問索引表性能較低讲仰,把映射關(guān)系放在緩存里性能更佳

解決方案

login_name查詢先到cache中查詢uid,再根據(jù)uid定位數(shù)據(jù)庫

假設(shè)cache miss痪蝇,采用掃全庫法獲取login_name對應(yīng)的uid鄙陡,放入cache

login_name到uid的映射關(guān)系不會(huì)變化,映射關(guān)系一旦放入緩存躏啰,不會(huì)更改趁矾,無需淘汰,緩存命中率超高

如果數(shù)據(jù)量過大给僵,可以通過login_name進(jìn)行cache水平切分

潛在不足:多一次cache查詢


login_name生成uid

思路:不進(jìn)行遠(yuǎn)程查詢毫捣,由login_name直接得到uid

解決方案

在用戶注冊時(shí),設(shè)計(jì)函數(shù)login_name生成uid帝际,uid=f(login_name)蔓同,按uid分庫插入數(shù)據(jù)

用login_name來訪問時(shí),先通過函數(shù)計(jì)算出uid蹲诀,即uid=f(login_name)再來一遍斑粱,由uid路由到對應(yīng)庫

潛在不足:該函數(shù)設(shè)計(jì)需要非常講究技巧,有uid生成沖突風(fēng)險(xiǎn)


login_name基因融入uid

思路:不能用login_name生成uid脯爪,可以從login_name抽取“基因”则北,融入uid中

假設(shè)分8庫矿微,采用uid%8路由,潛臺(tái)詞是尚揣,uid的最后3個(gè)bit決定這條數(shù)據(jù)落在哪個(gè)庫上涌矢,這3個(gè)bit就是所謂的“基因”。


解決方案

在用戶注冊時(shí)惑艇,設(shè)計(jì)函數(shù)login_name生成3bit基因蒿辙,login_name_gene=f(login_name),如上圖粉色部分

同時(shí)滨巴,生成61bit的全局唯一id,作為用戶的標(biāo)識俺叭,如上圖綠色部分

接著把3bit的login_name_gene也作為uid的一部分恭取,如上圖屎黃色部分

生成64bit的uid,由id和login_name_gene拼裝而成熄守,并按照uid分庫插入數(shù)據(jù)

用login_name來訪問時(shí)蜈垮,先通過函數(shù)由login_name再次復(fù)原3bit基因,login_name_gene=f(login_name)裕照,通過login_name_gene%8直接定位到庫


七攒发、用戶中心-運(yùn)營側(cè)最佳實(shí)踐

前臺(tái)用戶側(cè),業(yè)務(wù)需求基本都是單行記錄的訪問晋南,只要建立非uid屬性?login_name / phone / email到uid的映射關(guān)系惠猿,就能解決問題。

后臺(tái)運(yùn)營側(cè)负间,業(yè)務(wù)需求各異偶妖,基本是批量分頁的訪問,這類訪問計(jì)算量較大政溃,返回?cái)?shù)據(jù)量較大趾访,比較消耗數(shù)據(jù)庫性能。


如果此時(shí)前臺(tái)業(yè)務(wù)和后臺(tái)業(yè)務(wù)公用一批服務(wù)和一個(gè)數(shù)據(jù)庫董虱,有可能導(dǎo)致扼鞋,由于后臺(tái)的“少數(shù)幾個(gè)請求”的“批量查詢”的“低效”訪問,導(dǎo)致數(shù)據(jù)庫的cpu偶爾瞬時(shí)100%愤诱,影響前臺(tái)正常用戶的訪問(例如云头,登錄超時(shí))。

而且转锈,為了滿足后臺(tái)業(yè)務(wù)各類“奇形怪狀”的需求盘寡,往往會(huì)在數(shù)據(jù)庫上建立各種索引,這些索引占用大量內(nèi)存撮慨,會(huì)使得用戶側(cè)前臺(tái)業(yè)務(wù)uid/login_name上的查詢性能與寫入性能大幅度降低竿痰,處理時(shí)間增長脆粥。


對于這一類業(yè)務(wù),應(yīng)該采用“前臺(tái)與后臺(tái)分離”的架構(gòu)方案:

用戶側(cè)前臺(tái)業(yè)務(wù)需求架構(gòu)依然不變影涉,產(chǎn)品運(yùn)營側(cè)后臺(tái)業(yè)務(wù)需求則抽取獨(dú)立的web / service / db來支持变隔,解除系統(tǒng)之間的耦合,對于“業(yè)務(wù)復(fù)雜”“并發(fā)量低”“無需高可用”“能接受一定延時(shí)”的后臺(tái)業(yè)務(wù):

可以去掉service層蟹倾,在運(yùn)營后臺(tái)web層通過dao直接訪問db

不需要反向代理匣缘,不需要集群冗余

不需要訪問實(shí)時(shí)庫,可以通過MQ或者線下異步同步數(shù)據(jù)

在數(shù)據(jù)庫非常大的情況下鲜棠,可以使用更契合大量數(shù)據(jù)允許接受更高延時(shí)的“索引外置”或者“HIVE”的設(shè)計(jì)方案


八肌厨、總結(jié)

將以“用戶中心”為典型的“單KEY”類業(yè)務(wù),水平切分的架構(gòu)點(diǎn)豁陆,本文做了這樣一些介紹柑爸。


水平切分方式

范圍法

哈希法


水平切分后碰到的問題

通過uid屬性查詢能直接定位到庫,通過非uid屬性查詢不能定位到庫


非uid屬性查詢的典型業(yè)務(wù)

用戶側(cè)盒音,前臺(tái)訪問表鳍,單條記錄的查詢,訪問量較大祥诽,服務(wù)需要高可用譬圣,并且對一致性的要求較高

運(yùn)營側(cè),后臺(tái)訪問雄坪,根據(jù)產(chǎn)品厘熟、運(yùn)營需求,訪問模式各異诸衔,基本上是批量分頁的查詢盯漂,由于是內(nèi)部系統(tǒng),訪問量很低笨农,對可用性的要求不高就缆,對一致性的要求也沒這么嚴(yán)格


這兩類業(yè)務(wù)的架構(gòu)設(shè)計(jì)思路

針對用戶側(cè),應(yīng)該采用“建立非uid屬性到uid的映射關(guān)系”的架構(gòu)方案

針對運(yùn)營側(cè)谒亦,應(yīng)該采用“前臺(tái)與后臺(tái)分離”的架構(gòu)方案


用戶前臺(tái)側(cè)竭宰,“建立非uid屬性到uid的映射關(guān)系”最佳實(shí)踐

索引表法:數(shù)據(jù)庫中記錄login_name->uid的映射關(guān)系

緩存映射法:緩存中記錄login_name->uid的映射關(guān)系

login_name生成uid

login_name基因融入uid


運(yùn)營后臺(tái)側(cè),“前臺(tái)與后臺(tái)分離”最佳實(shí)踐

前臺(tái)份招、后臺(tái)系統(tǒng)web/service/db分離解耦切揭,避免后臺(tái)低效查詢引發(fā)前臺(tái)查詢抖動(dòng)

可以采用數(shù)據(jù)冗余的設(shè)計(jì)方式

可以采用“外置索引”(例如ES搜索系統(tǒng))或者“大數(shù)據(jù)處理”(例如HIVE)來滿足后臺(tái)變態(tài)的查詢需求


轉(zhuǎn)自:沈劍的微信文章

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市锁摔,隨后出現(xiàn)的幾起案子廓旬,更是在濱河造成了極大的恐慌,老刑警劉巖谐腰,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件孕豹,死亡現(xiàn)場離奇詭異涩盾,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)励背,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進(jìn)店門春霍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人叶眉,你說我怎么就攤上這事址儒。” “怎么了衅疙?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵莲趣,是天一觀的道長。 經(jīng)常有香客問我炼蛤,道長妖爷,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任理朋,我火速辦了婚禮,結(jié)果婚禮上绿聘,老公的妹妹穿的比我還像新娘嗽上。我一直安慰自己,他們只是感情好熄攘,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布兽愤。 她就那樣靜靜地躺著,像睡著了一般挪圾。 火紅的嫁衣襯著肌膚如雪浅萧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天哲思,我揣著相機(jī)與錄音洼畅,去河邊找鬼。 笑死棚赔,一個(gè)胖子當(dāng)著我的面吹牛帝簇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播靠益,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼丧肴,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了胧后?” 一聲冷哼從身側(cè)響起芋浮,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎壳快,沒想到半個(gè)月后纸巷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體镇草,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年何暇,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了陶夜。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,650評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡裆站,死狀恐怖条辟,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情宏胯,我是刑警寧澤羽嫡,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站肩袍,受9級特大地震影響杭棵,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜氛赐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一魂爪、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧艰管,春花似錦滓侍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至缸浦,卻和暖如春夕冲,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背裂逐。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工歹鱼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人絮姆。 一個(gè)月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓醉冤,卻偏偏與公主長得像,于是被迫代替她去往敵國和親篙悯。 傳聞我的和親對象是個(gè)殘疾皇子蚁阳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評論 2 349

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