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

讀寫分離水太深,你把握不住,讓叔來——命令查詢權責分離模式

運維 數(shù)據(jù)庫運維
多年以前,那時我正年輕,做技術如魚得水,甚至一度希望自己能當一輩子的一線程序員。但是我又有兩個小愿望想要達成:一個是想多掙點錢;另一個就是對項目的技術棧和架構選型能多有點主動權。

[[403252]]

多年以前,那時我正年輕,做技術如魚得水,甚至一度希望自己能當一輩子的一線程序員。

但是我又有兩個小愿望想要達成:一個是想多掙點錢;另一個就是對項目的技術棧和架構選型能多有點主動權。

多掙點錢是因為當時我剛結婚不久,有自己的家庭規(guī)劃,所以掙錢的欲望也蠻強。

而想有多點技術主動權的原因則是當時領導很賞識我,有些東西逐漸的放權讓我做,我嘗到了甜頭,所以,也有了自己的一些小野心。

而正巧就在那時候,領導給我了一個現(xiàn)在看來職業(yè)生涯中還挺重要的機會。

當時,廣告聯(lián)盟正是發(fā)展的如火如荼的時候,公司也想?yún)⑴c進去分杯羹,于是決定從零開始搞一套廣告平臺。

而我正好也有些類似的開發(fā)經(jīng)驗,且做事還算靠譜,于是,領導便想著讓我去當這套系統(tǒng)的技術負責人。

如果我能把系統(tǒng)做好,對我來說絕對是個證明自己的機會,對以后達成我的兩個小愿望有好處。對我誘惑很大。

只是,老天給你開了一扇門,就總要給你關一扇窗。這個機會不僅僅是我領導看上了,當時,還有另外一個部門的老大也瞄上了。

不得已,上了高層會議討論。討論來討論去的結果就是學習當時別的公司的做法,內(nèi)部競爭。

兩個部門做各做一套平臺,然后各放到線上運營一陣子,誰做得好誰就能得到公司全力投入的機會。

好吧,機會變成了冒險。只是到此時,我也并不能退縮。一旦我退縮會連累賞識我的領導,而且將來在公司的發(fā)展也會嚴重受阻,只能沖了。

為了贏得這場競爭,我和這套系統(tǒng)的產(chǎn)品負責人也溝通了許久。最后定下來了兩個必須實現(xiàn)的目標:

1. 這套系統(tǒng)功能一定要盡量多,尤其是提供給相關業(yè)務人員的功能要多。

之所以要這樣,是因為現(xiàn)在是內(nèi)部競爭。而對于內(nèi)部競爭,使用我們這套系統(tǒng)的業(yè)務人員話語權其實非常大,他們的滿意度很可能是最終評估的勝負手。

同時,我們也計劃為投放在我們這套系統(tǒng)的廣告主們多準備一些體驗度非常好的數(shù)據(jù)追蹤和分析功能,這樣能最大的增加我們產(chǎn)品的吸引力。

2. 這套系統(tǒng)的穩(wěn)定性和可靠性要求非常高,有時候哪怕為此做一些過度設計和實現(xiàn)也是值得的。

這里要解釋下穩(wěn)定性和可靠性在我們當時那個場景里的含義。穩(wěn)定性就是要保證性能是穩(wěn)定的,也就是說我們的系統(tǒng)響應時間應該盡全力保證在一個很短的時間內(nèi)響應。

而可靠性則是我們的系統(tǒng)應該盡全力保證不出錯,因為出錯很可能就會造成用戶流失,導致我們的產(chǎn)品失敗。

定完目標以及產(chǎn)品給完需求后,我就和團隊進入了異常艱苦的開發(fā)工作。那時候,我真的是付出了我全身心的心血。

其實,我本來是個享受生活勝過埋頭苦干的人。雖然此前工作也很忙碌,但是空閑日子也是過得很愜意的。聽聽歌,看看電影,有時和老婆找家餐廳享用美食,時不時的也會踢一場酣暢淋漓的足球。

可是,自從開始投入了這套廣告系統(tǒng)的開發(fā)以后,悠閑的日子就一去不復返了。

我記得那時候我下班是踉踉蹌蹌的走,上班又是踉踉蹌蹌的來。當時最大的心愿就是有張床,躺下去永遠別有人叫醒我。

可是即使這樣辛苦,我依然遇到了數(shù)不清的難題,這些橫亙在開發(fā)路上的硬骨頭,導致我的開發(fā)目標一再被調(diào)整。

其中最麻煩的,就是高并發(fā)的性能問題。

當時我的經(jīng)驗尚淺,Java 說實話周邊的生態(tài)也并不完善。能用來承載訪問的也就是緩存和數(shù)據(jù)庫。同時,由于版權等問題,我還只能選擇 MySQL 數(shù)據(jù)庫。

為了解決這些性能問題,我還特意把官方的 MySQL 手冊打印了出來,天天鉆研。

開始的時候,為了抗住預想中的超高并發(fā)量,我采用的是當時很流行的讀寫分離模式。

但是,實際測試下來,總是有各種不滿意的地方。其中最麻煩的就是各種復雜查詢的性能。

我說過為了獲得內(nèi)部競爭的勝利,這套系統(tǒng)我們盡可能想去往高并發(fā)、多功能這兩個目標上靠。所以,為了這兩個目標,這套系統(tǒng)其實多了很多方便業(yè)務人員使用的功能,并且這個功能設想的目標是:

在高并發(fā)下,也依然保持穩(wěn)定和流暢。

其中,最典型的一個業(yè)務就是可以實時更新的廣告投放排行功能。

這個廣告投放排行需求是這樣的:

  • 首先,我們的用戶要能在管理后臺看到他們自己的投放廣告排行,排名是根據(jù)消費的金額和點擊次數(shù)等指標來排次序。
  • 其次,在我們的后臺,也給業(yè)務人員也搞了個這么個排名,不同的是它是個全局的,是我們所有客戶投放的廣告的一個總排行。
  • 然后,這個排名要能實時的根據(jù)消費金額和點擊次數(shù)的變化而變化。當然,這個實時可以搞成準實時,只要別延遲太過也可以。

本身呢,做排行榜由于用的指標比較多,就需要寫很復雜的 SQL 去數(shù)據(jù)庫中查詢。再加上個需要實時變化,那就得不停的去數(shù)據(jù)庫中查詢。

而對于這種情況,我無論如何優(yōu)化總是得不到滿意的結果。如果我緩存這個排行呢,由于這個排行需要各種統(tǒng)計加排序,所以從數(shù)據(jù)庫中查詢出來后,還需要各種模型轉換,如果并發(fā)量上來,查詢再轉換,性能真的掉的飛快。

那時候,我的壓力非常大,腦子一直在想著性能問題,手上的 MySQL 手冊翻得都快爛的掉了頁。就連回到家睡覺時,眼睛閉上腦海里總是想著如何解決這些問題。

最終上線的時間不斷地逼近,手上的項目卻死死卡在這些性能難題上難以進展,競爭對手卻時不時聽到內(nèi)部競爭對手順利進行到某某程度的消息。

這一切的一切我快扛不住了,內(nèi)心勸自己放棄的聲音也越來越大。

我曾經(jīng)一度認為自己是一個韌性非常強的人,但是現(xiàn)在看來,其實也就是個再普通不過的打工仔而已。

我要逃避了,我想去和產(chǎn)品商量就這樣上線吧,我不想管了,是死是活看老天爺吧,賭對方也遇到我這種問題,甚至還不如我。

只是就在我準備拉上產(chǎn)品最終確定就這樣上線的時候,我內(nèi)心強烈的不甘阻止了我。我想在我放棄之前,無論如何要知道競爭對手怎么樣了,對方有什么方案和思路可供我參考的。

我找遍了我所有公司的熟人,去不停的打探競爭對手的消息。但是,結果并不好,因為對方比我做的更絕,他們進行了封閉式的開發(fā),而且警惕性非常高。

最終,我只得到了一個關鍵詞:CQRS。對方用 CQRS 來解決性能問題!!!

我年少讀書,那時還沒有手機,總是能一心一意的做好讀書這件事,讀書效率極高。但是如今有了手機,現(xiàn)在我再讀書,總是時不時會分心去看看手機里的信息,有時候為了好好把書讀進去,還不得不把手機特意丟在遠處,防止分心。

而 CQRS 就是這種思路。這個模式與其說是一種架構模式還不如說是一種思想。

CQRS 認為一套系統(tǒng)里的操作,總共就分為讀和寫兩大類。如果一套系統(tǒng)不專門把讀和寫專門分開優(yōu)化,那么系統(tǒng)就像我讀書帶著手機那樣,會一心兩用,從而因為彼此影響,導致各自的性能無法達到最優(yōu)。

所以,讀寫應該專門的分開,并分別優(yōu)化。

在 CQRS 里,寫這種行為被稱為命令,而讀行為被稱為查詢。因為想讓他們分開,所以 CQRS 模式中文翻譯過來就被稱為命令查詢權責分離模式。

我知道這套思路之后,本來并不在意,因為乍一看,這套東西其實和我采用的數(shù)據(jù)庫的讀寫分離是一樣的,就是把讀寫給分開。

但是,我的技術直覺告訴我,這些并沒有那么簡單。

在計算機的世界里,一個名詞不會無緣無故出現(xiàn),也不會無緣無故的開始流行。如果真的和數(shù)據(jù)庫的讀寫分離一樣,那直接叫數(shù)據(jù)庫讀寫分離就好了。一定有什么不一樣了。

我沒再滿足于中文的搜索結果了,我直接去了 Martin Flower 的網(wǎng)站看原始版本去了。然后,我發(fā)現(xiàn)了這樣一幅架構圖。

再結合他的原文我一下子明白了,是模型,模型的不同!

原來的數(shù)據(jù)庫讀寫分離確實把讀寫的這兩個行為分開了,但是它依然有一個重要的事情沒有做,那就是職責的分開。

什么叫職責的分開呢?就是讀寫雙方不要搞同一套模型。而數(shù)據(jù)庫讀寫分離的問題就在這里,它使用了同一個模型。

使用同一個模型在這里造成的問題是,這個模型由于既要考慮讀取數(shù)據(jù)不能太困難,也要考慮寫入數(shù)據(jù)不能太困難。

而這個恰恰就是違背了 CQRS 中的核心思想:讀寫徹底自由。

如果我們使用 CQRS 思想的話,假設寫入不需要關心讀取的問題,讀取數(shù)據(jù)也不用關心寫入的問題,那么雙方是不是可以徹底放飛自我了?

比如,寫入數(shù)據(jù)由于不需要考慮讀取,那我大可以使用 Json 格式,使用 XML 格式之類的非標準格式,甚至直接寫個日志都可以。而讀取數(shù)據(jù)則根本不需要考慮寫入的問題,我甚至可以弄成一個容易搜索的索引格式來。

而 CQRS 在我看來,正是解決卡死我的性能問題的靈丹妙藥。

以廣告排行這個問題為例,廣告排行麻煩就麻煩在,每次加載排行榜需要有很復雜的查詢,去數(shù)據(jù)庫中讀取數(shù)據(jù)。

如果能徹底地把排行榜的讀取和排行榜依賴的那些點擊、消費指標的更新分開,那我苦惱的排行榜性能問題就能迎刃而解。

我費勁心思后,仿照 CQRS 的原版思想搞了一個這樣的設計思路:

這里,數(shù)據(jù)統(tǒng)計就是廣告排名需要的點擊、消費等數(shù)據(jù)。這些數(shù)據(jù)會被放到一個單獨的數(shù)據(jù)庫中,這個數(shù)據(jù)庫只用來寫入,不考慮讀。

然后,展示廣告排行的功能本身又會單獨從緩存中把廣告排行的模型直接讀取出來展示出去,而不用專門再做什么轉換了。也不存在什么復雜查詢的問題。

但是,我們的需求是要準實時的讓廣告排行根據(jù)點擊、消費等數(shù)據(jù)自動更新,那么如果寫入數(shù)據(jù)和讀取數(shù)據(jù)模型分開了,該怎么辦呢?

多年以前,當我第一次在網(wǎng)上買東西的時候,心里有個疑問:我下了個訂單,賣我東西的商家是怎么知道的?莫非要一直盯著?

這個問題到我親自開發(fā)電商系統(tǒng)的時候才知道,當我們下單的時候,需要發(fā)一個通知給對應的商家,告訴商家哪個客戶購買了哪個商品。

所以,廣告排行自動更新的解決方案有了,和電商下單通知商家的道理一樣。當有數(shù)據(jù)寫入的時候,我們把寫入的數(shù)據(jù)復制一份通知給讀取數(shù)據(jù)的模型就可以了。

好,現(xiàn)在整套邏輯完整了。

但是,我并沒有急于馬上把 CQRS 這套模式去應用到實際的項目當中。因為,我發(fā)現(xiàn)我竟然不知道 CQRS 這套模式的缺點是什么。

要知道,世界上還不存在完美的解決方案,全都是既有優(yōu)點又有缺點的。而 CQRS 我竟然覺得很完美的解決了我的問題,這說明我對這套模式的認知還存在問題。

當時,離約定的上線時間已經(jīng)越來越近了,差不多還剩一周時間。我真的很想閉眼把方案實施下去。

但是,不行,我這個人做事向來喜歡把事情想得通透,把事物認知的十分清楚后再去做。

我決定冒險花兩天去實現(xiàn)兩個功能點,然后親自體驗一下引入 CQRS 的得與失。

兩天后,我終于發(fā)現(xiàn)了問題:引入 CQRS 的模式后,最大的問題在于引入了過度的復雜性。

由于需要讀和寫分開,那么我們開發(fā)的工作量無形中被加大了一倍。又引入 CQRS,這變得更復雜了。

因為我們發(fā)現(xiàn),不同的功能,只有使用不同的讀取或者寫入模型才能充分用上 CQRS 的優(yōu)點。

比如,廣告排行可能使用了緩存中間件去存取現(xiàn)成的排名。根據(jù)關鍵字搜索各種合適的廣告,可能就得考慮開源的搜索引擎中間件。每引入一種都會增加開發(fā)成本、服務器成本,以及更多的復雜度。

最終,我們的廣告系統(tǒng)按時上線了。

只不過,并沒有廣泛的采用 CQRS 模式,我只是把最重要的功能點用上了 CQRS,其余的有關性能的問題,我決定暫時放下。

之所以這樣,是因為我覺得大部分的問題,其實是我們過度設計引發(fā)的。即使因此我失敗了,我也認了。

我并不想為自己親手打造的系統(tǒng)埋下巨大的隱患,更不想給團隊帶來無謂的工作量,我不想卷成這樣。

上線后,我是如此忐忑,尤其是在上線運營的頭兩個月。

我不知道自己的妥協(xié)是否會誘發(fā)巨大的問題,我也不知道自己的所作所為是不是真的是對的。

兩個系統(tǒng)的競爭在上線兩個月后就有結果了。

這么快的得到結果,恰恰就是因為我的對手廣泛的使用了 CQRS 模式。

他從一開始設計的時候,就想著一鳴驚人,他的系統(tǒng)里引入了七八種中間件。把大量的功能拆分成了讀寫兩部分,而這引發(fā)了巨大的災難,過度的復雜性,導致整個系統(tǒng)難以控制。

其中最頭痛的就是,由于引入 CQRS,他們必須通過消息的傳遞去溝通讀寫兩套組件。

但是,當讀取組件收到消息后,卻發(fā)現(xiàn)寫入失敗了。導致用戶看到了對應的數(shù)據(jù)后,過一段時間,卻發(fā)現(xiàn)數(shù)據(jù)和以前看到的對不上了。

比如,點擊次數(shù),開始看到的是 1000 次,結果兩個小時后,發(fā)現(xiàn)變成了 999 次了。

這類問題每天都在出現(xiàn),而他們因為系統(tǒng)太復雜了,查問題、定位問題、解決問題的時間被大大拉長。最后,客戶們紛紛不干了,公司只好把客戶轉到了我這邊的平臺上。

競爭結束了,我勝利了,可是我真的無法高興地起來。因為今天他因為錯誤的引入新技術失敗了,那明天我又何嘗不會因為誤用新技術新思想而失敗呢?今日的他又何嘗不是明日的我?

愿天下程序員凡事深思熟悉,謹言慎行!

本文轉載自微信公眾號「四猿外」,可以通過以下二維碼關注。轉載本文請聯(lián)系四猿外公眾號。

 

責任編輯:武曉燕 來源: 四猿外
相關推薦

2021-05-19 10:09:23

消息隊列架構

2022-06-20 14:59:14

讀寫分離模Loki

2019-09-30 09:19:54

Redis分離云數(shù)據(jù)庫

2018-10-16 16:45:05

數(shù)據(jù)庫讀寫分離

2017-05-25 10:22:13

NoSQL數(shù)據(jù)庫主主備份

2021-03-26 08:20:51

SpringBoot讀寫分離開發(fā)

2023-07-07 08:36:45

配置注解jar

2022-04-25 08:03:57

MySQL中間件MyCat

2009-05-04 09:13:52

PHPMySQL讀寫分離

2017-09-04 09:53:58

MySQLAtlasNavicat

2020-04-23 15:08:41

SpringBootMyCatJava

2018-01-01 05:23:13

服務化讀寫分離架構

2010-05-17 11:19:44

MySQL proxy

2021-06-25 10:05:58

SpringBootMySQL數(shù)據(jù)庫

2025-02-26 12:19:52

2024-05-31 13:34:57

2023-02-01 07:34:41

讀寫分離數(shù)據(jù)庫

2020-02-28 19:06:21

緩存讀寫Redis

2011-08-30 12:49:59

Mysql ProxyLua分離

2021-09-08 10:23:08

讀寫分離Java數(shù)據(jù)庫
點贊
收藏

51CTO技術棧公眾號