最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

純異步事件驅(qū)動構(gòu)建的微服務(wù)體系

2023-08-25 20:13 作者:迷路idea  | 我要投稿

奇葩的需求

通常我們都只會記錄最后一次變更的狀態(tài),因為最終狀態(tài)是真實時間多數(shù)的需求。例如修改了用戶名,只會記錄最后修改的用戶名,通常還會加上修改時間和創(chuàng)建時間,就是我們多數(shù)常見系統(tǒng)的設(shè)計模式。 如果需求增加了:“用戶名不能和曾經(jīng)使用過的用戶名一致”,問題就來了。

如果不用常見的設(shè)計方案,會怎樣

修改用戶名,這個操作就是一次事件。事件是關(guān)于“發(fā)生了什么”的記錄,類似日志。但是與日志不同的是,事件還是事實的單一來源。因此,它們必須包含準(zhǔn)確描述所發(fā)生事件所需的所有信息。


事件驅(qū)動的解決方案

存儲

那如果我們不進(jìn)行update,直接存儲了原始完整的事件,也就是只記錄了日志,會怎樣? 數(shù)據(jù)庫里會有多條記錄,每次查詢都必須使用max(版本)取得最后記錄后才能拿到最準(zhǔn)確的信息。性能上不夠好,且產(chǎn)生了大量的冗余信息。 那如果不考慮存儲成本,也不考慮事務(wù),且有一種物化視圖,能夠全自動的從所有事件中自動取得最新版本,是不是就是最理想的狀態(tài)? 類似區(qū)塊鏈的運(yùn)行原理,沒有刪除和修改,只有新增,所有發(fā)生的事件都被完整存儲,測試、解耦、伸縮變得so easy

調(diào)用

如果我們向mq發(fā)出一個事件,但等待對此事件的一個回信(可能從另一個topic中),不考慮性能的情況下,本質(zhì)上來說就是一個普通調(diào)用了。 不需要服務(wù)發(fā)現(xiàn)也不需要負(fù)載均衡,每個調(diào)用都被完整記錄,且請求或返回數(shù)據(jù)的共享變得so easy。


同步調(diào)用的缺陷

  1. 解耦。無論是常見的服務(wù)發(fā)現(xiàn)還是dubbo式能力發(fā)現(xiàn),必須在知道被調(diào)用方的前提下才能執(zhí)行調(diào)用。至少需要知道被調(diào)用方的名稱和請求對象,才能準(zhǔn)確執(zhí)行調(diào)用。 這樣不夠“聲明式”,不夠解耦。

  2. 彈性。今天我們在k8s這樣的平臺上,似乎很少遇到彈性問題。深入細(xì)節(jié),長連接中的高qps依然無法分流,特別是在特殊協(xié)議中這種情況可能雪上加霜。

  3. 線上故障。沒打訪問日志?哭死。打了訪問日志?一個月激增10倍的日志成本

  4. 接口版本。多個 API 定義和服務(wù)版本通常需要同時存在。強(qiáng)制讓客戶端升級到最新的 API 并不總是可行或可取的。

  5. 測試。單元測試改動了數(shù)據(jù)怎么辦?基建層要不要做單元測試?


基于純異步事件驅(qū)動構(gòu)建的微服務(wù)體系

事件應(yīng)該是什么樣

準(zhǔn)確的描述是:包含唯一id的kv結(jié)構(gòu)數(shù)據(jù)

最佳實踐的格式:使用protobuf或apache avro,保持足夠的體積優(yōu)勢、反解析優(yōu)勢,利用現(xiàn)有的基建(例如proto工程化能力)

事件的設(shè)計

  1. 錯誤的設(shè)計:用戶名正在更新

  2. 正確的設(shè)計:用戶名更新為xxx 事件不能是處于中間狀態(tài),而且已經(jīng)完成,成為事實的事情。

  3. 怎樣定義“類型” 錯誤的設(shè)計:


id: 1 name: xxx admin_name: "" type: user


正確的設(shè)計:


id: 1 name: xxx --- id: 2 admin_name: xxx


不要使不同事件“合用”定義,如果是兩個類型,就定義2個事件。事件不需要和數(shù)據(jù)庫設(shè)計對等 3. 最小化事件 拿修改用戶名的事件舉例,事件中當(dāng)然需要包含用戶id和用戶名,但需要不需要包含用戶頭像等其他有關(guān)聯(lián)但并不是“有用的信息”?站在最佳實踐的角度上,不要包含此類信息。不僅會造成數(shù)據(jù)量變大,而且實際上也要校驗每次的“更新”是否對原始數(shù)據(jù)有修改,造成了額外的負(fù)擔(dān)

技術(shù)和中間件

  1. mq。常見的mq都可以完成。但是kafka這種有各種限制(消費(fèi)者數(shù)目不能大于分區(qū)數(shù)等),可能會導(dǎo)致整體服務(wù)性能或彈性能力不足。

  2. 落盤。根據(jù)數(shù)據(jù)類型的不同,有的數(shù)據(jù)需要實時落盤+事務(wù)做聚會,這種情況需要開發(fā)。如果不需要實時,比如”用戶名不能和曾經(jīng)使用過的用戶名一致“的場景,完全可以使用某些”奇葩“的方案,包括但不限于:

  3. 使用kafka connect把數(shù)據(jù)按照parquet格式寫入對象存儲,使用presto加載parquest進(jìn)行查詢。

  4. 使用帶有kafka抽取的數(shù)據(jù)庫(例如singlestore),直接抽取kafka數(shù)據(jù),自動落盤

老系統(tǒng)怎么辦

  1. 觸發(fā)器。使用觸發(fā)器拿到最新數(shù)據(jù),并發(fā)布在流中

  2. 數(shù)據(jù)庫日志。訂閱binlog并推送在流中,可能需要做相應(yīng)的轉(zhuǎn)化,因為一般數(shù)據(jù)庫的數(shù)據(jù)都有一定冗余,比如上面說的頭像信息

  3. orm攔截器。代碼層面的變更通知

  4. 定時掃描update_at。使用定時任務(wù)獲取變更事件并推送

有了事件流,然后呢

  1. 困擾多年的問題突然沒有了

  2. mysql如何同步redis

  3. mysql如何同步es

  4. 需求變化快?我變的更快。甚至無需修改原有代碼,訂閱事件結(jié)果,并直接使用事件覆蓋上一個事件,可以快速滿足需求,代碼屎山也可以輕松重構(gòu)。

  5. 海量數(shù)據(jù)+事務(wù)。打破傳統(tǒng)tp和ap天然的邊界(可能是兩個老死不相往來的部門),研發(fā)的思路可以不用總是局限在加索引這件事上

結(jié)尾

對于“傳統(tǒng)”研發(fā)團(tuán)隊而言,以純事件驅(qū)動架構(gòu)改造微服務(wù)是個過大的調(diào)整,會打破現(xiàn)有的多數(shù)認(rèn)知。我個人猜想敢于嘗試這只螃蟹的肯定不多。

但是有了這種打破常規(guī)的思路,在某些問題上可能就不那么會受到限制。對于某些“惡臭”的傳統(tǒng)設(shè)計,是否能夠在某些程度的突破一下邊界。在某些特定的、非核心的系統(tǒng)中,可以嘗試下使用新模式解決問題。



更多精彩內(nèi)容

我們?yōu)槭裁从钟钟钟中枰粋€新的mq了

小團(tuán)隊的實用云原生指南

jdk17的gc選擇

研發(fā)團(tuán)隊新鮮事兒,來公眾號「迷路idea」找我一起探討


純異步事件驅(qū)動構(gòu)建的微服務(wù)體系的評論 (共 條)

分享到微博請遵守國家法律
武邑县| 新化县| 昌吉市| 修文县| 昭觉县| 湘阴县| 宜兴市| 灯塔市| 科尔| 临武县| 镇原县| 灵台县| 澄迈县| 曲阳县| 喀喇| 来凤县| 铜鼓县| 宁陵县| 古浪县| 卢氏县| 石狮市| 瑞金市| 九龙城区| 竹山县| 谢通门县| 定襄县| 资溪县| 日喀则市| 横山县| 米林县| 垫江县| 江安县| 抚远县| 顺平县| 武川县| 高雄市| 清徐县| 蚌埠市| 麻栗坡县| 秦皇岛市| 泸水县|