CREATE TABLE `t_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=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;
CREATE TABLE `t_order` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '订单ID',
`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=InnoDB AUTO_INCREMENT=5687 DEFAULT CHARSET=utf8mb4;
CREATE TABLE `t_seckill_goods` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '秒杀商品ID',
`goods_id` bigint(20) DEFAULT NULL COMMENT '商品ID',
`seckill_price` decimal(10,2) DEFAULT '0.00' COMMENT '秒杀价',
`stock_count` int(10) DEFAULT NULL COMMENT '库存数量',
`start_date` datetime DEFAULT NULL COMMENT '秒杀开始时间',
`end_date` datetime DEFAULT NULL COMMENT '秒杀结束时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;
CREATE TABLE `t_seckill_order` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '秒杀订单ID',
`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`),
UNIQUE KEY `seckill_uid_gid` (`user_id`,`goods_id`) USING BTREE COMMENT '用户id+商品id解决同一个用户秒杀多商品'
) ENGINE=InnoDB AUTO_INCREMENT=5687 DEFAULT CHARSET=utf8mb4;
CREATE TABLE `t_user` (
`id` bigint(20) NOT NULL COMMENT '用户ID,手机号码',
`nickname` varchar(255) NOT NULL,
`password` varchar(32) DEFAULT NULL COMMENT 'MD5(MD5(pass明文+固定salt)+salt)',
`slat` varchar(10) DEFAULT NULL,
`head` varchar(128) DEFAULT NULL COMMENT '头像',
`register_date` datetime DEFAULT NULL COMMENT '注册时间',
`last_login_date` datetime DEFAULT NULL COMMENT '最后一次登陆时间',
`login_count` int(11) DEFAULT '0' COMMENT '登陆次数',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
登陆网页地址:localhost:8080/login/toLogin
①一开始是将整个页面缓存在了redis中,加快响应速度。后面设计了静态页面,在本这个项目中,也就是只用了ajax来发送请求、传输数据等。用户不用每次都要去请求整个页面,降低了服务器的压力。
①在项目启动的时候,就把mysql中的秒杀商品库存加载到redis中。后续的减库存直接在redis中进行。使用redis的自减命令有效的防止了超卖问题(后面用了lua脚本来预减库存)。
②在mysql中将秒杀订单表中的商品id和用户id设置为唯一索引,在数据库端保证一个用户只能秒杀一件商品。
③用户在有了一个订单之后,存入redis中,加快响应速度。
④下订单的操作交给了RabbitMQ来做,有效的降低了服务器的压力。
⑤设置了一个内存标记。当redis中的库存为0之后,不用访问redis,直接返回。
⑥明文密码二次加密。第一次加密是为了防止密码在网络中明文传输。第二次加密是为了防止服务器被攻击而采取的保护措施。
①为了防止脚本刷接口,做了算术验证码进行校验。这样做可以阻止一部分简单脚本,一方面可以延长时间跨度。
②为了更好的防止一些较为高级一点的脚本,隐藏了秒杀接口地址。在秒杀的时候,需要先根据用户id和商品id获取秒杀地址,然后再去请求秒杀接口。这样可以阻止一些高级的秒杀脚本。
③使用redis进行计数限流。设置每秒钟只能有50个请求打进来。对于不同的秒杀商品,使用了AOP注解进行不用的技术限流。然后顺便把每个接口的参数User存进了线程的ThreadLocal中进行保存和获取。