我選擇了MySQL和SpringData JPA
- 2022 年 1 月 13 日
- 筆記
我是3y,一年CRUD經驗用十年的markdown程式設計師👨🏻💻常年被譽為優質八股文選手
今天想跟大家聊聊資料庫層面上的事,austin項目繼續更新(注:今天聊的資料庫都特指關係型資料庫)
01、資料庫選擇
之前發了一張我可能要在austin項目上引入哪些技術棧的圖,好多人問我分散式配置中心為什麼不選擇Nacos,而是用Apollo。卻沒人問我為什麼資料庫選擇MySQL。
說起來MySQL,在網上看到的各類Java教程,幾乎都是使用MySQL作為資料庫。日常在群里聊各種資料庫上的問題,也差不多都是MySQL,只有個別的可能用PostgreSQL和Oracle或其他
就連我在面試的時候,我也沒被面試官問過:「你的資料庫為什麼選擇MySQL啊?這塊技術選型是怎麼樣的」
看到這裡,是不是覺得我有答案了?其實我也沒有。寫到一半的時候發現我也說不出啥比較好的理由...既然我不知道,於是我就去看看人家是怎麼說的。
//www.zhihu.com/question/21793412/answer/32127410
總結原因可能是:
- 前期MySQL免費開源易用,從眾多廠商中硬生生搞出了生態。有了生態,很難就被幹掉了。(最主要的)
- 互聯網用MySQL就是用來存數據「低成本快速的數據存儲插入方案」,要求也相對沒那麼高(這條我後面會詳細聊聊)
- 很多時候對某技術選型並非是技術原因

而我,我只會MySQL。我在生產環境下只用過MySQL,當年我還是小白的時候接觸過Oracle,但現在也基本忘得差不多了。
很多時候對某技術選型並非是技術原因(我是懶狗,我承認了)。近幾年PostgreSQL很火,聽說很多地方都比MySQL要好,感興趣的小夥伴可以把austin項目的MySQL替換為PostgreSQL
對資料庫選型感興趣的大哥們也可以找點資料繼續查閱資料,也很歡迎在評論區輸出下自己的經驗,這種話題討論我覺得還是蠻有意思的。
跟著我一起做austin項目的小夥伴應該對關係型資料庫都有所了解了,這裡的基礎我就不展開講述了。對MySQL感興趣或者準備要面試的同學,可以看看我《對線面試官》系列的MySQL章節(在各大部落格平台中受到了不錯的回饋)
02、ORM框架選擇
記得幾年前我剛接觸資料庫和Java的時候,那時候要用JDBC連接資料庫來操作數據,我就很不解:明明我可以通過各種的資料庫客戶端就能對數據進行操作,為啥我要用JDBC,好麻煩啊!
至於為什麼會有這種疑問,我也不理解我當時是怎麼想的(哈哈哈哈)。後來想通了以後,也學習了很多在程式上「簡化JDBC模板」的姿勢(DBUtils/Hibernate/Spring JDBC/Mybatis/SpringData JPA)

我在生產環境中接觸過的都是Mybatis,但這一次我在asutin項目中決定使用SpringData JPA作為ORM框架。
03、使用資料庫的經驗
這兩年我是呆在互聯網公司上班的,我就來聊下我個人所接觸到的東西,分享下我的看法。
一般來說,每個業務團隊維護著自己的資料庫(一個業務團隊可能就有好幾個庫),當我們需要某一個團隊的相關數據時,團隊會提供對應的RPC介面給公司內部業務使用。
這意味著數據邏輯對調用業務方而言,是透明的(調用業務方不需要關注其他團隊資料庫的任何資訊,無論是資料庫表設計還是具體的欄位)。

這個好處是顯然地:要某團隊的業務數據,只要找到他們提供的介面就完事了。作為需求方,只需要調個介面就能拿到自己想要的數據。
回到資料庫內部存儲本身,我們會儘可能將表結構設計得更簡單:在很多情況下,都會放棄資料庫三大範式來設計表。
舉個很簡單又可能不太恰當的場景:一個作者可能會寫多篇文章(意味著多篇文章會屬於同一個作者) author:content(1:N)
那在初學的時候,可能有的教程會這樣設計:author表、content表、autor_content_mapping表

但是,我們在實際中生產環境中很有可能是不設計這種關聯表,而是直接把相關欄位冗餘在一張表裡。這樣在查詢的時候,就能直接通過一張表查到對應的資訊了,不用進行多層關聯
如果按上面的結構進行查詢:比如我要查到某一篇文章的作者基本資訊,那我此時的動作是:
- 關聯
author_content表查到文章的authorId - 通過
authorId去author表查到作者的基本資訊
如果我把authorId直接存到content表中,那就意味著少了去author_content表查詢了。
注:這裡我不是說讓你們把所有的資訊都存在一張表裡,一張表裡有上百個欄位,千萬不要誤會我的意思!

說起關聯,又有一個能聊的話題:是否join(這個話題我曾經在我的交流群中聊過,不過也是各抒所見吧)。我在以前公司接觸到的項目,在mapper.xml中都看不到join的身影,我寫join只在hive寫統計腳本的時候用到。
【強制】超過三個表禁止 join。需要 join 的欄位,數據類型必須絕對一致;多表關聯查詢時,保證被關聯的欄位需要有索引。
說明:即使雙表 join 也要注意表索引、SQL 性能。
喜歡用join的會告訴你:我寫join會讓程式碼變得更簡單。查數據太麻煩了,要查的數據會存到多張表裡,直接在用join的開發效率是最快的!

而我,我是支援在程式碼里寫業務邏輯的。所有都是單表查詢,在程式程式碼中對數據進行關聯(資料庫的JOIN能幹到的事,在程式上一定能幹得到)。這樣的好處就在於:SQL簡單,SQL易復用,SQL易優化
在絕大數情況下,我們的介面瓶頸都是來源於「資料庫」,而非應用伺服器。多JOIN且複雜的SQL是不好優化的,而簡單的SQL是比較好優化的,並且我認為程式邏輯往往都要比SQL更容易維護。

在我這兩年在互聯網公司中,關係型資料庫在我的認知里,它就是作為一個支援事務的存儲。如果我們存儲的數據對事務沒有要求的,可能壓根就不需要存儲至關係型資料庫中。
現在數據源可選擇的太多了,我們可以把數據存儲到Redis(記憶體資料庫)、Elasticsearch(搜索引擎)、HBase(分散式、可伸縮的大數據存儲)、HDFS(分散式文件系統)、clickhouse(OLAP存儲系統)等等等

基於上面這些背景下,我的查詢SQL就不會複雜,那麼Spring Data JPA不就很適合我了么?
04、開發之外的資料庫
去到有一定規模的公司,都會有資料庫相關的基礎建設,下面提下常見的基礎建設吧
一、DDL和DML都需要走工單
生產環境的資料庫理論都不能通過自己編寫介面在程式中修改(高危動作),需要修數據或者建表都需要經過工單系統審核(一般是資料庫負責人+DBA)
比如你提交建表申請,DBA會看你的表設計是否合理(是否有加索引等等)

二、DQL查詢線上數據需要許可權
我們要查詢線上的數據,一般都得申請庫的許可權,有了許可權之後在公司內網特定的頁面進行數據查詢(我們一般只需要查團隊內的數據,所以其實也還好,其他團隊的資料庫許可權是不開放的,要數據一般只能通過介面獲取)

三、程式上一般不直連資料庫(會有代理層)
一般只有線下資料庫可以通過ip直連,線上資料庫都會經過代理層(代理層可以做很多東西,包括監控鑒權分庫分表等等)

四、完備的監控告警
資料庫作為一個很重要的存儲之一(如果掛了是真的影響很大),會有完備的監控和告警。比如說執行SQL失敗的告警、執行慢SQL的告警等等,對資料庫的各種指標進行實時監控

05、austin建表DDL
如果有提前預習的同學,應該就知道在austin.sql下我放了兩張表的DDL。為了讓大家理解我在做什麼,我來解釋下這兩張表的DDL具體是什麼含義(為什麼我要建這兩張表)
從message_template這張表開始解釋吧,所有的欄位我都添加了注釋,應該還是比較容易看得懂的。

註:如果程式由於擴展導致資料庫注釋有落後,還是有必要更新下(造福後人)
我們需要讓所有的消息都有一個「載體」,這個載體說白了就是模板,模板是austin系統的基石(有了模板,才能做業務處理,才能溯源,才能數據統計,才能擴展出一整套的建設...)
下面聊下幾個可能大家有疑問的幾個欄位吧:
-
audit_status和flow_id:模板在發送之前需要經過審核(這在發送消息里非常重要,這會很大程度上能防止對消息的誤發(相信大家也能看到各大公司都有過發錯消息的報道) -
msg_type消息類型:分隔不同的消息類型,可以在下發時讓不同的類型走不同的通道進行實現消息隔離(營銷類的消息即便堵住了,也不會影響到通知類的消息) -
send_account發送帳號:一個渠道內可能會有多個帳號發送(比如,郵件渠道可以選擇不同的郵件組進行發送、簡訊渠道可以選擇不同的簡訊類型帳號進行發送) -
deduplication_time和is_ngiht_shield平台規則:作為發送類型的組件(平台),需要有通用的規則。而去重和夜間屏蔽下發這種就很適合在平台內做 -
msg_conteng:這個欄位是作為消息內容發送的核心,不同的渠道對應下發的格式都不一樣,我後面會直接將JSON存儲進去。支援佔位符的方式進行替換 -
...
有可能後續還會擴展欄位(畢竟在初期考慮設計表的時候,不會盡全盡美)。這種作為模板或者理解為配置的表,從使用上就註定它不會有很大的數據量。
下面來看下sms_record表吧,其實這表能說的不多(就是要把簡訊發送的記錄以及簡訊的回執存儲進去)。它的作用一方面是能追蹤到為何發送給某個用戶的簡訊失敗了,另一方面是將這些記錄進行關聯做對賬使用。

06、總結
這篇文章其實想我聊的是:資料庫是一個很重要的角色,如果它掛了會影響很大很大。但同時,我們很多時候都是「輕量級」地去使用它(通過簡單的SQL),它的存在很多時候是因它能很好地支援事務(數據強一致性)。
我們最能夠信任的數據就是存儲在資料庫的,其他的存儲我們可能擔心會丟、會多、會不實時等等(這是資料庫比其他存儲的最大的優勢)
我說得不對一定,不要以我的為準,我們可以在評論區聊
歡迎關注我的微信公眾號【Java3y】來聊聊Java面試,對線面試官系列持續更新中!
【對線面試官+從零編寫Java項目】 持續高強度更新中!求star!!原創不易!!求三連!!
Gitee鏈接://gitee.com/austin
GitHub鏈接://github.com/austin
