基础的认识

凡是那些特别难解决的、让你付出巨大代价的,或者损失惨重的技术问题,几乎都可以归结为存储系统的问题

存储是系统中最核心、最重要、最关键的组成部分,没有之一

MySQL、Redis、ElasticSearch、HBase、Hive、MongoDB、RocksDB、CockroachDB 等等,这些存储还真就是谁都替代不了谁,每一种都有它擅长的地方,有它适用的场景,当然也有很突出的短板。如何根据业务系统的特点,选择合适的存储来构建我们的系统,这也是需要学习和掌握的

如何保证数据准确无误

合格的订单系统,最基本的要求是数据不能出错

如何避免重复下单

  • 让订单服务具备幂等性
    • 任意多次执行所产生的影响均与一次执行的影响相同
    • 利用数据库主键的唯一性约束来解决创建订单服务的幂等性问题(自定义一个订单号生成的服务)

如何解决ABA问题

对数据的更新也要注意ABA问题

  • 什么是ABA问题
    • 一个简单的例子,假如有两次请求,第一次要求把数据修改为666,当数据库修改成功,在返回响应的时候失败了,而此时第二个请求到了,要把数据修改为888,并且响应成功了。由于第一次申请没有收到正确的响应,所以进行了重试,这时数据又修改成了666。
  • 怎么解决呢?
    • 给数据库表增加一列version,也就是版本号的意思,每次查询version都随着数据返回,再更新的时候把version作为更新请求的参数,发送给更新服务
    • 更新服务在接收到请求后,对比当前数据的version,是否与请求中的一致,如果不一致就拒绝更新。如果一致,就更新数据的同时把version+1。当前这个更新的过程必须在同一事务里面

商品详情页如何设计

商品都包括哪些信息

  • 基本信息
  • 商品参数
  • 商品介绍
  • 图片视频

  • 促销信息
  • 推荐商品
  • 评价信息
  • 评论信息
  • 配送信息
  • 店铺信息

商品基本信息如何存储

  1. 商品基本信息的主副标题、价格、颜色等基本、主要属性,都是固定的。数据量不大,建议在数据库中建一张表来保存商品基本信息。然后在数据库前面加一道缓存,基于内存的KV存储。
  2. 前置缓存缓存商品数据,读取请求流程:
    2.1. 先去缓存查找,如果找到就直接返回数据
    2.2. 如果没有找到就去数据库查询,把返回结果返回,并缓存一份到缓存
  3. 更新时,在更新数据库的同时也要把缓存给删除,来保证数据一致性(Cache Aside缓存更新策略)

设计商品信息表时,一定要记得保留商品数据的每一个历史版本

缓存更新策略
  • Cache Aside
  • Read/Write Through
  • Write Behind

商品参数如何存储

使用MongoDB保存商品参数,和商品的基本属性一样,都是结构化数据,不同类型的商品,它的参数也完全不一样。

MongoDB

MongoDB是一个面向文档存储的NoSQL数据库,在MongoDB中,表、行、列对应概念:Collection、document、field。
表结构是不需要事先定义,MongoDB没有表结构。支持把任意数据放在同一张表中。

MongoDB中的每一行数据,在存储层就是简单地转化成BSON格式。这是一种更紧凑的JSON,MongoDB 不支持 SQL,多表联查和复杂事务比较孱弱,不太适合存储一般的数据。对于商品参数信息,数据量大、数据结构不统一,这些 MongoDB 都可以很好的满足。我们也不需要事务和多表联查,MongoDB 简直就是为了保存商品参数量身定制的一样。

图片和视频如何存储

保存在对象存储中

对象存储

对象存储可以简单理解为一个无限容量的大文件 KV 存储,它的存储单位是对象,其实就是文件,可以是一张图片,一个视频,也可以是其他任何文件。每个对象都有一个唯一的 key,利用这个 key 就可以随时访问对应的对象。基本的功能就是写入、访问和删除对象。

商品介绍如何存储

商品介绍的文本,一般都是随着商详页一起静态化,保存在 HTML 文件中

Tomcat 能能抗的并发量和 Nginx 完全不是一个数量级的

商详页静态化之后,不仅仅是可以节省服务器资源,还可以利用 CDN 加速,把商详页放到离用户最近的 CDN 服务器上,让商详页访问更快。

商品系统的存储需要提供商品的基本信息、商品参数、图片和视频以及商品介绍等等这些数据。商品的基本信息和商品参数分别保存在 MySQL 和 MongoDB 中,用 Redis 作为前置缓存,图片和视频存放在对象存储中,商品介绍随着商详页一起静态化到商详静态页中。