高性能架構(gòu)-數(shù)據(jù)庫(kù)架構(gòu)方案(數(shù)據(jù)庫(kù)高可用架構(gòu))
數(shù)據(jù)是是一個(gè)企業(yè)的核心價(jià)值,現(xiàn)在每個(gè)企業(yè)都把數(shù)據(jù)視為公司核心機(jī)密。而數(shù)據(jù)庫(kù)是存儲(chǔ)數(shù)據(jù)的地方,在一個(gè)系統(tǒng)中的重要性更不言而喻。如何設(shè)計(jì)一個(gè)高性能的數(shù)據(jù)庫(kù)系統(tǒng),直接影響一個(gè)系統(tǒng)的存亡。目前常用的架構(gòu)方案有主備、主從、讀寫(xiě)分離、雙主等,以及數(shù)據(jù)庫(kù)擴(kuò)容方案分庫(kù)分表。今天講一講企業(yè)中常用的方案。
主備架構(gòu)
主備架構(gòu)是比較常見(jiàn)的架構(gòu)方案,中有主庫(kù)提供讀寫(xiě)服務(wù),備份庫(kù)同步主庫(kù)數(shù)據(jù),當(dāng)主庫(kù)故障時(shí)系統(tǒng)自動(dòng)切換至備份庫(kù)。
優(yōu)點(diǎn):讀寫(xiě)都操作主庫(kù),不存在數(shù)據(jù)一致性問(wèn)題。架構(gòu)相對(duì)簡(jiǎn)單運(yùn)維成本比較低。
缺點(diǎn):讀寫(xiě)都在主庫(kù),很容易產(chǎn)生系統(tǒng)瓶頸。大部分情況下讀多寫(xiě)少,讀會(huì)先成為瓶頸,進(jìn)而影響寫(xiě)性能。備庫(kù)只是單純的備份,資源利用率低。只能通過(guò)建立索引和增加緩存的方式提高性能。
主從架構(gòu)
主從架構(gòu)也是一種比較常用的架構(gòu),一般會(huì)一主多從,讀寫(xiě)分離進(jìn)行實(shí)現(xiàn)。寫(xiě)數(shù)據(jù)會(huì)在主庫(kù)上進(jìn)行操作,然后從庫(kù)會(huì)同步主庫(kù)數(shù)據(jù)。讀數(shù)據(jù)只在從庫(kù)上進(jìn)行操作,分擔(dān)了主庫(kù)的壓力。
優(yōu)點(diǎn):一般大型系統(tǒng)讀多寫(xiě)少,讀會(huì)成瓶頸,這樣的架構(gòu)分擔(dān)了主庫(kù)的壓力。索引不用建在主庫(kù),可以建在只用于查詢(xún)的從庫(kù)上,這樣可以提高寫(xiě)的效率??梢酝ㄟ^(guò)增加從庫(kù)來(lái)提高讀的性能。
缺點(diǎn):存在單點(diǎn)故障,如果主庫(kù)掛了,寫(xiě)操作無(wú)法進(jìn)行。從庫(kù)越多,需要從主庫(kù)拉取日志的從庫(kù)端就越多,進(jìn)而影響主庫(kù)的性能,并且數(shù)據(jù)同步完成的時(shí)間也會(huì)更長(zhǎng)。
數(shù)據(jù)同步一致性問(wèn)題
由于從庫(kù)拉取主庫(kù)數(shù)據(jù)一般通過(guò)日志方式,即主庫(kù)獲取日志記錄,然后同步到從庫(kù)上執(zhí)行。這個(gè)過(guò)程中可能存在延遲。假如一個(gè)用戶(hù)剛寫(xiě)入一條數(shù)據(jù),然后就開(kāi)始刷新數(shù)據(jù)列表,這條數(shù)據(jù)有可能還未同步至從庫(kù),造成無(wú)法顯示在用戶(hù)端。有以下方案進(jìn)行解決:
選擇讀主
首先在寫(xiě)數(shù)據(jù)的時(shí)候同時(shí)往緩存里寫(xiě)一份數(shù)據(jù),比如根據(jù)庫(kù) 表 業(yè)務(wù)特征生成一個(gè)key放到Cache里并設(shè)置超時(shí)時(shí)間(大于等于主從數(shù)據(jù)同步時(shí)間)。讀請(qǐng)求時(shí),同樣的方式生成key先去查Cache,再判斷是否命中。若命中,則讀主庫(kù),否則讀從庫(kù)。代價(jià)是多了一次緩存讀寫(xiě),基本可以忽略。
同步復(fù)制
同步復(fù)制等主從同步完成,寫(xiě)請(qǐng)求才返回。這里利用數(shù)據(jù)庫(kù)自帶的功能,實(shí)現(xiàn)比較簡(jiǎn)單。代價(jià)是寫(xiě)請(qǐng)求時(shí)延增長(zhǎng),吞吐量降低。
強(qiáng)制讀主
比如一些剛剛存儲(chǔ)的數(shù)據(jù),大概率還沒(méi)有同步到從庫(kù)的情況下,可以強(qiáng)制從主庫(kù)讀取。
分庫(kù)分表方案
數(shù)據(jù)庫(kù)瓶頸
服務(wù)器都有IO和CPU的瓶頸,隨著數(shù)據(jù)庫(kù)的活躍連接數(shù)增加,數(shù)據(jù)庫(kù)會(huì)達(dá)到活躍連接數(shù)的閾值。如果一個(gè)數(shù)據(jù)庫(kù)的列比較多,請(qǐng)求也比較多,這樣可以采用垂直分表方案,把數(shù)據(jù)分開(kāi)放不同表,這樣可以加快讀速度。如果網(wǎng)絡(luò)IO也比較大,就可以采取垂直分庫(kù)技術(shù),把數(shù)據(jù)存在在不同的數(shù)據(jù)庫(kù),以加快返回速度。單表數(shù)據(jù)量太大,查詢(xún)時(shí)掃描的行太多,SQL效率低,CPU率先出現(xiàn)瓶頸,可以采用水平分表方式優(yōu)化。
水平分庫(kù)(表)
以字段為依據(jù),按照一定策略(hash、range等),將一個(gè)庫(kù)中的數(shù)據(jù)拆分到多個(gè)庫(kù)(表)中。每個(gè)庫(kù)或表的結(jié)構(gòu)都是一樣的,但是數(shù)據(jù)是不一致的,所有數(shù)據(jù)的并集就是全量數(shù)據(jù)。
如果庫(kù)只有一張表數(shù)據(jù)量大性能太低,就考慮水平分表。假如庫(kù)里的表字段相對(duì)比較少,數(shù)據(jù)量大且服務(wù)器運(yùn)行達(dá)到極限,就要考慮水平分庫(kù)。水平分庫(kù)(表)主要解決單庫(kù)(表)數(shù)據(jù)量太大的問(wèn)題。
垂直分庫(kù)(表)
以表為依據(jù),按照業(yè)務(wù)歸屬不同,將不同的表字段拆分到不同的庫(kù)中。每個(gè)庫(kù)(表)結(jié)構(gòu)都不一樣,每個(gè)庫(kù)(表)結(jié)構(gòu)也不一樣,所有庫(kù)(表)數(shù)據(jù)的并集為全量數(shù)據(jù)。
表的記錄并不多,但是字段多,并且熱點(diǎn)數(shù)據(jù)和非熱點(diǎn)數(shù)據(jù)在一起,單行數(shù)據(jù)所需的存儲(chǔ)空間較大。以至于數(shù)據(jù)庫(kù)緩存的數(shù)據(jù)行減少,查詢(xún)時(shí)會(huì)去讀磁盤(pán)數(shù)據(jù)產(chǎn)生大量的隨機(jī)讀IO,產(chǎn)生IO瓶頸。這個(gè)時(shí)候就需要垂直分表。隨著業(yè)務(wù)的發(fā)展一些公用的配置表、字典表等越來(lái)越多,這時(shí)可以將這些表拆到單獨(dú)的庫(kù)??傊褪歉鶕?jù)業(yè)務(wù)邏輯及運(yùn)行情況,把數(shù)據(jù)進(jìn)行拆分,減少單表字段很多的情況。