自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

完爆90%的性能毛病,數(shù)據(jù)庫優(yōu)化八大通用絕招!

數(shù)據(jù)庫 其他數(shù)據(jù)庫
這八個(gè)方案里,大部分都存在數(shù)據(jù)同步的情況,只要存在數(shù)據(jù)同步,無論是一主多從、分布式緩存、CQRS都好,都會(huì)有數(shù)據(jù)一致性的問題導(dǎo)致,因此這些方案更多適合一些只讀的業(yè)務(wù)場(chǎng)景。當(dāng)然有些寫后既查的場(chǎng)景,可以通過過渡頁或者廣告頁通過用戶點(diǎn)擊關(guān)閉切換頁面的方式來緩解數(shù)據(jù)不一致性的情況。

大家好,我是不才陳某~

毫不夸張的說咱們后端工程師,無論在哪家公司,呆在哪個(gè)團(tuán)隊(duì),做哪個(gè)系統(tǒng),遇到的第一個(gè)讓人頭疼的問題絕對(duì)是數(shù)據(jù)庫性能問題。如果我們有一套成熟的方法論,能讓大家快速、準(zhǔn)確的去選擇出合適的優(yōu)化方案,我相信能夠快速準(zhǔn)備解決咱么日常遇到的80%甚至90%的性能問題。

從解決問題的角度出發(fā),我們得先了解到問題的原因;其次我們得有一套思考、判斷問題的流程方式,讓我們合理的站在哪個(gè)層面選擇方案;最后從眾多的方案里面選擇一個(gè)適合的方案進(jìn)行解決問題,找到一個(gè)合適的方案的前提是我們自己對(duì)各種方案之間的優(yōu)缺點(diǎn)、場(chǎng)景有足夠的了解,沒有一個(gè)方案是完全可以通吃通用的,軟件工程沒有銀彈。

下文的我工作多年以來,曾經(jīng)使用過的八大方案,結(jié)合了平常自己學(xué)習(xí)收集的一些資料,以系統(tǒng)、全面的方式整理成了這篇博文,也希望能讓一些有需要的同行在工作上、成長(zhǎng)上提供一定的幫助。

為什么數(shù)據(jù)庫會(huì)慢?

慢的本質(zhì):

慢的本質(zhì)


查找的時(shí)間復(fù)雜度

查找算法

存儲(chǔ)數(shù)據(jù)結(jié)構(gòu)

存儲(chǔ)數(shù)據(jù)結(jié)構(gòu)

數(shù)據(jù)總量

數(shù)據(jù)拆分

高負(fù)載

CPU、磁盤繁忙

無論是關(guān)系型數(shù)據(jù)庫還是NoSQL,任何存儲(chǔ)系統(tǒng)決定于其查詢性能的主要有三種:

  • 查找的時(shí)間復(fù)雜度
  • 數(shù)據(jù)總量
  • 高負(fù)載

而決定于查找時(shí)間復(fù)雜度主要有兩個(gè)因素:

  • 查找算法
  • 存儲(chǔ)數(shù)據(jù)結(jié)構(gòu)

無論是哪種存儲(chǔ),數(shù)據(jù)量越少,自然查詢性能就越高,隨著數(shù)據(jù)量增多,資源的消耗(CPU、磁盤讀寫繁忙)、耗時(shí)也會(huì)越來越高。關(guān)注公眾號(hào):碼猿技術(shù)專欄,回復(fù)關(guān)鍵詞:1111 獲取阿里內(nèi)部Java性能調(diào)優(yōu)手冊(cè)

從關(guān)系型數(shù)據(jù)庫角度出發(fā),索引結(jié)構(gòu)基本固定是B+Tree,時(shí)間復(fù)雜度是O(log n),存儲(chǔ)結(jié)構(gòu)是行式存儲(chǔ)。因此咱們對(duì)于關(guān)系數(shù)據(jù)庫能優(yōu)化的一般只有數(shù)據(jù)量。

而高負(fù)載造成原因有高并發(fā)請(qǐng)求、復(fù)雜查詢等,導(dǎo)致CPU、磁盤繁忙等,而服務(wù)器資源不足則會(huì)導(dǎo)致慢查詢等問題。該類型問題一般會(huì)選擇集群、數(shù)據(jù)冗余的方式分擔(dān)壓力。

圖片

應(yīng)該站在哪個(gè)層面思考優(yōu)化?

圖片

從上圖可見,自頂向下的一共有四層,分別是硬件、存儲(chǔ)系統(tǒng)、存儲(chǔ)結(jié)構(gòu)、具體實(shí)現(xiàn)。層與層之間是緊密聯(lián)系的,每一層的上層是該層的載體;因此越往頂層越能決定性能的上限,同時(shí)優(yōu)化的成本也相對(duì)會(huì)比較高,性價(jià)比也隨之越低。以最底層的具體實(shí)現(xiàn)為例,那么索引的優(yōu)化的成本應(yīng)該是最小的,可以說加了索引后無論是CPU消耗還是響應(yīng)時(shí)間都是立竿見影降低;然而一個(gè)簡(jiǎn)單的語句,無論如何優(yōu)化加索引也是有局限的,當(dāng)在具體實(shí)現(xiàn)這層沒有任何優(yōu)化空間的時(shí)候就得往上一層【存儲(chǔ)結(jié)構(gòu)】思考,思考是否從物理表設(shè)計(jì)的層面出發(fā)優(yōu)化(如分庫分表、壓縮數(shù)據(jù)量等);關(guān)注公眾號(hào):碼猿技術(shù)專欄,回復(fù)關(guān)鍵詞:1111 獲取阿里內(nèi)部Java性能調(diào)優(yōu)手冊(cè);如果是文檔型數(shù)據(jù)庫得思考下文檔聚合的結(jié)果;如果在存儲(chǔ)結(jié)構(gòu)這層優(yōu)化得沒效果,得繼續(xù)往再上一次進(jìn)行考慮,是否關(guān)系型數(shù)據(jù)庫應(yīng)該不適合用在現(xiàn)在得業(yè)務(wù)場(chǎng)景?如果要換存儲(chǔ),那么得換怎樣得NoSQL?

所以咱們優(yōu)化的思路,出于性價(jià)比的優(yōu)先考慮具體實(shí)現(xiàn),實(shí)在沒有優(yōu)化空間了再往上一層考慮。當(dāng)然如果公司有錢,直接使用鈔能力,繞過了前面三層,這也是一種便捷的應(yīng)急處理方式。

該篇文章不討論頂與底的兩個(gè)層面的優(yōu)化,主要從存儲(chǔ)結(jié)構(gòu)、存儲(chǔ)系統(tǒng)中間兩層的角度出發(fā)進(jìn)行探討。

八大方案總結(jié)

圖片

數(shù)據(jù)庫的優(yōu)化方案核心本質(zhì)有三種:減少數(shù)據(jù)量、用空間換性能、選擇合適的存儲(chǔ)系統(tǒng),這也對(duì)應(yīng)了開篇講解的慢的三個(gè)原因:數(shù)據(jù)總量、高負(fù)載、*查找的時(shí)間復(fù)雜度。*

這里大概解釋下收益類型:短期收益,處理成本低,能緊急應(yīng)對(duì),久了則會(huì)有技術(shù)債務(wù);長(zhǎng)期收益則跟短期收益相反,短期內(nèi)處理成本高,但是效果能長(zhǎng)久使用,擴(kuò)展性會(huì)更好。

靜態(tài)數(shù)據(jù)意思是,相對(duì)改動(dòng)頻率比較低的,也無需過多聯(lián)表的,where過濾比較少。動(dòng)態(tài)數(shù)據(jù)與之相反,更新頻率高,通過動(dòng)態(tài)條件篩選過濾。

減少數(shù)據(jù)量

減少數(shù)據(jù)量類型共有四種方案:數(shù)據(jù)序列化存儲(chǔ)、數(shù)據(jù)歸檔、中間表生成、分庫分表。

就如上面所說的,無論是哪種存儲(chǔ),數(shù)據(jù)量越少,自然查詢性能就越高,隨著數(shù)據(jù)量增多,資源的消耗(CPU、磁盤讀寫繁忙)、耗時(shí)也會(huì)越來越高。目前市面上的NoSQL基本上都支持分片存儲(chǔ),所以其天然分布式寫的能力從數(shù)據(jù)量上能得到非常的解決方案。而關(guān)系型數(shù)據(jù)庫,查找算法與存儲(chǔ)結(jié)構(gòu)是可以優(yōu)化的空間比較少,因此咱們一般思考出發(fā)點(diǎn)只有從如何減少數(shù)據(jù)量的這個(gè)角度進(jìn)行選擇優(yōu)化,因此本類型的優(yōu)化方案主要針對(duì)關(guān)系型數(shù)據(jù)庫進(jìn)行處理。

圖片

數(shù)據(jù)歸檔

圖片

注意點(diǎn):別一次性遷移數(shù)量過多,建議低頻率多次限量遷移。像MySQL由于刪除數(shù)據(jù)后是不會(huì)釋放空間的,可以執(zhí)行命令OPTIMIZE TABLE釋放存儲(chǔ)空間,但是會(huì)鎖表,如果存儲(chǔ)空間還滿足,可以不執(zhí)行。

建議優(yōu)先考慮該方案,主要通過數(shù)據(jù)庫作業(yè)把非熱點(diǎn)數(shù)據(jù)遷移到歷史表,如果需要查歷史數(shù)據(jù),可新增業(yè)務(wù)入口路由到對(duì)應(yīng)的歷史表(庫)。

圖片

中間表(結(jié)果表)

圖片

中間表(結(jié)果表)其實(shí)就是利用調(diào)度任務(wù)把復(fù)雜查詢的結(jié)果跑出來存儲(chǔ)到一張額外的物理表,因?yàn)檫@張物理表存放的是通過跑批匯總后的數(shù)據(jù),因此可以理解成根據(jù)原有的業(yè)務(wù)進(jìn)行了高度的數(shù)據(jù)壓縮。以報(bào)表為例,如果一個(gè)月的源數(shù)據(jù)有數(shù)十萬,我們通過調(diào)度任務(wù)以月的維度生成,那么等于把原有的數(shù)據(jù)壓縮了幾十萬分之一;接下來的季報(bào)和年報(bào)可以根據(jù)月報(bào)*N來進(jìn)行統(tǒng)計(jì),以這種方式處理的數(shù)據(jù),就算三年、五年甚至十年數(shù)據(jù)量都可以在接受范圍之內(nèi),而且可以精確計(jì)算得到。關(guān)注公眾號(hào):碼猿技術(shù)專欄,回復(fù)關(guān)鍵詞:1111 獲取阿里內(nèi)部Java性能調(diào)優(yōu)手冊(cè)

那么數(shù)據(jù)的壓縮比率是否越低越好?下面有一段口訣:

  • 字段越多,粒度越細(xì),靈活性越高,可以以中間表進(jìn)行不同業(yè)務(wù)聯(lián)表處理。
  • 字段越少,粒度越粗,靈活性越低,一般作為結(jié)果表查詢出來。

數(shù)據(jù)序列化存儲(chǔ)

圖片

圖片

在數(shù)據(jù)庫以序列化存儲(chǔ)的方式,對(duì)于一些不需要結(jié)構(gòu)化存儲(chǔ)的業(yè)務(wù)來說是一種很好減少數(shù)據(jù)量的方式,特別是對(duì)于一些M*N的數(shù)據(jù)量的業(yè)務(wù)場(chǎng)景,如果以M作為主表優(yōu)化,那么就可以把數(shù)據(jù)量維持最多是M的量級(jí)。另外像訂單的地址信息,這種業(yè)務(wù)一般是不需要根據(jù)里面的字段檢索出來,也比較適合。

這種方案我認(rèn)為屬于一種臨時(shí)性的優(yōu)化方案,無論是從序列化后丟失了部份字段的查詢能力,還是這方案的可優(yōu)化性都是有限的。

分庫分表

分庫分表作為數(shù)據(jù)庫優(yōu)化的一種非常經(jīng)典的優(yōu)化方案,特別是在以前NoSQL還不是很成熟的年代,這個(gè)方案就如救命草一般的存在。

如今也有不少同行也會(huì)選擇這種優(yōu)化方式,但是從我角度來看,分庫分表是一種優(yōu)化成本很大的方案。這里我有幾個(gè)建議:

  1. 分庫分表是實(shí)在沒有辦法的辦法,應(yīng)放到最后選擇。
  2. 優(yōu)先選擇NoSQL代替,因?yàn)镹oSQL誕生基本上為了擴(kuò)展性與高性能。
  3. 究竟分庫還是分表?量大則分表,并發(fā)高則分庫
  4. 不考慮擴(kuò)容,一部做到位。因?yàn)榧夹g(shù)更新太快了,每3-5年一大變。

拆分方式

圖片

只要涉及到這個(gè)拆,那么無論是微服務(wù)也好,分庫分表也好,拆分的方式主要分兩種:垂直拆分、水平拆分。

垂直拆分更多是從業(yè)務(wù)角度進(jìn)行拆分,主要是為了降低業(yè)務(wù)耦合度;此外以SQL Server為例,一頁是8KB存儲(chǔ),如果在一張表里字段越多,一行數(shù)據(jù)自然占的空間就越大,那么一頁數(shù)據(jù)所存儲(chǔ)的行數(shù)就自然越少,那么每次查詢所需要IO則越高因此性能自然也越慢;因此反之,減少字段也能很好提高性能。之前我聽說某些同行的表有80個(gè)字段,幾百萬的數(shù)據(jù)就開始慢了。

水平拆分更多是從技術(shù)角度進(jìn)行拆分,拆分后每張表的結(jié)構(gòu)是一模一樣的,簡(jiǎn)而言之就是把原有一張表的數(shù)據(jù),通過技術(shù)手段進(jìn)行分片到多張表存儲(chǔ),從根本上解決了數(shù)據(jù)量的問題。

圖片

圖片

路由方式

圖片

進(jìn)行水平拆分后,根據(jù)分區(qū)鍵(sharding key)原來應(yīng)該在同一張表的數(shù)據(jù)拆解寫到不同的物理表里,那么查詢也得根據(jù)分區(qū)鍵進(jìn)行定位到對(duì)應(yīng)的物理表從而把數(shù)據(jù)給查詢出來。

路由方式一般有三種區(qū)間范圍、Hash、分片映射表,每種路由方式都有自己的優(yōu)點(diǎn)和缺點(diǎn),可以根據(jù)對(duì)應(yīng)的業(yè)務(wù)場(chǎng)景進(jìn)行選擇。

區(qū)間范圍根據(jù)某個(gè)元素的區(qū)間的進(jìn)行拆分,以時(shí)間為例子,假如有個(gè)業(yè)務(wù)我們希望以月為單位拆分那么表就會(huì)拆分像 table_2022-04,這種對(duì)于文檔型、ElasticSearch這類型的NoSQL也適用,無論是定位查詢,還是日后清理維護(hù)都是非常的方便的。那么缺點(diǎn)也明顯,會(huì)因?yàn)闃I(yè)務(wù)獨(dú)特性導(dǎo)致數(shù)據(jù)不平均,甚至不同區(qū)間范圍之間的數(shù)據(jù)量差異很大。

Hash也是一種常用的路由方式,根據(jù)Hash算法取模以數(shù)據(jù)量均勻分別存儲(chǔ)在物理表里,缺點(diǎn)是對(duì)于帶分區(qū)鍵的查詢依賴特別強(qiáng),如果不帶分區(qū)鍵就無法定位到具體的物理表導(dǎo)致相關(guān)所有表都查詢一次,而且在分庫的情況下對(duì)于Join、聚合計(jì)算、分頁等一些RDBMS的特性功能還無法使用。

圖片

一般分區(qū)鍵就一個(gè),假如有時(shí)候業(yè)務(wù)場(chǎng)景得用不是分區(qū)鍵的字段進(jìn)行查詢,那么難道就必須得全部掃描一遍?其實(shí)可以使用分片映射表的方式,簡(jiǎn)單來說就是額外有一張表記錄額外字段與分區(qū)鍵的映射關(guān)系。舉個(gè)例子,有張訂單表,原本是以UserID作為分區(qū)鍵拆分的,現(xiàn)在希望用OrderID進(jìn)行查詢,那么得有額外得一張物理表記錄了OrderID與UserID的映射關(guān)系。因此得先查詢一次映射表拿到分區(qū)鍵,再根據(jù)分區(qū)鍵的值路由到對(duì)應(yīng)的物理表查詢出來??赡苡行┡笥褧?huì)問,那這映射表是否多一個(gè)映射關(guān)系就多一張表,還是多個(gè)映射關(guān)系在同一張表。我優(yōu)先建議單獨(dú)處理,如果說映射表字段過多,那跟不進(jìn)行水平拆分時(shí)的狀態(tài)其實(shí)就是一致的,這又跑回去的老問題。

用空間換性能

該類型的兩個(gè)方案都是用來應(yīng)對(duì)高負(fù)載的場(chǎng)景,方案有以下兩種:分布式緩存、一主多從。

與其說這個(gè)方案叫用空間換性能,我認(rèn)為用空間換資源更加貼切一些。因此兩個(gè)方案的本質(zhì)主要通數(shù)據(jù)冗余、集群等方式分擔(dān)負(fù)載壓力。

對(duì)于關(guān)系型數(shù)據(jù)庫而言,因?yàn)樗腁CID特性讓它天生不支持寫的分布式存儲(chǔ),但是它依然天然的支持分布式讀。

圖片

分布式緩存

圖片

緩存層級(jí)可以分好幾種:客戶端緩存、API服務(wù)本地緩存和分布式緩存,咱們這次只聊分布式緩存。一般我們選擇分布式緩存系統(tǒng)都會(huì)優(yōu)先選擇NoSQL的鍵值型數(shù)據(jù)庫,例如Memcached、Redis,如今Redis的數(shù)據(jù)結(jié)構(gòu)多樣性,高性能,易擴(kuò)展性也逐漸占據(jù)了分布式緩存的主導(dǎo)地位。

緩存策略也主要有很多種:Cache-Aside、Read/Wirte-Through、Write-Back,咱們用得比較多的方式主要Cache-Aside,?具體流程可看下圖:

圖片

我相信大家對(duì)分布式緩存相對(duì)都比較熟悉了,但是我在這里還是有幾個(gè)注意點(diǎn)希望提醒一下大家:

避免濫用緩存

緩存應(yīng)該是按需使用,從28法則來看,80%的性能問題由主要的20%的功能引起。濫用緩存的后果會(huì)導(dǎo)致維護(hù)成本增大,而且有一些數(shù)據(jù)一致性的問題也不好定位。特別像一些動(dòng)態(tài)條件的查詢或者分頁,key的組裝是多樣化的,量大又不好用keys指令去處理,當(dāng)然我們可以用額外的一個(gè)key把記錄數(shù)據(jù)的key以集合方式存儲(chǔ),刪除時(shí)候做兩次查詢,先查Key的集合,然后再遍歷Key集合把對(duì)應(yīng)的內(nèi)容刪除。這一頓操作下來無疑是非常廢功夫的,誰弄誰知道。

圖片

避免緩存擊穿

當(dāng)緩存沒有數(shù)據(jù),就得跑去數(shù)據(jù)庫查詢出來,這就是緩存穿透。假如某個(gè)時(shí)間臨界點(diǎn)數(shù)據(jù)是空的例如周排行榜,穿透過去的無論查找多少次數(shù)據(jù)庫仍然是空,而且該查詢消耗CPU相對(duì)比較高,并發(fā)一進(jìn)來因?yàn)槿鄙倭司彺鎸拥膶?duì)高并發(fā)的應(yīng)對(duì),這個(gè)時(shí)候就會(huì)因?yàn)椴l(fā)導(dǎo)致數(shù)據(jù)庫資源消耗過高,這就是緩存擊穿。數(shù)據(jù)庫資源消耗過高就會(huì)導(dǎo)致其他查詢超時(shí)等問題。

該問題的解決方案也簡(jiǎn)單,對(duì)于查詢到數(shù)據(jù)庫的空結(jié)果也緩存起來,但是給一個(gè)相對(duì)快過期的時(shí)間。有些同行可能又會(huì)問,這樣不就會(huì)造成了數(shù)據(jù)不一致了么?一般有數(shù)據(jù)同步的方案像分布式緩存、后續(xù)會(huì)說的一主多從、CQRS,只要存在數(shù)據(jù)同步這幾個(gè)字,那就意味著會(huì)存在數(shù)據(jù)一致性的問題,因此如果使用上述方案,對(duì)應(yīng)的業(yè)務(wù)場(chǎng)景應(yīng)允許容忍一定的數(shù)據(jù)不一致。?

不是所有慢查詢都適用

一般來說,慢的查詢都意味著比較吃資源的(CPU、磁盤I/O)。舉個(gè)例子,假如某個(gè)查詢功能需要3秒時(shí)間,串行查詢的時(shí)候并沒什么問題,我們繼續(xù)假設(shè)這功能每秒大概QPS為100,那么在第一次查詢結(jié)果返回之前,接下來的所有查詢都應(yīng)該穿透到數(shù)據(jù)庫,也就意味著這幾秒時(shí)間有300個(gè)請(qǐng)求到數(shù)據(jù)庫,如果這個(gè)時(shí)候數(shù)據(jù)庫CPU達(dá)到了100%,那么接下來的所有查詢都會(huì)超時(shí),也就是無法有第一個(gè)查詢結(jié)果緩存起來,從而還是形成了緩存擊穿。

一主多從

圖片

常用的分擔(dān)數(shù)據(jù)庫壓力還有一種常用做法,就是讀寫分離、一主多從。咱們都是知道關(guān)系型數(shù)據(jù)庫天生是不具備分布式分片存儲(chǔ)的,也就是不支持分布式寫,但是它天然的支持分布式讀。一主多從是部署多臺(tái)從庫只讀實(shí)例,通過冗余主庫的數(shù)據(jù)來分擔(dān)讀請(qǐng)求的壓力,路由算法可有代碼實(shí)現(xiàn)或者中間件解決,具體可以根據(jù)團(tuán)隊(duì)的運(yùn)維能力與代碼組件支持視情況選擇。

一主多從在還沒找到根治方案前是一個(gè)非常好的應(yīng)急解決方案,特別是在現(xiàn)在云服務(wù)的年代,擴(kuò)展從庫是一件非常方便的事情,而且一般情況只需要運(yùn)維或者DBA解決就行,無需開發(fā)人員接入。當(dāng)然這方案也有缺點(diǎn),因?yàn)閿?shù)據(jù)無法分片,所以主從的數(shù)據(jù)量完全冗余過去,也會(huì)導(dǎo)致高的硬件成本。從庫也有其上限,從庫過多了會(huì)主庫的多線程同步數(shù)據(jù)的壓力。

圖片

選擇合適的存儲(chǔ)系統(tǒng)

NoSQL主要以下五種類型:鍵值型、文檔型、列型、圖型、搜素引擎,不同的存儲(chǔ)系統(tǒng)直接決定了查找算法、存儲(chǔ)數(shù)據(jù)結(jié)構(gòu),也應(yīng)對(duì)了需要解決的不同的業(yè)務(wù)場(chǎng)景。NoSQL的出現(xiàn)也解決了關(guān)系型數(shù)據(jù)庫之前面臨的難題(性能、高并發(fā)、擴(kuò)展性等)。

例如,ElasticSearch的查找算法是倒排索引,可以用來代替關(guān)系型數(shù)據(jù)庫的低性能、高消耗的Like搜索(全表掃描)。而Redis的Hash結(jié)構(gòu)決定了時(shí)間復(fù)雜度為O(1),還有它的內(nèi)存存儲(chǔ),結(jié)合分片集群存儲(chǔ)方式以至于可以支撐數(shù)十萬QPS。

因此本類型的方案主要有兩種:CQRS、替換(選擇)存儲(chǔ),這兩種方案的最終本質(zhì)基本是一樣的主要使用合適存儲(chǔ)來彌補(bǔ)關(guān)系型數(shù)據(jù)庫的缺點(diǎn),只不過切換過渡的方式會(huì)有點(diǎn)不一樣。

圖片

CQRS

CQS(命令查詢分離)指同一個(gè)對(duì)象中作為查詢或者命令的方法,每個(gè)方法或者返回的狀態(tài),要么改變狀態(tài),但不能兩者兼?zhèn)?/strong>

圖片

講解CQRS前得了解CQS,有些小伙伴看了估計(jì)還沒不是很清晰,我這里用通俗的話解釋:某個(gè)對(duì)象的數(shù)據(jù)訪問的方法里,要么只是查詢,要么只是寫入(更新)。而CQRS(命令查詢職責(zé)分離)基于CQS的基礎(chǔ)上,用物理數(shù)據(jù)庫來寫入(更新),而用另外的存儲(chǔ)系統(tǒng)來查詢數(shù)據(jù)。因此我們?cè)谀承I(yè)務(wù)場(chǎng)景進(jìn)行存儲(chǔ)架構(gòu)設(shè)計(jì)時(shí),可以通過關(guān)系型數(shù)據(jù)庫的ACID特性進(jìn)行數(shù)據(jù)的更新與寫入,用NoSQL的高性能與擴(kuò)展性進(jìn)行數(shù)據(jù)的查詢處理,這樣的好處就是關(guān)系型數(shù)據(jù)庫和NoSQL的優(yōu)點(diǎn)都可以兼得,同時(shí)對(duì)于某些業(yè)務(wù)不適于一刀切的替換存儲(chǔ)的也可以有一個(gè)平滑的過渡。

從代碼實(shí)現(xiàn)角度來看,不同的存儲(chǔ)系統(tǒng)只是調(diào)用對(duì)應(yīng)的接口API,因此CQRS的難點(diǎn)主要在于如何進(jìn)行數(shù)據(jù)同步。

數(shù)據(jù)同步方式

圖片

一般討論到數(shù)據(jù)同步的方式主要是分拉:

推指的是由數(shù)據(jù)變更端通過直接或者間接的方式把數(shù)據(jù)變更的記錄發(fā)送到接收端,從而進(jìn)行數(shù)據(jù)的一致性處理,這種主動(dòng)的方式優(yōu)點(diǎn)是實(shí)時(shí)性高。

拉指的是接收端定時(shí)的輪詢數(shù)據(jù)庫檢查是否有數(shù)據(jù)需要進(jìn)行同步,這種被動(dòng)的方式從實(shí)現(xiàn)角度來看比推簡(jiǎn)單,因?yàn)橥剖切枰獢?shù)據(jù)變更端支持變更日志的推送的。

而推的方式又分兩種:CDC(變更數(shù)據(jù)捕獲)和領(lǐng)域事件。對(duì)于一些舊的項(xiàng)目來說,某些業(yè)務(wù)的數(shù)據(jù)入口非常多,無法完整清晰的梳理清楚,這個(gè)時(shí)候CDC就是一種非常好的方式,只要從最底層數(shù)據(jù)庫層面把變更記錄取到就可。

對(duì)于已經(jīng)服務(wù)化的項(xiàng)目來說領(lǐng)域事件是一種比較舒服的方式,因?yàn)镃DC是需要數(shù)據(jù)庫額外開啟功能或者部署額外的中間件,而領(lǐng)域事件則不需要,從代碼可讀性來看會(huì)更高,也比較開發(fā)人員的維護(hù)思維模式。

圖片

替換(選擇)存儲(chǔ)系統(tǒng)

因?yàn)閺谋举|(zhì)來看該模式與CQRS的核心本質(zhì)是一樣的,主要是要對(duì)NoSQL的優(yōu)缺點(diǎn)有一個(gè)全面認(rèn)識(shí),這樣才能在對(duì)應(yīng)業(yè)務(wù)場(chǎng)景選擇與判斷出一個(gè)合適的存儲(chǔ)系統(tǒng)。這里我像大家介紹一本書馬丁.福勒《NoSQL精粹》,這本書我重復(fù)看了好幾遍,也很好全面介紹各種NoSQL優(yōu)缺點(diǎn)和使用場(chǎng)景。

當(dāng)然替換存儲(chǔ)的時(shí)候,我這里也有個(gè)建議:加入一個(gè)中間版本,該版本做好數(shù)據(jù)同步與業(yè)務(wù)開關(guān),數(shù)據(jù)同步要保證全量與增加的處理,隨時(shí)可以重來,業(yè)務(wù)開關(guān)主要是為了后續(xù)版本的更新做的一個(gè)臨時(shí)型的功能,主要避免后續(xù)版本更新不順利或者因?yàn)榘姹靖聲r(shí)導(dǎo)致的數(shù)據(jù)不一致的情況出現(xiàn)。在跑了一段時(shí)間后,驗(yàn)證了兩個(gè)不同的存儲(chǔ)系統(tǒng)數(shù)據(jù)是一致的后,接下來就可以把數(shù)據(jù)訪問層的底層調(diào)用替換了。如此一來就可以平滑的更新切換。

結(jié)束

本文到這里就把八大方案介紹完了,在這里再次提醒一句,每個(gè)方案都有屬于它的應(yīng)對(duì)場(chǎng)景,咱們只能根據(jù)業(yè)務(wù)場(chǎng)景選擇對(duì)應(yīng)的解決方案,沒有通吃,沒有銀彈。

這八個(gè)方案里,大部分都存在數(shù)據(jù)同步的情況,只要存在數(shù)據(jù)同步,無論是一主多從、分布式緩存、CQRS都好,都會(huì)有數(shù)據(jù)一致性的問題導(dǎo)致,因此這些方案更多適合一些只讀的業(yè)務(wù)場(chǎng)景。當(dāng)然有些寫后既查的場(chǎng)景,可以通過過渡頁或者廣告頁通過用戶點(diǎn)擊關(guān)閉切換頁面的方式來緩解數(shù)據(jù)不一致性的情況。

責(zé)任編輯:武曉燕 來源: 碼猿技術(shù)專欄
相關(guān)推薦

2022-04-25 11:12:08

數(shù)據(jù)庫優(yōu)化性能

2011-05-11 13:19:42

MySQL數(shù)據(jù)庫性能優(yōu)化

2010-07-30 15:31:34

2009-07-07 17:27:37

JDBC連接Oracl

2021-07-20 10:12:53

機(jī)器學(xué)習(xí)數(shù)據(jù)庫深度學(xué)習(xí)

2017-09-29 08:56:13

2011-03-03 13:43:29

2023-05-18 08:00:00

2010-06-03 09:39:24

優(yōu)化MySQL性能

2009-06-22 14:07:46

JSF優(yōu)勢(shì)

2013-09-17 10:32:08

Android性能優(yōu)化數(shù)據(jù)庫

2021-07-11 17:01:22

數(shù)據(jù)庫數(shù)據(jù)算法

2024-02-16 20:28:40

2011-04-29 09:15:16

Servlet

2024-04-24 09:52:19

云技能云遷移云計(jì)算

2011-03-04 11:02:41

2021-01-31 17:50:41

數(shù)據(jù)庫查詢程序員

2023-03-29 08:36:33

國產(chǎn)數(shù)據(jù)庫開源

2011-05-20 10:30:20

ORACLE數(shù)據(jù)庫性能優(yōu)化

2011-05-18 09:39:19

Oracle數(shù)據(jù)庫性能優(yōu)化
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)