项目名称:秒杀行动(达内项目峰会GF小组出品)
项目背景:高并发场景下的业务处理以及优化
项目描述:
前端:Thymeleaf+Bootstrap+JQuery
Thymeleaf:
Thymeleaf是网站或者独立应用程序的新式的服务端java模板引擎,可以执行HTML,XML,JavaScript,CSS甚至纯文本模板。
Thymeleaf的主要目标是提供一个以优雅的高可维护型的方式创建模板,为了达到这个目的,他建立了自然模板的概念,以一种不影响模板设计原型的方式将逻辑注入到模板文件中,可以显著的减少设计和开发之间的沟通成本。
在需要的情况下,Thymeleaf可以创建一个各种校验模式的模板(尤其是基于HTML5)
详情请见本博客Thymeleaf专题
Bootstrap(web框架):
Bootstrap是美国Twitter公司的设计师Mark Otto和Jacob Thornton合作基于HTML、CSS、JavaScript 开发的简洁、直观、强悍的前端开发框架,使得 Web 开发更加快捷。Bootstrap提供了优雅的HTML和CSS规范,它即是由动态CSS语言Less写成。Bootstrap一经推出后颇受欢迎,一直是GitHub上的热门开源项目,包括NASA的MSNBC(微软全国广播公司)的Breaking News都使用了该项目。国内一些移动开发者较为熟悉的框架,如WeX5前端开源框架等,也是基于Bootstrap源码进行性能优化而来。
详情请见本博客Bootstrap专题
JQuery(JavaScript框架):
jQuery是一个快速、简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScript框架)。jQuery设计的宗旨是“write Less,Do More”,即倡导写更少的代码,做更多的事情。它封装JavaScript常用的功能代码,提供一种简便的JavaScript设计模式,优化HTML文档操作、事件处理、动画设计和Ajax交互。
jQuery的核心特性可以总结为:具有独特的链式语法和短小清晰的多功能接口;具有高效灵活的css选择器,并且可对CSS选择器进行扩展;拥有便捷的插件扩展机制和丰富的插件。jQuery兼容各种主流浏览器,如IE 6.0+、FF 1.5+、Safari 2.0+、Opera 9.0+等。
详情请见本博客JQuery专题
后端:SpringBoot+MyBatis+Mysql
SpringBoot:
Spring boot是Spring家族中的一个全新的框架,它用来简化Spring应用程序的创建和开发过程,也可以说Spring boot能简化我们之前采用SpringMVC+Spring+Mybatis框架进行开发的过程。
在以往我们采用SpringMVC+Spring+Mybatis框架进行开发的时候,搭建和整合三大框架,我们需要做很好工作,比如配置web.xml,配置Spring,配置Mybatis,并将它们整合在一起等,而Spring boot框架对此开发过程进行了革命性的颠覆,抛弃了繁琐的xml配置过程,采用大量的默认配置简化我们的开发过程.
所以采用Spring boot可以非常容易和快速的创建基于Spring框架的应用程序,它让编码变简单了,配置变简单了,部署变简单了,监控也变简单了。
详情请见本博客SpringBoot专题
MyBatis:
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
中间件:RabbitMQ+Redis+Druid
RabbitMQ:
MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法。应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们。消息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如远程过程调用的技术。排队指的是应用程序通过 队列来通信。队列的使用除去了接收和发送应用程序同时执行的要求。其中较为成熟的MQ产品有IBM WEBSPHERE MQ等等。
详情请见本博客RabbitMQ专题
Redis:
redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
Redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客户端,使用很方便。
Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。
详情请见本博客Redis专题
Druid:
Druid首先是一个数据库连接池。Druid是目前最好的数据库连接池,在功能、性能、扩展性方面,都超过其他数据库连接池,包括DBCP、C3P0、BoneCP、Proxool、JBoss DataSource。
Druid支持所有JDBC兼容的数据库,包括Oracle、MySql、Derby、Postgresql、SQL Server、H2等等,并且Druid针对Oracle和MySql做了特别优化,比如Oracle的PS Cache内存占用优化,MySql的ping检测优化。
通过Druid提供的监控功能,监控SQL的执行时间、ResultSet持有时间、返回行数、更新行数、错误次数、错误堆栈信息,可以清楚知道连接池和SQL的工作情况,能够详细统计SQL的执行性能,这对于线上分析数据库访问性能有帮助。
详情请见本博客Druid专题
项目开始:
数据库表的设计: 数据库为miaosha
/*
MySQL Data Transfer
Source Host: localhost
Source Database: miaosha
Target Host: localhost
Target Database: miaosha
Date: 2018/12/4 14:18:42
*/
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for goods
-- ----------------------------
CREATE TABLE `goods` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '商品ID',
`goods_name` varchar(16) DEFAULT NULL COMMENT '商品名称',
`goods_title` varchar(64) DEFAULT NULL COMMENT '商品标题',
`goods_img` varchar(64) DEFAULT NULL COMMENT '商品图片',
`goods_detail` longtext COMMENT '商品的详情介绍',
`goods_price` decimal(10,2) DEFAULT '0.00' COMMENT '商品价格',
`goods_stock` int(11) DEFAULT '0' COMMENT '商品库存,-1表示没有限制',
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for miaosha_goods
-- ----------------------------
CREATE TABLE `miaosha_goods` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '秒杀的商品表',
`goods_id` bigint(20) DEFAULT NULL COMMENT '商品id',
`miaosha_price` decimal(10,2) DEFAULT '0.00' COMMENT '秒杀价',
`stock_count` int(11) DEFAULT NULL COMMENT '库存数量',
`start_date` datetime DEFAULT NULL COMMENT '秒杀开始时间',
`end_date` datetime DEFAULT NULL COMMENT '秒杀结束时间',
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for miaosha_order
-- ----------------------------
CREATE TABLE `miaosha_order` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) DEFAULT NULL COMMENT '用户ID',
`order_id` bigint(20) DEFAULT NULL COMMENT '订单ID',
`goods_id` bigint(20) DEFAULT NULL COMMENT '商品ID',
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=127 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for miaosha_user
-- ----------------------------
CREATE TABLE `miaosha_user` (
`id` bigint(20) NOT NULL COMMENT '用户ID,手机号码',
`nickname` varchar(255) NOT NULL,
`password` varchar(32) DEFAULT NULL COMMENT 'MD5(MD5(pass+固定salt) + salt)',
`salt` varchar(10) DEFAULT NULL,
`head` varchar(128) DEFAULT NULL COMMENT '头像,云存储的ID',
`register_date` datetime DEFAULT NULL COMMENT '注册时间',
`last_login_date` datetime DEFAULT NULL COMMENT '上次登录时间',
`login_count` int(11) DEFAULT '0' COMMENT '登录次数',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for order_info
-- ----------------------------
CREATE TABLE `order_info` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) DEFAULT NULL COMMENT '用户ID',
`goods_id` bigint(20) DEFAULT NULL COMMENT '商品ID',
`delivery_addr_id` bigint(20) DEFAULT NULL COMMENT '收货地址ID',
`goods_name` varchar(16) DEFAULT NULL COMMENT '冗余过来的商品名称',
`goods_count` int(11) DEFAULT '0' COMMENT '商品数量',
`goods_price` decimal(10,2) DEFAULT '0.00' COMMENT '商品单价',
`order_channel` tinyint(4) DEFAULT '0' COMMENT '1pc,2android,3ios',
`status` tinyint(4) DEFAULT '0' COMMENT '订单状态:0新建未支付,1已支付,2已发货,3已收货,4已退款,5已完成',
`create_date` datetime DEFAULT NULL COMMENT '订单的创建时间',
`pay_date` datetime DEFAULT NULL COMMENT '支付时间',
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=144 DEFAULT CHARSET=utf8;
三个版本中的所有类:
版本一:
- mybatis+redis+mysql完成基本秒杀功能
- 利用Jmeter进行高并发测试
- 问题1:并发量不高
- 问题2:数据库中数据异常----东西卖超了QAQ
版本二:
- 继承版本一的逻辑,对程序进行性能优化,完成秒杀流程
- 前端优化:
- 静态页面的缓存-----将静态html缓存到redis(无参数)
- url级缓存---------------将静态html缓存到redis(带参数)
- 对象级缓存------------将user对象永久缓存到redis(修改密码时修改)
- 接口优化:
- 利用redis预减库存来减少数据库的访问
- 通过添加内存标记减少redis的访问
- 请求秒杀之后先进入rabbitmq消息队列
- 解决卖超问题:
- 数据库sql中增加一个判断语句
- 利用Jmeter进行高并发测试:
- 并发量大幅度提升
- 数据库中数据正常
版本三:
- 继承版本二的逻辑,并对程序进行安全优化,完成秒杀流程
- 安全优化
- 秒杀接口的隐藏(秒杀请求前先验证)----防君子不防小人
- 图形验证码----防止用户频繁访问
- 接口限流--------防止恶意访问