Marvel-Site Marvel-Site
首页
  • Java

    • Java基础
    • Java进阶
    • Java容器
    • Java并发编程
    • Java虚拟机
  • 计算机基础

    • 数据结构与算法
    • 计算机网络
    • 操作系统
    • Linux
  • 框架|中间件

    • Spring
    • MySQL
    • Redis
    • MQ
    • Zookeeper
    • Git
  • 架构

    • 分布式
    • 高并发
    • 高可用
    • 架构
  • 框架

    • React
    • 其他
  • 实用工具
  • 安装配置

    • Linux
    • Windows
    • Mac
  • 开发工具

    • IDEA
    • VsCode
  • 关于
  • 收藏
  • 草稿
  • 索引

    • 分类
    • 标签
    • 归档
GitHub (opens new window)

Marvel

吾必当乘此羽葆盖车
首页
  • Java

    • Java基础
    • Java进阶
    • Java容器
    • Java并发编程
    • Java虚拟机
  • 计算机基础

    • 数据结构与算法
    • 计算机网络
    • 操作系统
    • Linux
  • 框架|中间件

    • Spring
    • MySQL
    • Redis
    • MQ
    • Zookeeper
    • Git
  • 架构

    • 分布式
    • 高并发
    • 高可用
    • 架构
  • 框架

    • React
    • 其他
  • 实用工具
  • 安装配置

    • Linux
    • Windows
    • Mac
  • 开发工具

    • IDEA
    • VsCode
  • 关于
  • 收藏
  • 草稿
  • 索引

    • 分类
    • 标签
    • 归档
GitHub (opens new window)
  • Java

  • 计算机基础

  • 框架|中间件

  • 架构

    • 分布式

    • 高并发

      • 如何设计一个高并发架构
      • 讲座预约高并发方案
        • MQ + Redis 并发方案
        • 改进
          • 问题及改进方案
          • 其他改进
          • 高并发进一步解决
      • 分库分表
    • 高可用

    • 架构

  • 后端
  • 架构
  • 高并发
Marvel
2022-08-22
目录

讲座预约高并发方案

# 项目高并发介绍

草稿

# MQ + Redis 并发方案

两个微服务:

  • Order 微服务:从 Redis 中读取信息判断用户是否可以预约,当用户可以预约讲座时,将用户 id 和讲座 id 封装成一个对象发送到 MQ。

  • Lecture 微服务:监听 MQ,从 MQ 中获取用户 id 和讲座 id,将用户预约记录插入数据库并减少用户可预约讲座数量。同时更新 Redis 内的信息。

Redis:

  • 存储每一场讲座的开始预约时间,开始时间之后用户才可以预约。
  • 存储每一场讲座的剩余可预约数量,当可预约数量为 0 时就不可预约了。
  • 存储已预约记录,防止用户重复预约。

MQ:

  • 存储用户 id + 讲座 id 封装成的对象,根据这信息,消费者服务就可以更新 MySQL 和 Redis。

MySQL:

  • Lecture表:存放讲座的相关信息,包括剩余可预约数量。
  • Order表:存放用于的预约记录(user Id 和 lecture Id 构成唯一索引)

预约流程:

  1. 前端发送预约请求 nginx 反向代理到 Order 微服务
  2. 开始业务处理流程:
    1. 判断用户是否登录
    2. 从 Redis 内查询讲座预约是否开始或结束
    3. 从 Redis 内查询该用户是否重复预订讲座
    4. 递减 Redis 内该讲座的剩余可预约数量
    5. 将用户 id 和讲座 id 封装,发送到 MQ
  3. Lecture 微服务监听 MQ
    1. 发现 MQ 的队列中有消息就开始消费
    2. 开启事务
    3. 添加用户预约讲座记录
    4. 减少该讲座的剩余可预约数量
    5. commit

# 改进

# 问题及改进方案

🔶 问题1:MQ 积压情况下,重复预约

问题:当用户第一次预约,封装有用户 id 和讲座 id 的消息在 MQ 中没有被消费时,此时该用户又多次预约,这些预约信息会同样堆积到 MQ 中,导致 MQ 中出现无用的消息。并且,随着用户每一次的预约,Redis 内保存的可预约数量也会减少。

解决:当用户将预约记录发送给 MQ 的时候可以在 Zookeeper 内创建一个节点,表示用户正在预约,下一次用户再次预约的时候发现这个节点的存在,就不会在往 MQ 中发送消息了。

🔶 问题2:操作数据库失败,Redis 和 MySQL 数据不一致

问题:当 Lecture 微服务在操作数据库失败时,回滚事务后,需要将 Redis 内该讲座的剩余可预约数量 +1。因为在 Order 微服务内对该讲座可预约数量 -1,没有预约成功的时候要加回来。

🔶 问题3:预约之后无法立刻知道预约情况

问题:消息发送到消息队列中了,正常情况可以预约成功,但是如果发生意外,Order 微服务也不知道是否预约成功。

解决:使用 Zookeeper 做分布式协调,Zookeeper 中的节点表示正在预约,当该节点存在的时候,前端界面就一直 Loading,当 Zookeeper 中该节点消失就说明可以再次刷新用户预约状态。

# 其他改进

🔶 高并发读改进

之前解决的高并发问题都是针对于预约,其他一些常用查询也可以缓存到 Redis 里,所有的查询请求都是从 Redis 内查询,当 Redis 内不存在时再去请求 MySQL。当写请求修改讲座信息时,需要先删除 Redis 缓存内的数据,再更新 MySQL,保证 Redis 和数据库的一致性。(JVM 内部队列,保证更新数据或当获取 Redis 中不存在数据时会按队列内部串行执行)

🔶 静态资源缓存

预约开始之前会存大量的刷新请求页面资源。

页面资源访问多:需要考虑静态化,CDN,静态资源缓存及压缩

🔶 接口限流

  • 前端限流:隐藏、disable 按钮等方法
  • 同一个用户 10s 内只能请求预约操作一次,通过 redis 键过期策略,order:userId:lectuerId
  • 令牌桶算法,令牌桶算法的基本思路是每个请求尝试获取一个令牌,后端只处理持有令牌的请求,生产令牌的速度和效率我们都可以自己限定。

🔶 服务降级

当服务某个服务器出现宕机或服务不可用时,可以使用 Hystrix 进行熔断和降级,给用户一个友好的提示。

# 高并发进一步解决

系统拆分:将服务进一步拆分,每个服务到单独操作一类数据库。原本一个服务对应一个数据库,就变成了 n 个服务对应 n 个数据库,提高了并发量。

分库分表:一个数据库拆分成多个数据库,多个库分担压力;一个表拆分为多个表,提高 sql 语句性能。

读写分离:数据库搞主从架构,主库写入,从库读取,实现读取分离。

秒杀系统设计攻略 (opens new window)

编辑 (opens new window)
上次更新: 2023/08/20, 21:21:52
如何设计一个高并发架构
分库分表

← 如何设计一个高并发架构 分库分表→

最近更新
01
位运算
05-21
02
二叉树
05-12
03
Spring三级缓存解决循环依赖
03-25
更多文章>
Theme by Vdoing | Copyright © 2022-2024 Marvel
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式