• 购物网站和秒杀系统实现技术


    我们需要两个模块,一个后台Admin模块,一个前台Home模块,利用ThinkPhp框架,自动生成MVC框架如图6-2所示。

     

    任何一个表单的操作,都需要前端验证和后台验证,前端验证是为了用户体验,使用javascript,后台验证是为了数据的完整性,使用php,最好的方法,是结合二者,就是ajax了。图片上传的部分,使用tp自带的上传类。

    6.3 秒杀系统

    秒杀系统其实是针对库存做的系统。用户成功秒杀商品,对于我们系统的操作就是减库存和记录用户的购买明细。用户的购买明细包括记录谁购买成功、购买成功的时间和付款信息。而对于减库存操作,需要考虑到以下两个问题:

    (1)若是用户成功秒杀商品,我们记录了其购买明细,却没有减库存。会导致商品的超卖。

    (2)减了库存却没有记录用户的购买明细,导致商品的少卖。

    对于上述两个问题,可以通过MySQL内置的事务机制进行处理,它可以准确的帮我们完成减库存和记录用户购买明细的过程。

    对于秒杀系统,我们只是实现秒杀的一些功能:

    (1)秒杀接口的暴露。

    (2)执行秒杀的操作。

    (3)相关查询,比如说列表查询,详情页查询。

    秒杀系统包括包括三个模块的设计,DAO层、Service层和Web层的设计,另外考虑到系统高并发的问题,从而设计了系统高并发的处理。在系统设计之前,为了更好地理解系统的开发过程,对相关技术进行描述。

    6.3.2 相关软件包安装

    用Maven创建我们的项目seckill,然后使用IDEA打开该项目。在 main包下进行我们项目的代码编写及相关配置文件,test包下进行我们项目的测试。

    秒杀系统的servlet版本为3.1,相关的第三发jar包通过pom文件添加,

    6.3.2 DAO层

    首先需要创建秒杀库存表和秒杀成功明细表,如下所示:

    基于MyBatis来实现我们设计的Dao层接口。首先需要配置我们的MyBatis,在resources包下创建MyBatis全局配置文件mybatis-config.xml文件。

    配置文件创建好后我们需要关注的是Dao接口该如何实现,mybatis为我们提供了mapper动态代理开发的方式为我们自动实现Dao的接口。在mapper包下创建对应Dao接口的xml映射文件,里面用于编写我们操作数据库的sql语句,SeckillDao.xml和SuccessKilledDao.xml。

    MyBatis和Spring的整合,整合目标:

    (1)更少的编码:只写接口,不写实现类。

    (2)更少的配置:别名、配置扫描映射xml文件、dao实现。

    (3)足够的灵活性:自由定制SQL语句、自由传结果集自动赋值。

    在spring包下创建一个spring-dao.xml,用于配置dao层对象的配置文件,在resources包下创建jdbc.properties.xml,用于配置数据库的连接信息,配置如下。

    6.3.3 Service层

    在Dao层我们只完成了针对表的相关操作,包括写了接口方法和映射文件中的sql语句,并没有编写逻辑的代码,例如对多个Dao层方法的拼接,当我们用户成功秒杀商品时我们需要进行商品的减库存操作(调用SeckillDao接口)和增加用户明细(调用SuccessKilledDao接口),这些逻辑我们都需要在Service层完成。Dao层只进行数据的访问操作,接下来我们便进行Service层代码的编写。秒杀Service接口设计如下:

    (1)创建service包用于存放我们的Service接口和其实现类。

    (2)创建exception包用于存放service层出现的异常,例如重复秒杀商品异常、秒杀已关闭等异常。

    (3)创建dto包作为传输层, 用于完成web和service层的数据传递。

    (4)创建entity包用于业务数据的封装。

    在dto包中创建Exposer.java,用于封装秒杀的地址信息。SeckillExecution.java,用于判断秒杀是否成功,成功就返回秒杀成功的所有信息(包括秒杀的商品id、秒杀成功状态、成功信息、用户明细),失败就抛出一个我们允许的异常(重复秒杀异常、秒杀结束异常)。

    然后需要在exception包下创建我们在秒杀业务过程中允许的异常,RepeatKillException.java用于处理重复的秒杀异常;SeckillCloseException.java用于处理秒杀关闭异常;SeckillException.java用于处理秒杀相关业务的异常。

    在实现类SeckillServiceImpl.java中,我们用枚举的方式将异常函数中返回的常量进行封装,在enums包下创建一个枚举类型SeckillStatEnum.java,用于返回state和stateInfo这两个参数的相关数据。

    使用Spring托管Service依赖配置:

    在spring包下创建一个spring-service.xml文件,然后采用注解的方式将Service的实现类加入到Spring IOC容器中,然后在Service实现类的方法中,在需要进行事务声明的方法上加上事务的注解,配置如下。

    6.3.4 Web层

    秒杀系统Web层主要涉及前端交互设计、Restful:url满足Restful设计规范、Spring MVC、bootstrap+jquery这四个方面的开发。秒杀系统的前端交互流程设计如下图6-3所示。

     

    图6-3 前端交互流程

    整合配置Spring MVC框架:

    在web.xml中进行我们前端控制器DispatcherServlet的配置,配置springMVC需要加载的配置文件spring-dao.xml,spring-service.xml和spring-web.xml,详细配置如下。

    完成Spring MVC的相关配置后,接下来就要基于Restful接口实现项目中的Controller开发。Controller中的每一个方法都对应我们系统中的一个资源URL,其设计应该遵循Restful接口的设计风格。在web包下创建一个SeckillController.java,内容如表6-11所示。

    json数据的一个Vo类,即SeckillResult.java,在dto包中创建它,内容如下。

    6.3.5 高并发的优化

    秒杀系统面临着如下问题:

    (1)无法使用cdn缓存,因为系统逻辑不可能放在cdn中。

    (2)后端缓存困难:库存问题,因为运用到了mysql事务操作(设置联合主键)。

    (3)一行数据竞争:热点商品,因为多个用户同时对数据库某条数据进行操作。

    秒杀系统的优化方案:

    (1)前端控制:暴露接口,按钮防重复提交。

    (2)动静态数据分离:cdn缓存,后端Redis缓存。

    (3)事务竞争优化:减少事务锁时间,把客户端逻辑放在mysql服务端,避免网络延迟和GC的影响。 GC(Garbage Collection)垃圾回收机制

    使用Redis优化地址暴露接口,在dao包下新建一个cache包,然后创建一个RedisDao.java函数,在spring-dao.xml中配置redisdao构造器。

    针对网络延迟和GC导致的并发问题,使用存储过程,将整个事务放在mysql端完成,秒杀存储过程实现如下。

    最后,在ServiceService.java中建立存储执行秒杀操作的函数,在SeckillDao.java实现该接口,在SeckillDao.xml中使用mybatis调用存储过程,在服务端的SeckillServiceImpl.java完成配置即可。

  • 相关阅读:
    HTTP与HTTPS的区别
    Linux内核结构体--kfifo 环状缓冲区
    POSIX 线程详解
    linux的fork()函数-进程控制
    HDU 3435 A new Graph Game(最小费用最大流)&HDU 3488
    Memcached安装使用和源代码调试
    结构-01. 有理数比較(10)
    Android:你不知道的 WebView 使用漏洞
    关于文件异步上传
    <二代測序> 批量下载 NCBI sra 文件
  • 原文地址:https://www.cnblogs.com/smuxiaolei/p/7542903.html
Copyright © 2020-2023  润新知