背景描述
最近工作处理到一个需求:大概要求如下,我们之前在Mongo中存储了三个表,分别是
orders
订单表,一张总表描述各个订单
order_items
订单项表,描述每个订单的明细
products
产品表,用于存储订单中的商品明细和商品信息。
但其实这几张表是有关联的,每个订单的 order_items
和 products
信息其实都可以存储到 orders 这一张总表中
于是现在需求就是:将 order_items
和 products
合并到表 orders 中
方案一:直接读写新表
优点:一次性将写和读的逻辑替换过来,写直接写新表,读直接读新表,业务代码不需要考虑兼容性
缺点:因为我们线上的服务是同时读写这几张表的,所以如果直接修改业务逻辑将 order_items
和 products
这两个表的读写操作全部替换成对 orders 的读写操作,则上线过程中小流量观测阶段如果有请求打到了小流量实例,则查询操作只有当请求再次打到小流量实例才能查询出来,否则查询不到,因为线上的全流量实例还在读旧表,但是新的数据又没有写到旧表中
所以这种方案本质上是会对业务有影响的
方案二:双写旧表和新表
双写的优点:
- 1.2 版本只新增对新表的写入,但是不读,所以对原有的业务逻辑无影响;但是双写只是将新产生的数据写入到新表中,但是在旧表中的数据我们仍然需要迁移到新表中,这里可以考虑使用 cronjob 来执行这种一次性任务
- 1.3 版本再将原有的读逻辑替换过来,但是这时对旧表写的逻辑还需要照常保留,因为1.2旧的服务还是在读旧表,这样1.3上线过程中如果去掉对旧表的写的逻辑,则在上线过程中产生的新的数据旧的实例会无法读出来,因为写入到了新的表中
- 1.4 版本将旧表的写操作逻辑移除
- 这种方案适合QPS比较高的业务,这种迁移方式对业务几乎没有影响
缺点:上面方案要发布好几个版本,增加冗余代码适配双写或者双读的逻辑
总结
数据库的选型最好一开始就选型好,每种数据库都有每种数据库的特点,不建议中途替换数据库,这样对业务逻辑和代码逻辑几乎都要做非常大的变化