[轉]後端開發如何設計數據庫

設計傳統系統表結構(Java開發)

以前經常能夠看到,數據庫範式,現在說數據庫三大範式的少了。

三大範式我以前也很嚴格的弄過,但是後來發現,還是靈活好啊,爲什麼,業務變動太快了啊,按照範式來,結構變更頂不住。

下面我就說一說設計數據庫表要注意的一些地方吧。我不是DBA,只是Java後端開發,以下是根據我的個人經驗所得,至於能不能體會,看個人了。

外鍵、觸發器

外鍵、觸發器不要有。
有了外鍵、觸發器,你會發現: 寫代碼不方便。 訂正數據不方便。 遷移數據也麻煩。 總之,你要是堅持用,後續的坑等着你。

自增id

數據庫表,一定要有id,而且要用自增id!
有些人喜歡用自定義的,用UUID或者其他七七八八的id,如果在架構設計,代碼比較好的情況下,不會出啥大問題,但是一旦代碼寫的不行,極有可能就造成id重複之類的問題。
自增id另外還有一個好處,就是在數據遷移的時候,分頁查詢通過id來進行分頁,速度會比傳統分頁快很多。

創建時間&修改時間

創建時間和修改時間這兩個字段,每個表都要有! 注意,一定要用數據的時間戳,自動生成。不要通過代碼去操作這兩個字段。

有了這兩個字段。你可以追溯到數據的時間點,創建和修改的時間點。極大方便你在某些情況下的排查數據問題。

創建人&修改人

建議每個表也有這兩個字段。

還是和前面一個原因,出問題的時候可以追溯起因,否則遇上日誌過久無法查看或者其他原因出現未知數據,都不知道數據怎麼來的,需要花非常大的代價查看日誌、代碼等。

大文本字段

一列需要佔很大空間的字段,一定要單獨拎出來,不要和常用信息放一張表。

舉個例子: 文章的信息和文章的內容,這一定要分成兩個表。否則會給你的文章性能帶來極大的挑戰。因爲很多情況下,查看文章列表,根本不需要查看到文章的內容。

表與表的關聯

表與表之間的信息,用id進行關聯,儘量不要有冗餘的信息數據,否則你需要更新同一份信息的時候,需要更新多個地方。

但是在某些情況下,你確認信息不會經常變動,且該信息確實在兩個表中都有會比較好,那麼,放心的去冗餘吧。但是注意,數據的更新用上事務。

單庫單表單系統寫原則

這個原則我自己想出來的,也就是說,數據庫中的一張表,只能有一個系統對其進行寫操作。 其他的系統如果想寫這張表,那麼經過調用這個系統的接口進行操作。

如果有多個系統寫同一張表,可能帶來的問題會很多。首先就是數據併發問題,其次就是事務問題,還有就是表結構變更問題,數據來源追溯問題等等。

如果誰有一張表數據想用多個系統來進行寫,那肯定是想把團隊拖垮。時間越久,債務越多!

總結

數據庫設計,標準其實是在變的,不變的只是思想。

業務場景不同,實際需求不一樣,不會存在一樣的設計,但是通用的思想都是一樣的,爲業務服務,爲未來服務,方便維護,方便擴展。

這條路很長,只能慢慢在路上體會了。

設計大數據量表結構

在大數據量的情況下,如何去提前設計這個表結構,來達到一個比較好的效果。對於團隊,對於後續的維護和擴展都帶來更大的便利。

自增id

自增id還是可以有,但是不是必須的了。但是建議還是每張表中有一個自增id。 爲什麼,還是那句話,做數據查詢,遷移,排序的時候,有着天然的一些優勢。

唯一標識

這個標識無論是token,還是其他例如訂單的訂單號或者其他唯一標識都行。 重點是唯一,不只是在單系統中唯一,而是需要在併發的情況,也能夠保持唯一。

關於分佈式id的生成方案,網上已經有很多了,這裏就不重複了。谷歌搜索搜索,自己看下原理,跑跑demo,能夠滿足自己業務的最大併發情況下的唯一即可。

比如說你未來幾年的最大併發也就是100,搞個能支持在幾千併發下不會出現標識重複的實現方案即可,併發幾萬,幾十萬,真的需要嗎?

後續如果真的能夠達到幾萬併發,那說明什麼?說明業務火爆了啊。難道還抽不出時間,抽不出人來做一個id生成方案的改造?這裏有比較重要的一點,不要太過超前設計,沒必要,也沒那個時間。

創建時間&修改時間

創建時間和修改時間還是要有的,而且建議時間精確到毫秒級別,在上一篇,我沒有說精確多少,那是因爲併發不高,秒級完全夠了。但是在大數據量的情況下,可能一秒有幾十、幾百、上千、上萬的數據新增都是有可能的。那麼秒級在這種情況下完全就不夠看了,選擇毫秒級別是一個比較好的選擇。

分庫分表

前面的唯一標識/創建時間可以說就是爲了這步準備的。

但是怎麼來設計分庫分表,選擇什麼方式,範圍還是hash,選擇哪個字段,還是選擇幾個字段。平滑遷移還是停機遷移。

這些都沒有唯一答案。只能是根據場景來區分不同的情況。下面舉幾個例子來進行一個講解,不是標準答案,同一個場景爲了滿足不同的需求,也可能有不同的一個設計。

1:支付訂單的場景

例如,訂單每日新增千萬級,那麼在這個情況下。我們還需要區分一下。

1.1 訂單號包含了時間戳

那麼強烈建議按照時間維度進行分庫分表。 也強烈建議在訂單號中將時間戳放進去。
優點:

單表的大小是可以預知的,一天多少訂單量,一個月多少訂單量
非常便於水平擴展,後期如果想對整個分片集羣擴容時,只需要添加庫表即可,不需要對已經存在的分片數據進行遷移。使用訂單號進行範圍查找時,可以快速定位查詢,避免了跨片查詢的問題。
缺點:

最近的訂單會存在着熱點數據,可以通過其他方式進行解決,例如緩存等

1.2 訂單號不包含時間戳

不包含時間戳,你可以選擇創建時間來做範圍分片。 或者使用訂單號來做hash分片,也就是取模運算分片。

hash分片的缺點就是後期擴容會涉及到老數據的遷移,但是現在有一種方案可以避免該缺點,那就是使用虛節點,先佔位,但不使用,需要的節點需要是2的次方個纔行。大家可以去網上了解一下,這裏就不展開了。 另外一個缺點就是跨片查詢的性能問題,當查詢條件中沒有訂單號的時候,會無法定位到數據庫表,所以會遍歷所有的庫表,進行查詢,再在內存中合併數據,取最小集返回,在這種情況下,分庫分表反而會成爲累贅。

其他一些分庫分錶帶來的事務問題大家可以看看現在的一些分佈式事務解決方案,都還挺不錯的。阿里的Seata可以瞭解一下。

最後,分庫分表,並不是一定要分庫的,也可以只分表,這樣很多分庫分表的問題就不存在了。 分庫分表還是要跟進實際的數據增長速度來評估,比如說,每年數據才幾十萬或者百萬,那麼沒有必要進行一個過渡設計,單表即可。等數據庫到了瓶頸,可以再考慮優化。

很多時候,瓶頸也不一定是在數據庫。

性能優化

在這裏,對於性能優化提一句,因爲自己也剛完成一個性能優化的需求不久,提升性能2倍左右。這次優化完全沒有動數據庫。 主要優化點在:同步方法異步調用第三方服務、計算異步處理、批量單次調用、部分不變數據緩存 重點:拿資源(空間、線程)換時間

總結

當數據量大了之後,其實很多設計和傳統的數據庫還是沒有很大變化的。

主要是要考慮到數據量大之後,該表如果分庫分表,那麼怎麼設計更加合理一點,也許當下不需要分庫分表,但是可以給以後少埋點坑。

但是注意,還是那句話,不要過度設計,也不要不去設計。簡單的說,可以預估到以後的業務每日數據量新增是萬級幾十萬以上的,就可以考慮下以後的分表,但是當期並不需要做。 但如果是日增百萬千萬級別,那麼這個分庫分表肯定是當期就需要進行的。 假如是日增幾百幾千的表,那麼就不要花過多時間去考慮什麼分庫分表的方案了,真的用不上。

建議的一個提前思考時間,1年左右的思考維度設計比較好。即不會超前,也不會因爲迭代了一兩次業務就有人提出,不知道哪個**設計的結構,又得重新來設計。

最後,能夠在技術方案時就明確的事情,絕不留到寫代碼的時候再去明確! 技術方案越清晰(注意:不是說超前設計,這裏面有個度,只可意會不可言傳),寫代碼越輕鬆,團隊協作越流暢。

設計SaaS系統表結構

在公司做了一年的SaaS內核系統,但是有些東西不知道能不能透露出來。我儘量在不透露一些敏感東西的情況下(這個度我無法把控,只能是籠統了),將某些關於數據庫方面的精髓傳遞出來。如果表達不暢,請諒解。

前面的兩篇講解了在傳統系統和大數據量下的數據庫設計應該注意的事項。

接下來需要換一種思路,在SaaS系統中,數據庫應該如何進行設計。

與傳統開發的思考點不同,在SaaS中,可能更多考慮的是數據隔離(在這裏考慮共享數據庫,共享數據表),數據通用方面

租戶id

既然是SaaS平臺,那麼肯定是多租戶的一個生態。那麼在數據庫層面,一定要有一個字段來隔離數據。

這個字段在每個表都需要有,且每一次數據庫的操作都需要有該字段作爲條件。

這一步數據安全的控制都放在了代碼中,所以安全性和隔離性都是要依賴編碼的。

表的自增id

這個字段還是要有的,但是強烈建議不要在刪除行數據,查詢數據,修改數據時使用到該字段,因爲該字段的單獨操作會破壞掉數據的隔離性。也就是前面所說的,所有的sql操作,都要帶上租戶id再進行。

數據來源標識
作爲SaaS平臺,在很多情況下,不同的租戶可能有一樣的數據,或者是通過某些編程,或者是通過配置的方式,通過一套標準數據生成了各個租戶的數據。可以實現租戶的自定義。

但是在某些情況下,可能某個特性不需要租戶進行自定義,而是SaaS系統進行一個控制,那麼就需要一個標識,來知道這個數據來源一致。

需要確定的是,這個標識,在這個租戶下是唯一的。也就是說,前面的自增id沒有用,但是這個標識和租戶的id是可以唯一索引到一條數據的。

強烈建議使用租戶id和數據的來源標識進行操作數據。

元數據

元數據用一句話就是描述數據的數據

在SaaS中,存在着一些通用配置,通過這些通用配置,可以自由定義一些業務模型,可以極其快速的實現業務需求。

這個元數據,我正在公司負責這塊,但是可能不能透露。

簡單的說幾句,元數據能用非關係型數據庫就不要用關係型數據庫。前期量級小的時候問題,後面訪問量,壓力很大。

其次,通用的一些業務模型,一定要抽取出來。元數據對業務來說是極其基礎的存在的,業務不應該感知到元數據的存在。業務感知的應該是元數據的一些業務組合,也就是業務模型。

通過組裝業務模型,可以配合不同的業務場景,最後實現業務功能。

租戶數據

租戶的數據,是基於一些元數據來生成的,所以是可擴展的。在這裏,也建議不要使用關係型數據庫,因爲不太適合,非關係型數據庫更加適合SaaS系統這個體系。

其實東西很多,但是暫時先講到這了,我也不知道某些東西是不是屬於公司的,前些日子我們公司剛爆出了員工透露公司機密到網上,所以。。。

最後講下吧,如果要做SaaS系統,一定要考慮長遠,不要先被業務拖累。如果在半年一年內無法脫離業務需求來架構設計與開發SaaS系統,那麼我的建議是,不要做什麼SaaS了,開發業務吧,不然公司都活不下去的。

整篇看上去會比較理論,但是實際上,這些都是實踐後的一些理論點。有很多的一些東西,我無法分享太多,非常抱歉。這次也是借這個阿里雲活動的機會,分享一點出來。

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