我選擇了MySQL和SpringData JPA

我是3y,一年CRUD經驗用十年的markdown程序員👨🏻‍💻常年被譽爲優質八股文選手

今天想跟大家聊聊數據庫層面上的事,austin項目繼續更新(:今天聊的數據庫都特指關係型數據庫)

01、數據庫選擇

之前發了一張我可能要在austin項目上引入哪些技術棧的圖,好多人問我分佈式配置中心爲什麼不選擇Nacos,而是用Apollo。卻沒人問我爲什麼數據庫選擇MySQL。

說起來MySQL,在網上看到的各類Java教程,幾乎都是使用MySQL作爲數據庫。日常在羣裏聊各種數據庫上的問題,也差不多都是MySQL,只有個別的可能用PostgreSQL和Oracle或其他

就連我在面試的時候,我也沒被面試官問過:“你的數據庫爲什麼選擇MySQL啊?這塊技術選型是怎麼樣的”

看到這裏,是不是覺得我有答案了?其實我也沒有。寫到一半的時候發現我也說不出啥比較好的理由...既然我不知道,於是我就去看看人家是怎麼說的。

https://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表

但是,我們在實際中生產環境中很有可能是不設計這種關聯表,而是直接把相關字段冗餘在一張表裏。這樣在查詢的時候,就能直接通過一張表查到對應的信息了,不用進行多層關聯

如果按上面的結構進行查詢:比如我要查到某一篇文章的作者基本信息,那我此時的動作是:

  1. 關聯author_content表查到文章的authorId
  2. 通過authorIdauthor表查到作者的基本信息

如果我把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_statusflow_id:模板在發送之前需要經過審覈(這在發送消息裏非常重要,這會很大程度上能防止對消息的誤發(相信大家也能看到各大公司都有過發錯消息的報道)

  • msg_type消息類型:分隔不同的消息類型,可以在下發時讓不同的類型走不同的通道進行實現消息隔離(營銷類的消息即便堵住了,也不會影響到通知類的消息)

  • send_account發送賬號:一個渠道內可能會有多個賬號發送(比如,郵件渠道可以選擇不同的郵件組進行發送、短信渠道可以選擇不同的短信類型賬號進行發送)

  • deduplication_timeis_ngiht_shield平臺規則:作爲發送類型的組件(平臺),需要有通用的規則。而去重和夜間屏蔽下發這種就很適合在平臺內做

  • msg_conteng:這個字段是作爲消息內容發送的核心,不同的渠道對應下發的格式都不一樣,我後面會直接將JSON存儲進去。支持佔位符的方式進行替換

  • ...

有可能後續還會擴展字段(畢竟在初期考慮設計表的時候,不會盡全盡美)。這種作爲模板或者理解爲配置的表,從使用上就註定它不會有很大的數據量。

下面來看下sms_record表吧,其實這表能說的不多(就是要把短信發送的記錄以及短信的回執存儲進去)。它的作用一方面是能追蹤到爲何發送給某個用戶的短信失敗了,另一方面是將這些記錄進行關聯做對賬使用。

06、總結

這篇文章其實想我聊的是:數據庫是一個很重要的角色,如果它掛了會影響很大很大。但同時,我們很多時候都是“輕量級”地去使用它(通過簡單的SQL),它的存在很多時候是因它能很好地支持事務(數據強一致性)。

我們最能夠信任的數據就是存儲在數據庫的,其他的存儲我們可能擔心會丟、會多、會不實時等等(這是數據庫比其他存儲的最大的優勢)

我說得不對一定,不要以我的爲準,我們可以在評論區聊

歡迎關注我的微信公衆號【Java3y】來聊聊Java面試,對線面試官系列持續更新中!

【對線面試官+從零編寫Java項目】 持續高強度更新中!求star!!原創不易!!求三連!!

Gitee鏈接:https://gitee.com/austin

GitHub鏈接:https://github.com/austin

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章