多維度分片需求,如何解決查詢問(wèn)題?
點(diǎn)擊上方藍(lán)字“設(shè)為星標(biāo)”
大家好,我是【架構(gòu)擺渡人】,一只十年的程序猿。這是分庫(kù)分表系列的第一篇文章,這個(gè)系列會(huì)給大家分享很多在實(shí)際工作中有用的經(jīng)驗(yàn),如果有收獲,還請(qǐng)分享給更多的朋友。
?
其實(shí)這個(gè)系列有錄過(guò)視頻給大家學(xué)習(xí),但很多讀者反饋說(shuō)看視頻太慢了。也不好沉淀為文檔資料,希望能有一系列文字版本的講解,要用的時(shí)候可以快速瀏覽關(guān)鍵的知識(shí)點(diǎn)。那么它就來(lái)了,我再花點(diǎn)時(shí)間寫成幾篇連續(xù)的文章供大家學(xué)習(xí)。
?

需求背景
?
單庫(kù)單表的時(shí)候,我們?cè)趯?shí)現(xiàn)業(yè)務(wù)需求的時(shí)候,是不會(huì)考慮說(shuō)哪些字段不能用于查詢,只要表中有的字段就可以用它來(lái)做條件查詢。
?
當(dāng)分庫(kù)分表后,就必須要要考慮查詢條件中得有哪些字段。必須要有的肯定是分片的字段,比如你根據(jù)用戶ID進(jìn)行分片,然后查詢的時(shí)候卻沒(méi)有用戶ID,這樣就沒(méi)辦法知道這條SQL到底要去哪個(gè)庫(kù)哪個(gè)表查詢,只能查詢所有的庫(kù)表進(jìn)行結(jié)果的聚合邏輯,性能非常差。
?
比如我們以訂單來(lái)說(shuō)明,常用的查詢場(chǎng)景有根據(jù)訂單號(hào)查詢,根據(jù)買家查詢訂單,根據(jù)賣家查詢訂單。
?
比如我們以用戶來(lái)說(shuō)明,常用的查詢場(chǎng)景有根據(jù)用戶ID查詢,根據(jù)用戶名查詢,根據(jù)手機(jī)號(hào)碼查詢。
?
但是大家想一個(gè)問(wèn)題,就是你分表都是根據(jù)一個(gè)字段去分的,比如訂單的買家,也就是所有買家的訂單都會(huì)在某個(gè)庫(kù)的某個(gè)表中存儲(chǔ)。直接根據(jù)買家是可以定位到數(shù)據(jù)的位置,但是如果直接根據(jù)訂單號(hào)和賣家去查,是無(wú)法定位數(shù)據(jù)的存儲(chǔ)位置。用戶的查詢也是一樣的問(wèn)題,這就是我們今天要講的內(nèi)容。
?

實(shí)現(xiàn)方式
?
?
映射表方式
目前查詢訂單有三個(gè)場(chǎng)景,分別是買家,訂單號(hào),賣家或者店鋪。分表字段的選擇肯定是優(yōu)先選擇查詢量最大的場(chǎng)景進(jìn)行分片,所以訂單最適合的分片字段就是買家。
?
那現(xiàn)在要根據(jù)訂單號(hào)和賣家去查詢訂單使用映射表的方式該如何實(shí)現(xiàn)呢?
?
映射表其實(shí)就是單獨(dú)為賣家和訂單號(hào)建立一個(gè)映射關(guān)系,當(dāng)我們通過(guò)訂單號(hào)取查詢的時(shí)候,先通過(guò)映射關(guān)系找到訂單號(hào)對(duì)應(yīng)的買家,然后再通過(guò)買家就能找到數(shù)據(jù)的存儲(chǔ)位置了。
?

映射可以用普通的表進(jìn)行存儲(chǔ),也可以用KV的Nosql存儲(chǔ)。
?
二級(jí)索引
索引的方式其實(shí)跟映射差不多,不同的點(diǎn)在于映射是一一對(duì)應(yīng)的,而索引方式是一對(duì)多的場(chǎng)景。
也就是說(shuō)我們將買家,賣家,訂單號(hào)都存儲(chǔ)起來(lái),這個(gè)存儲(chǔ)可以用ES,因?yàn)镋S天生就支持水平擴(kuò)展,能否存儲(chǔ)大數(shù)據(jù)量。
?
要注意的是這里只是存儲(chǔ)要搜索的條件,所以是沒(méi)辦法替代數(shù)據(jù)庫(kù)的分庫(kù)分表。
?
那么怎么去構(gòu)建這個(gè)索引呢?可以采用代碼的方式,直接在數(shù)據(jù)創(chuàng)建的時(shí)候往索引里面寫一份,也可以基于binlog的方式,去構(gòu)建,這樣耦合度更低,數(shù)據(jù)存儲(chǔ)稍微有點(diǎn)延遲。
?

?
有了這個(gè)索引之后,比如根據(jù)訂單號(hào)去查詢的時(shí)候,就直接先查索引,得到買家,再去查詢?cè)紨?shù)據(jù)。賣家的查詢也是一樣的邏輯。
?
?
融合方式
比如根據(jù)訂單號(hào)去查詢,無(wú)論是通過(guò)映射還是索引的方式,都需要一次查詢操作。如果我們能直接通過(guò)訂單號(hào)就知道這個(gè)訂單號(hào)是哪個(gè)買家的,這樣就不用多出一次查詢操作了呀。
?
所以我們可以在訂單號(hào)里面融入買家的信息,一般訂單號(hào)都比較長(zhǎng),大家可以去看看自己淘寶的訂單號(hào),是不是能發(fā)現(xiàn)什么規(guī)律,比如前幾位是固定的,或者后幾位是固定的,講到這里大家都懂了吧。
?
把買家融入到訂單號(hào)里面后,查詢的時(shí)候就可以直接提取出買家,完美的省掉了一次多余的查詢操作。
?
?
空間換時(shí)間


總結(jié)
?
這篇文章主要給大家介紹了在分庫(kù)分表過(guò)程中,如何去滿足我們業(yè)務(wù)需求的多維度查詢問(wèn)題。實(shí)現(xiàn)方案有很多,大家要根據(jù)場(chǎng)景選擇合適的方式。
?
?
原創(chuàng):架構(gòu)擺渡人(公眾號(hào)ID:jiagoubaiduren),歡迎分享,轉(zhuǎn)載請(qǐng)保留出處。
