数据库设计 - 反范式冗余

What

大学里面学习数据库的时候,要求都是要按照三范式设计。但是在互联网高并发大数据量的场景下,往往要反范式设计。

Why

因为反范式的好处是可以通过冗余存储来减少计算。

How

引入一个例子:订单业务举例

  1. 订单业务
    Order(oid, info_detail)//订单主表
    T(buyer_id, seller_id, oid)//买家,卖家关系表
  2. 数据量大怎么办?
    水平切分
  3. 如何水平切分?如何满足查询?
    Order -> oid
    T -> buyer_id, seller_id?
    订单主表很容易切分(对oid进行取模即可),可是关系表T怎么办,如果按照买家的话,买家的读问题(只需要读一个库)是解决了,可是卖家读问题(需要读取多个库)解决不了。
  4. 解决方案:冗余表
    解决什么问题?
    a. 数据量大
    b. 需要水平切分
    c. 一个schema上有多个字段的查询需求
    怎么解决?
    • 数据库层面:
      a. Order(oid, info_detail)
      b. T1(buyer_id, seller_id, oid)//买家读取数据的时候读这个表
      c. T2(seller_id, buyer_id, oid)//卖家读取数据的时候读这个表

    • 服务层面:
      方案一:服务同步冗余
      在这里插入图片描述
      方案二:服务异步冗余
      在这里插入图片描述
      方案三:线下异步冗余:通过监控binlog日志(比如阿里的canal)
      在这里插入图片描述

    • 正表,反向标,如何确定操时序?比如新增一个订单是先insert T1表还是insert T2表
      此问题延伸为:对于一个不能保证事务性的操作,“哪个任务先做,哪个任务后做”?
      方法论:如果原子性被破坏,不一致出现,谁先做对业务的影响较小,就谁先执行。

      比如对T1和T2来说,如果先操作T1,那么买家是可以立即看到自己的订单,但是可能存在风险操作T2的时候没有成功,即卖家看不到这笔订单,影响程度较小;如果先操作T2,卖家可以立即看到自己的订单,但是可能存在风险操作T1的时候没有成功,即买家看不到这笔订单,影响程度较大(作为一个To C的应用,怎么能忍受C端的不良体验呢?)。所以最终的方案就是先执行T1,然后再操作T2。

    • 如何保证一致性?
      方法论:最终一致性
      方案一:全量数据扫描:这个方案比较稳,可以作为兜底的方案,缺点是比较慢,难以做到实时性,一般一天做一次。
      在这里插入图片描述
      方案二:增量日志扫描:速度快,大部分场景用这个方案即可,可以一个小时做一次。
      在这里插入图片描述
      方案三:实时消息对检测:实时性最好,可以做到秒级别,除非是一些支付等对实时性要求高的,可以考虑这个方案。
      在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/hudmhacker/article/details/108573169