每次上線都要加字段,走變更,如何破局?


大家好,我是架構擺渡人。這是實踐經驗系列的第六篇文章,這個系列會給大家分享很多在實際工作中有用的經驗,如果有收獲,還請分享給更多的朋友。

不知道大家有沒有遇到過類似的問題,每次新需求上線,或多或少都會有表結構的變更。主要就是需要新增字段來存儲某些特有需求的數據,聽起來其實很正常,新需求嘛,加字段,加表都是正常的,如果是傳統行業也沒啥太大問題。但是對於互聯網To C的應用來說,流量高,數據量大,每次對表進行DDL操作耗時都會非常長,主要是數據量太大了,而且都是分庫分表的,幾千張表都很正常。

用過MongoDB的都有一個很好的體驗就是不用再為加字段煩惱了,因為它沒有這個限制,每一條的數據格式都可以不一樣,也就避免的加字段帶來的煩惱,當然凡事有利也有弊,沒有限制也就意味着出錯的幾率會增加,你永遠不知道讀取出來的數據是什么格式。

通常我們為了盡量避免對現有的表結構進行加字段,都會有一些比較常用的方式來解決這個問題,下面就給大家介紹一些常用的方式。

預留擴展字段

預留擴展字段指的就是在創建表的時候,先預留幾個字段。如果后面需要使用直接就可以用了,也就是提前占個位子的意思。

CREATE TABLE `t_order` (
  `id` bigint(11) NOT NULL AUTO_INCREMENT,
  `orderNo` varchar(64) DEFAULT NULL,
  `buyerId` bigint(11) DEFAULT NULL,
  `storeId` bigint(11) DEFAULT NULL,
  `addition1` varchar(64) DEFAULT NULL COMMENT '擴展字段',
  `addition2` varchar(64) DEFAULT NULL COMMENT '擴展字段',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

當然這個也不是能夠處理所有情況,主要是你無法確定下一次需求到底需要加什么字段。比如你預留了一個varchar類型和一個int類型,如果后續需求都是要varchar類型的字段,那么int類型的將不能被使用。

存儲Json字符串

在建表的時候會設計一個比較長的字符串字段,比如叫addition。這個里面存儲格式就不再是某一個值了,而是一個Json字符串。這個就有點像Mongodb的感覺了,這樣的好處在於后續有需要要新增字段的就直接可以往里面放即可。

需要注意的是,什么類型的字段可以放在這個addition里面?就是只用於存儲和展示的,不用於條件查詢的數據,因為在Mysql 5.7之前是不支持Json類型字段的,存儲的就是一個普通的字符串而已。但是在5.7之后已經支持了Json類型的字段,這個時候里面的字段是支持查詢操作的。

擴展字段確實能夠解決大部分需求場景,但是問題在於隨着時間的推移,這個字段會越來越大。另一個問題就是當我的需求其實只需要讀取里面的某個值時,沒辦法做到部分讀取,只能全部讀取出來,然后轉成對象,取某個值,其實是比較耗時的。

比如訂單里面存儲了下單時的商品信息和用戶地址信息,如下:

addition={"sku":{name:"xxx",id:111},"addr":{"name":"xxx","city":"xxx"}}

當你要取商品信息的時候,沒辦法單獨讀取。

通用KV服務

最后介紹一個既比較通用又能支持無限存儲的方式,就是單獨實現一個KV服務來支持這種需求。

對於KV服務,核心接口無非就是下面幾個:

  • set(key, value)
  • batchSet(List<key,value>)
  • get(key)
  • list(key1, key2,keyn)
    底層存儲你可以使用任何數據庫進行存儲,用MongoDB,MySQL都可以。有了KV服務,就可以將addition里面的內容進行拆分,一個key對應一個value進行存儲,讀取也支持多個key或者單個key,按需讀取。

以上面訂單的需求來說,我們就可以將商品信息和用戶信息拆開存儲:

key=訂單號+sku
value={name:"xxx",id:111}

key=訂單號+addr
value={"name":"xxx","city":"xxx"}

當然這種通用的KV方式也不能解決搜索的問題,一般這種附加信息的存儲也是不會有搜索的需求,否則也不適合這種存儲方式。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM