1. 查詢模型的本質(zhì)
查詢模型的本質(zhì)就是:為不同的應(yīng)用場景選擇最合適的存儲引擎,充分發(fā)揮各個(gè)存儲引擎的優(yōu)勢。
在系統(tǒng)中,讀接口的數(shù)量遠(yuǎn)超寫接口,但我深信:==再簡單的寫也是復(fù)雜,再復(fù)雜的讀也是簡單。==
為什么呢?因?yàn)椋胱龊貌樵冎恍铻椴煌膽?yīng)用場景選擇最合適的存儲引擎,從而充分發(fā)揮底層存儲引擎的優(yōu)勢,然后所面對的高性能、高并發(fā)等技術(shù)問題就迎刃而解了。
如下圖所示:
面對一個(gè)查詢請求,我們需要:
接受并解析用戶請求;
從各個(gè)存儲引擎中獲取數(shù)據(jù);
對數(shù)據(jù)進(jìn)行加工,包括數(shù)據(jù)聚合、數(shù)據(jù)關(guān)聯(lián)、數(shù)據(jù)轉(zhuǎn)換等;
將最終結(jié)果返回用戶;
1.1. 常見存儲引擎的特征
技術(shù)選型唯一原則:==僅僅使用它的成名之作,萬萬不可被花里胡哨的東西干擾你的判斷。==
簡單列舉下常見的存儲引擎:
1.關(guān)系數(shù)據(jù)庫。
【特點(diǎn)】提供事務(wù)機(jī)制對數(shù)據(jù)強(qiáng)一致性進(jìn)行保障,其ACID四大特性更是建模利器;
【場景】適用于一致性要求高的金融或類金融場景,比如銀行、支付、訂單等;
2.Redis。
【特點(diǎn)】基于內(nèi)存的鍵值存儲引擎,具有高性能和低延遲;支持豐富的數(shù)據(jù)結(jié)構(gòu)(字符串、哈希、列表、集合、有序集合等)和功能(發(fā)布訂閱、事務(wù)等),提供豐富的持久化選項(xiàng);
【場景】:緩存、會話存儲、計(jì)數(shù)器、排行榜、分布式鎖等對性能和實(shí)時(shí)性要求較高的場景;
3.Elasticsearch。
【特點(diǎn)】全文搜索和分析引擎,建立在Lucene庫之上。擅長水平擴(kuò)展、近實(shí)時(shí)搜索、全文搜索和復(fù)雜查詢等功能;支持分布式架構(gòu)、自動分片和數(shù)據(jù)冗余;
【場景】日志分析、實(shí)時(shí)監(jiān)控、商業(yè)智能、搜索引擎、推薦系統(tǒng)等需要高效的實(shí)時(shí)全文搜索和分析功能的場景;
4.MongoDB。
【特點(diǎn)】面向文檔的NoSQL數(shù)據(jù)庫,以JSON風(fēng)格的文檔格式存儲數(shù)據(jù);支持動態(tài)模式、靈活的索引和復(fù)制集、分片等特性,可擴(kuò)展性好,支持水平擴(kuò)展;
【場景】大數(shù)據(jù)量、高寫入頻率、動態(tài)模式和靈活查詢的場景,如內(nèi)容管理系統(tǒng)、用戶個(gè)性化數(shù)據(jù)存儲、實(shí)時(shí)分析等;
1.2. 讀接口三把利器
對于查詢請求,主要有三種模式:
1.Query Object 模式。基于 Query Object 建模,完成對單引擎的快速查詢;
通過對 Query Object 對象建模,便可以對查詢條件進(jìn)行靈活管理;
無需寫 SQL,只需在 Query Object 上聲明好各種過濾條件,便能完成查詢。包括單條查詢、批量查詢、數(shù)量查詢、分頁查詢等
2.內(nèi)存 Join 模式。基于 View Object 建模,完成對結(jié)果數(shù)據(jù)的聚合操作;
通過對 View Object 對象建模,便可以對返回結(jié)果進(jìn)行靈活控制;
無需手寫關(guān)聯(lián)代碼,只需在 View Object 上聲明關(guān)聯(lián)關(guān)系,自動完成關(guān)聯(lián)數(shù)據(jù)的聚合;
3.異構(gòu)&冗余模式。
CQRS 思想的體現(xiàn),徹底的將寫模型和讀模型拆分開,從而最大限度的發(fā)揮存儲引擎優(yōu)勢;
異構(gòu)意味著冗余,冗余意味著數(shù)據(jù)不一致,該模式通過準(zhǔn)實(shí)時(shí)巡檢、天級對賬來保障數(shù)據(jù)的最終一致性;
三大模式綜合使用如下:
內(nèi)存 Join 模式,從遠(yuǎn)程服務(wù)、存儲引擎中獲取數(shù)據(jù),完成數(shù)據(jù)的聚合操作,然后對聚合數(shù)據(jù)進(jìn)行轉(zhuǎn)換,返回給用戶;
Query Object 模式,大大簡化對單引擎的查詢,讓你從繁重的 SQL(底層API) 中解放出來,大大提升開發(fā)效率;
異構(gòu)&冗余模式,方便構(gòu)建多副本異構(gòu)數(shù)據(jù)模型,完成最繁瑣的數(shù)據(jù)同步和數(shù)據(jù)一致性保障;
基于 Spring Boot + MyBatis Plus + Vue & Element 實(shí)現(xiàn)的后臺管理系統(tǒng) + 用戶小程序,支持 RBAC 動態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能
項(xiàng)目地址:https://github.com/YunaiV/ruoyi-vue-pro
視頻教程:https://doc.iocoder.cn/video/
2. Query Object 模式
這是最常見,也是應(yīng)用最多的模型,主要用于解決單引擎的數(shù)據(jù)查詢。讓開發(fā)聚焦于查詢建模,而不再是繁雜易錯(cuò)的技術(shù)細(xì)節(jié)。
我們以簡單的 MySQL 查詢?yōu)槔偃缡褂?MyBatis 作為系統(tǒng)的 ORM 框架,其核心流程如下:
首先,我們會定義一組查詢對象;
當(dāng)我們接收到參數(shù)后,把有效參數(shù)填充到 Example 對象;
然后,將 Example 對象傳入 MyBatis API 進(jìn)行查詢;
MyBatis 根據(jù) Mapper 配置,將 Example 對象轉(zhuǎn)換為對應(yīng)的 SQL 和參數(shù),并提交給 MySQL;
最終,MySQL 執(zhí)行 SQL 獲取并返回查詢結(jié)果;
仔細(xì)思考下,這里面是不是存在很多“固定邏輯”,而我們每天寫的代碼是不是有很強(qiáng)的“重復(fù)性”?
接下來看下面這張圖:
內(nèi)核和核心流程沒有變化,但上層 API 出現(xiàn)巨大變化:
1.首先,引入了 Query Object:
將分散的查詢參數(shù)封裝到一個(gè)類中;
在查詢對象的屬性上多了一組注解,用于聲明該屬性與數(shù)據(jù)庫查詢條件的關(guān)系;
2.然后,多了一個(gè)核心組件 MyBatisQueryRepository:
從 Query Object 上讀取屬性和注解信息,并完成對 Example 對象的填充;
使用填充好的 Example 對象調(diào)用 MyBatis API,從而完成數(shù)據(jù)查詢;
在該模式下,開發(fā) MyBatis 的單表查詢,只有一件事要做:按照業(yè)務(wù)要求對 Query Object 進(jìn)行建模。
當(dāng)然為了方便使用,QueryRepository 提供多種接口:
get:查詢單個(gè)對象;
listOf:查詢多個(gè)對象;
countOf:查詢數(shù)量;
pageOf:分頁查詢;
如對該部分感興趣,可研讀稍后文章。
該玩法支持復(fù)雜查詢嗎?
首先,不支持。對于復(fù)雜查詢,只能回歸到 MyBatis 底層 API。
【注】不要奢求一個(gè)框架或一個(gè)方案解決所有問題。使用 20% 的精力來解決 80% 的問題,那開發(fā)效率已經(jīng)得到極大提升。
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實(shí)現(xiàn)的后臺管理系統(tǒng) + 用戶小程序,支持 RBAC 動態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能
項(xiàng)目地址:https://github.com/YunaiV/yudao-cloud
視頻教程:https://doc.iocoder.cn/video/
3. 內(nèi)存 Join 模式
內(nèi)存 Join 等同于關(guān)系數(shù)據(jù)庫的 Join 語句,只是將 Join 動作從數(shù)據(jù)層提升到了應(yīng)用層。
其實(shí)我們每天都在寫這樣的重復(fù)代碼!!!
假如有一個(gè)需求,實(shí)現(xiàn)我的訂單接口,返回值里面需要包括 用戶信息(User)、收獲地址信息(Address)、商品信息(Product)等。而這些信息沒有在一個(gè)數(shù)據(jù)庫,甚至分散在不同的服務(wù),需要調(diào)用遠(yuǎn)程接口才能獲取到。由于無法使用數(shù)據(jù)庫的 join 語句,所以就出現(xiàn)了如下接口:
查詢我的訂單并將其轉(zhuǎn)換為 OrderDetail 集合:
獲取 User 信息,并填充到 OrderDetail 對象:
獲取 Address 信息,并填充到 OrderDetail 對象:
獲取 Product 信息,并填充到 OrderDetail 對象:
最后,返回填充好的 OrderDetail 集合;
仔細(xì)觀察上面的代碼,你是找到了“重復(fù)邏輯”?
如果,又要開發(fā)一個(gè)購物車列表呢?購物車列表和我的訂單是否存在重復(fù)邏輯?
思考完之后,請看 內(nèi)存 Join 模式:
可以看到:
大量繁雜冗余代碼被簡單的 @Join注解 取代
還可以開啟并發(fā)模型,使用多線程技術(shù)加快接口響應(yīng)速度
整體流程如下:
我們通過對 View Object 建模便能對返回?cái)?shù)據(jù)進(jìn)行控制,從而大大簡化對返回結(jié)果的開發(fā)成本。
如對該部分感興趣,可研讀稍后文章。
4. 異構(gòu)&冗余模式
異構(gòu)冗余模式,主要用于多存儲引擎的場景,旨在保障多存儲引擎間數(shù)據(jù)的一致性。
比如,在一個(gè)復(fù)雜的系統(tǒng)中,核心數(shù)據(jù)存儲于 MySQL,使用 Redis 進(jìn)行緩存加速,使用 ES 完成全文檢索。如何設(shè)計(jì)系統(tǒng),才能保障 MySQL 中的數(shù)據(jù)與 Redis、ES 的數(shù)據(jù)始終保持同步,從而實(shí)現(xiàn)最終一致性。
看似很簡單,但真正實(shí)現(xiàn)起來卻到處是坑,在深入思索后得出兩個(gè)特征:
存在決策節(jié)點(diǎn)并具備強(qiáng)順序性。按照決策節(jié)點(diǎn)給出的變更順序,依次在異構(gòu)引擎上進(jìn)行回放,便能實(shí)現(xiàn)兩者的最終一致性;
存在權(quán)威的“源信息”,發(fā)現(xiàn)不一致時(shí)可以使用源頭信息對數(shù)據(jù)進(jìn)行自動修復(fù);
從而,推導(dǎo)出該場景下的最佳實(shí)踐:
整體架構(gòu)分為如下幾部分:
索引:主要完成數(shù)據(jù)的構(gòu)建,從多個(gè)系統(tǒng)中拉取數(shù)據(jù)完成數(shù)據(jù)的裝配,并按所需結(jié)構(gòu)對數(shù)據(jù)進(jìn)行轉(zhuǎn)化;
巡檢:對系統(tǒng)中的數(shù)據(jù)進(jìn)行實(shí)時(shí)巡檢或定時(shí)對賬,發(fā)現(xiàn)系統(tǒng)中不一致的數(shù)據(jù)并完成數(shù)據(jù)的自動修復(fù)。如遇數(shù)據(jù)無法修復(fù)的場景,自動進(jìn)行報(bào)警,人工介入進(jìn)行處理;
查詢:充分發(fā)揮存儲引擎的優(yōu)勢,提供業(yè)務(wù)查詢能力,常與 Query Object 模式 和 內(nèi)存 Join 模式 結(jié)合使用;
通過對最佳實(shí)踐的封裝,可以在同一套組件、同一個(gè)數(shù)據(jù)模型基礎(chǔ)上,完成對 索引&更新、巡檢&修復(fù) 兩大流程的融合,大大降低研發(fā)工作量。
如對該部分感興趣,可研讀稍后文章。
5. 小結(jié)
查詢模型的本質(zhì)就是:為不同的應(yīng)用場景選擇最合適的存儲引擎,然后充分發(fā)揮各個(gè)存儲引擎的優(yōu)勢。
基于此提出三個(gè)模式:
Query Object 模式。通過 Query Object 建模,實(shí)現(xiàn)對查詢條件的靈活管理。無需寫 SQL,只需在 Query Object 上聲明好各種過濾條件,便能完成常規(guī)查詢。包括單條查詢、批量查詢、數(shù)量查詢、分頁查詢等;
內(nèi)存 Join 模式。基于 View Object 建模,實(shí)現(xiàn)對返回結(jié)果的靈活控制。無需手寫關(guān)聯(lián)代碼,只需在 View Object 上聲明關(guān)聯(lián)關(guān)系,自動完成關(guān)聯(lián)數(shù)據(jù)的聚合;
異構(gòu)&冗余模式。CQRS 思想的體現(xiàn),徹底的將寫模型和讀模型拆分開,通過準(zhǔn)實(shí)時(shí)巡檢、天級對賬來保障數(shù)據(jù)的最終一致性,從而最大限度的發(fā)揮存儲引擎優(yōu)勢;
-
接口
+關(guān)注
關(guān)注
33文章
8691瀏覽量
151911 -
多線程
+關(guān)注
關(guān)注
0文章
278瀏覽量
20071 -
模型
+關(guān)注
關(guān)注
1文章
3305瀏覽量
49217
原文標(biāo)題:DDD死黨:查詢模型的本質(zhì)
文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
電機(jī)的本質(zhì)運(yùn)行原理是什么
MATPOWER工具本質(zhì)原理是什么?
XML數(shù)據(jù)流基于組著色的XPath查詢模型
一種新的查詢意圖識別模型
![一種新的<b class='flag-5'>查詢</b>意圖識別<b class='flag-5'>模型</b>](https://file.elecfans.com/web1/M00/46/08/o4YBAFqPgI6AVzwuAABX3T9pvvQ014.jpg)
"Scalable, Distributed Systems Using Akka, Spring Boot, DDD, and Java--轉(zhuǎn)"
!["Scalable, Distributed Systems Using Akka, Spring Boot, <b class='flag-5'>DDD</b>, and Java--轉(zhuǎn)"](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
可從GraphQL查詢生成Java模型的Apollo HarmonyOS
用好DDD必須先過Spring Data這關(guān)
一文理解DDD領(lǐng)域驅(qū)動設(shè)計(jì)
![一文理解<b class='flag-5'>DDD</b>領(lǐng)域驅(qū)動設(shè)計(jì)](https://file1.elecfans.com/web2/M00/88/AC/wKgaomRu_sSAGwklAAATpzreM7w877.jpg)
DDD學(xué)習(xí)與感悟——向屎山?jīng)_鋒
![<b class='flag-5'>DDD</b>學(xué)習(xí)與感悟——向屎山?jīng)_鋒](https://file1.elecfans.com//web2/M00/07/AF/wKgZombyTo2AZoglAAGro_B2Gyo735.png)
在DVEVM上通過ddd運(yùn)行Demo
![在DVEVM上通過<b class='flag-5'>ddd</b>運(yùn)行Demo](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
評論