我選擇了MySQL和SpringData JPA

Java3y發表於2022-01-13

我是3y,一年CRUD經驗用十年的markdown程式設計師??‍?常年被譽為優質八股文選手

今天想跟大家聊聊資料庫層面上的事,austin專案繼續更新(:今天聊的資料庫都特指關係型資料庫)

01、資料庫選擇

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

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

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

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

https://www.zhihu.com/questio...

總結原因可能是:

  • 前期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專案】 持續高強度更新中!求star!!原創不易!!求三連!!

Gitee連結:https://gitee.com/austin

GitHub連結:https://github.com/austin

相關文章