6

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

 3 years ago
source link: https://www.cnblogs.com/jiagoubaiduren/p/15760589.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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

大家好,我是架构摆渡人。这是实践经验系列的第六篇文章,这个系列会给大家分享很多在实际工作中有用的经验,如果有收获,还请分享给更多的朋友。

不知道大家有没有遇到过类似的问题,每次新需求上线,或多或少都会有表结构的变更。主要就是需要新增字段来存储某些特有需求的数据,听起来其实很正常,新需求嘛,加字段,加表都是正常的,如果是传统行业也没啥太大问题。但是对于互联网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方式也不能解决搜索的问题,一般这种附加信息的存储也是不会有搜索的需求,否则也不适合这种存储方式。


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK