如何进行系统设计 | 青训营笔记

82 阅读4分钟

这是我参与「第五届青训营」伴学笔记创作活动的第 8 天

如何设计

  1. 场景分析:

    什么系统需要哪些功能,多大的并发量

  2. 存储设计:

    数据如何组织(Sql,NoSql)

  3. 服务设计

    业务功能实现与逻辑整合

  4. 可拓展性

    解决设计缺陷,提高健壮性

通过以下三种方式可以对系统瓶颈进行分析:

  • 火焰图
  • 链路追踪
  • 性能测试

image-20230205174955263

保证系统可用性

设计秒杀系统

需求分析

秒杀系统需要涉及以下三个方面:

  • 消费者端
  • 商家端
  • 线上电商环境

而秒杀业务则具有以下几个特点:

  • 瞬时流量高
  • 读多写少
  • 实时性要求高

系统同时需要面对以下几种挑战:

image-20230205232213447

设计系统

而从上文所提及的四个方面对秒杀系统进行设计:

  1. 场景:

    • 功能:
      • 秒杀活动发布
      • 商品详情
      • 秒杀下单
    • 并发:
      • qps 1w+
      • TPS 1k+
  2. 存储:

    存储采用三层解决方案:mysql+redis+localcache

    image-20230205232529413

  3. 服务:

    将服务进行拆分,同时也包含服务需要的基础组件:

    • 服务
      • 用户服务
      • 风控服务
      • 活动服务
      • 订单服务
    • 基础组件
      • ID生成
      • 缓存组件
      • MQ组件
      • 限流组件
  4. 服务拓展部分:

    image-20230205232818935

image-20230205233916695

系统实现

为什么使用redis

秒杀系统,是典型的短时大量突发访问类问题。

而秒杀系统通常分为三个阶段,每个阶段redis的作用也不尽相同:

  1. 秒杀开始前

    在这个阶段,用户会不断刷新商品详情页,这会导致详情页的瞬时请求量剧增。这个阶段的应对方案,一般是尽量把商品详情页的页面元素静态化,然后使用CDN或是浏览器把这些静态化的元素缓存起来,将流量拦截在服务端外,减轻服务器压力,在这个阶段不需要使用redis

  2. 秒杀开始

    简单来说,这个阶段的操作就是三个:库存查验、库存扣减和订单处理。因为每个秒杀请求都会查询库存,而请求只有查到有库存余量后,后续的库存扣减和订单处理才会被执行。所以,这个阶段中最大的并发压力都在库存查验操作上。

    为了支撑大量高并发的库存查验请求,我们需要在这个环节使用Redis保存库存量,这样一来,请求可以直接从Redis中读取库存并进行查验。

    而在秒杀过程中,针对于订单操作我们应在数据库层面进行操作,而针对库存我们并不应该直接操作数据库

    • 当数据库进行库存更新时,需要对redis中的库存数据进行同步,这个过程增加了额外的操作逻辑,也带来了额外的开销。
    • 当过多请求直接修改数据库,由于对于行锁的争夺,数据可能并不能及时进行修改,从而导致下单量超过实际库存出现超售,而redis操作是单线程的,可以避免该问题的发生

    所以,我们就需要直接在Redis中进行库存扣减。具体的操作是,当库存查验完成后,一旦库存有余量,我们就立即在Redis中扣减库存。而且,为了避免请求查询到旧的库存值,库存查验和库存扣减这两个操作需要保证原子性。

  3. 秒杀活动结束后:

    在这个阶段,可能还会有部分用户刷新商品详情页,尝试等待有其他用户退单。而已经成功下单的用户会刷新订单详情,跟踪订单的进展。不过,这个阶段中的用户请求量已经下降很多了,服务器端一般都能支撑。而有关订单超时取消的部分,也可以利用mq进行解决

引用

部分内容来自: