美文网首页
秒杀系统

秒杀系统

作者: HamletSunS | 来源:发表于2019-07-26 19:37 被阅读0次

    Maven建立工程,管理jar包

    jar包依赖
    日志、数据库、数据库连接池(生疏点)、DAO相关、Servlet web相关、Spring系列

    DAO层的设计
    表结构设计、实体类的定义、DAO接口的定义,使用mybatis实现接口,spring实现IOC

    1. 秒杀业务分析

    <del>展示界面、需要的信息(库存、开始时间、结束时间)、业务逻辑(开始前倒计时、活动期间可以秒杀、结束后显示活动结束)、登陆注册、对高并发场景的处理</del>

    库存

    减库存、记录购买明细、完整事务、数据落地

    购买行为

    谁购买成功、购买时间与有效期、付款时间和发货信息

    事务的意义

    原子性,保证减库存后必然会记录购买明细,否则会发生多卖(记录、没减库存)或少卖的情况(减库存、没记录)

    数据落地

    mysql vs nosql(高可用、分布式,不支持事务)

    2. mysql实现秒杀功能的难点分析

    <del>同数据库建立连接比较消耗时间,qps低</del>

    并发处理秒杀行为时各个用户之间竞争访问数据库

    事务+行级锁
    会导致一个用户访问db时别的用户排队等待,变成串行操作,qps低

    3.实现哪些秒杀功能

    <del>对重复提交的秒杀的处理</del>
    秒杀接口的暴露 执行秒杀 相关查询

    4.代码开发阶段

    1. DAO层 设计编码
    2. Service层 设计编码
    3. Web层 设计编码

    整体梳理

    技术栈

    日志、数据库、数据库缓存池、Spring、SpringMVC、服务器、Redis

    项目结构

    DAO层、业务层、WEB层

    优化分析

    瓶颈点 -- 竞争(数据库的事务、行级锁)
    优化思路
    流量分流(动静分离、读写分离--redis缓存、接口隐藏减少流量、集群化处理、深度优化--减少行级锁占用时间、使用存储过程)

    秒杀页面优化(频繁刷新)
    CDN(Content Delivery Network)
    静态页面可以放在CDN上,动静分离,分流流量,较少服务器压力

    秒杀地址接口优化
    为什么秒杀API不能放CDN?
    因为CDN放的内容适合放不变化的,秒杀处理会导致数据变化,比如返回值,没开始、活动期间、活动结束的返回值是不同的
    适合放在服务端的Redis缓存服务器

    1. 单机10万QPS,集群可达百万QPS,适合处理高并发场景
    2. 一致性维护成本低(超时穿透、主动更新)

    秒杀操作优化
    难点:
    无法放CDN
    因为最核心的东西不能放CDN,大部分写操作都不会放CDN
    后端缓存也比较困难
    因为有库存的问题,若命中缓存即返回,可能不会及时更新数据库
    一行数据竞争问题
    MySQL事务机制、行级锁机制
    优化思路:深度优化 比如设计存储过程。减少行级锁占用时间

    其他方案分析:
    执行秒杀
    原子计数器(记录库存,Redis) --》 记录行为(消息队列) --》消费消息并落地(数据库库)
    优势:QPS高,性能好
    劣势:开发和维护成本很高,幂等性难以保证,技术难点高

    MySQL作为解决方案的分析

    • 性能低?
      一条update记录压力测试(4w QPS),性能其实还不错,但由于事务和行级锁机制,造成竞争,使得后续到达的减库存的更新操作被阻塞,必须等待当前事务被提交或回滚后才能获得锁,进行处理
    • 瓶颈分析
      update减库存的执行开销+网络延迟和GC开销、insert购买明细的执行开销+网络延迟和GC开销、commit或rollback执行后,后续请求才能获得锁,开始处理。因此会造成竞争和等待
      结论:MySQL本身性能还可以,但是Java客户端与数据库之间的通信会造成额外的开销导致性能不尽人意,再一个就是数据库处理请求时产生的竞争问题。
      容易疏忽的地方:数据库和Java客户端之间也是依靠网络连接建立的
      优化方向:
    1. 尽快的让事务提交或回滚,减少行级锁的占用时间
    2. update的处理逻辑由Java客户端转移到MySQL服务器上去执行,避免网络延迟和GC的影响
      如何实现2?
    • 定制化SQL,修改MySQL源码
    • 使用存储过程,使其在数据库服务器上执行而不是在Java客户端执行

    优化总结:
    前端控制:隐藏秒杀接口、按钮防重复
    动静数据分离:CDN、后端缓存
    事务竞争优化:减少事务锁的时间

    部署

    CDN WebServicer Redis MySQL


    DAO编码与设计

    • 工作内容:
      表结构设计、建立数据库和表
    • 定义model层:
      Entity实体类、DAO接口
      配置MyBatis,通过它的xml文件中的mapper实现DAO接口(MyBatis框架可以使我们只管接口,不负责实现)
    • MyBatis + Spring:
      更少编码(可以省略MyBatis API的编写)
      更少配置(配置文件扫描:自动扫描路径和包,只写文件名即可定位;DAO实现:MyBatis自动实现DAO接口,自动注入Spring容器)
      足够灵活(Mybatis可以定制SQL语句、自由传参、结果集自动赋值。XML提供SQL,另外,DAO接口Mapper)

    Spring的使用:

    • Spring-DAO.xml:
      1. (整合MyBatis):
        • 配置数据库连接属性文件
        • 配置数据库连接池
          -配置sqlSessionFactory对象(前两步注入的对象都是用来连接数据库的,第三步注入的对象才是整合MyBatis的)

    相关文章

      网友评论

          本文标题:秒杀系统

          本文链接:https://www.haomeiwen.com/subject/jntjrctx.html