# jseckill
![license](https://img.shields.io/github/license/alibaba/dubbo.svg)
<br/>
| 📘 | 🛫 | 🐱 | 🏛 | 🛒 | 🚀 | 💡 |
| :--------: | :---------: | :------: | :------: | :------: | :------: | :------: |
| [介绍](#介绍) | [演示](#演示) | [技术栈](#技术栈) | [架构图](#架构图) | [秒杀过程](#秒杀过程) | [Quick Start](#QuickStart) | [源码解析](#源码解析) |
| 📌 | ❓ | 🐞 | 🔨 | 💌 |
| :------: | :------: | :------: | :------: | :------: |
| [Todo list](#Todo-list) | [Q&A](#Q-and-A) | [调试排错](#调试排错) | [做贡献](#做贡献) | [联系作者](#联系作者) |
## 介绍
<code>jseckill</code>:Java实现的秒杀网站,基于Spring Boot 2.X。
<code>jseckill</code>:Seckill website implemented with Java, based on Spring Boot 2.X.
**谢谢您对本项目的支持** <br/>
**请点击此处进行**[Star](https://github.com/liushaoming/jseckill/stargazers)
**GitHub** 地址为[https://github.com/liushaoming/jseckill](https://github.com/liushaoming/jseckill)
建议访问GitHub以获取更多分布式项目源码[https://github.com/liushaoming?tab=repositories](https://github.com/liushaoming?tab=repositories)
## 演示
**点击进入演示**:[http://jseckill.appjishu.com](http://jseckill.appjishu.com)
注意:提升输入手机号时,随便输入一个11位的数字即可,**不需要填自己的真实手机号**
效果图
![](doc/image/demo-1.jpg) ![](doc/image/demo-2.jpg)
<br/>
<br/>
![](doc/image/demo-3.jpg)
## 技术栈
- Spring Boot 2.X
- MyBatis
- Redis, MySQL
- Thymeleaf + Bootstrap
- RabbitMQ
- Zookeeper, Apache Curator
## 架构图
部署图
(zookeeper暂时没有用上, 忽略之)
<br/><br/>
![](doc/image/arch-1.jpg)
<br/>
<br/>
## 秒杀过程
秒杀进行的过程包含两步骤:
步骤一(秒杀):在Redis里进行秒杀。 这个步骤用户并发量非常大,抢到后,给与30分钟的时间等待用户付款, 如果用户过期未付款,则Redis库存加1
,算用户自动放弃付款。
步骤二(付款):用户付款成功后,后台把付款记录持久化到MySQL中,这个步骤并发量相对小一点,使用数据库的事务解决数据一致性问题
下面重点讲步骤一,**秒杀**过程
秒杀步骤流程图
![](doc/image/arch-seckill.png)
1.流程图Step1:先经过Nginx负载均衡和分流
2.进入jseckill程序处理。 Google guava RateLimiter限流。 并发量大的时候,直接舍弃掉部分用户的请求
3.Redis判断是否秒杀过。避免重复秒杀。如果没有秒杀过 <br/>
把用户名(这里是手机号)和seckillId封装成一条消息发送到RabbitMQ,请求变成被顺序串行处理 <br/>
立即返回状态“排队中”到客户端上,客户端上回显示“排队中...”
4.后台监听RabbitMQ里消息,每次取一条消息,并解析后,请求Redis做库存减1操作(decr命令) <br/>
并手动ACK队列
如果减库存成功,则在Redis里记录下库存成功的用户手机号userPhone.
5.流程图Step2:客户端排队成功后,定时请求后台查询是否秒杀成功,后面会去查询Redis是否秒杀成功<br/>
如果抢购成功,或者抢购失败则停止定时查询, 如果是排队中,则继续定时查询。
详情见源码文档
## QuickStart
- clone源码
<code>git clone https://github.com/liushaoming/jseckill.git </code>
- 在Intelij IDEA/eclipse里导入根路径下的pom.xml,再导入文件夹jseckill-backend下面的pom.xml, 等待maven依赖下载完毕
详细操作:
**如果是IDEA**,先IDEA | File | Open...,选择jseckill根路径下的pom文件, Open as project以导入根项目jseckill。
操作菜单栏 View | Tool Windows | Maven Projects。 点击"+", 添加jseckill-backend下面的pom。
此时Maven Projects下面有根项目jseckill和jseckill-backend。如下图
![](doc/image/quickstart-0.png)
**如果是Eclipse**, import导入maven项目,勾选jseckil和jseckill-backend下面共两个pom文件即可。
- 修改application.properties里面的自己的Redis,MySQL,Zookeeper,RabbitMQ的连接配置
- 右键JseckillBackendApp.java--run as--Java Application
开始Debug
## 源码解析
👉 [进入源码解析](SOURCE-README.md)
### Java后端限流
使用Google guava的RateLimiter来进行限流 <br/>
例如:每秒钟只允许10个人进入秒杀步骤. (可能是拦截掉90%的用户请求,拦截后直接返回"很遗憾,没抢到") <br/>
AccessLimitServiceImpl.java代码 <br/>
```java
package com.liushaoming.jseckill.backend.service.impl;
import com.google.common.util.concurrent.RateLimiter;
import com.liushaoming.jseckill.backend.service.AccessLimitService;
import org.springframework.stereotype.Service;
/**
* 秒杀前的限流.
* 使用了Google guava的RateLimiter
*/
@Service
public class AccessLimitServiceImpl implements AccessLimitService {
/**
* 每秒钟只发出10个令牌,拿到令牌的请求才可以进入秒杀过程
*/
private RateLimiter seckillRateLimiter = RateLimiter.create(10);
/**
* 尝试获取令牌
* @return
*/
@Override
public boolean tryAcquireSeckill() {
return seckillRateLimiter.tryAcquire();
}
}
```
👉 [查看更多源码解析](SOURCE-README.md)
## Todo list
- 秒杀成功30分钟订单过期的实现
**方案**:
A:用redis对key设置过期时间,超时的监听
秒杀成功后订单保存在redis,对key设置过期时间为当时向后推半小时,当key过期后触发监听,对redis库存+1。
- 怎么避免用来削峰的mq中的消息过长,导致mq崩溃
**方案**:
在进入削峰队列之前,需要判断mq中的消息数目是否过多,如果超过设定的数量限制,直接返回给客户端"已售罄"
channel.messageCount("seckill") 可以获取到队列中当前到ready的消息的数目
见接口 [http://localhost:27000/api/rabbitmq](http://localhost:27000/api/rabbitmq)
## Q and A
Q:
为什么有时候会发现消息发送到了队列中,但是不被消费?
A:
一种可能的原因是。 你的电脑上在Debug一个程序jseckill-backend, 另外在你自己的服务器上也运行了同样的程序。
两个程序如果连接的是同一个RabbitMQ,就会同时消费消息,就会发生这样的情况。因为我们在程序员里
<code>com.liushaoming.jseckill.backend.mq.MQConsumer#receive</code>里限制了消费者的个数。
```java
channel.basicQos(0, 1, false);
```
## 调试排错
- 1.java.net.SocketException: Socket Closed--nested exception is com.rabbitmq.client.AuthenticationFailureException: ACCESS_REFUSED
```text
03/10-16:51:28 [main] WARN org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext- Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'initTask': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'MQConsumer': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'seckillServiceImpl': Unsatisfied dependency expressed through field 'mqProducer'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'MQProducer': Unsatisfied dependency expressed through field 'mqChannelManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'MQChannelManager': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mqConnectionSeckill' defined in class path resource [com/liushaoming/jseckill/backend/config/MQConfig.class]:
没有合适的资源?快使用搜索试试~ 我知道了~
Java实现的秒杀网站,基于Spring Boot 2.X
共67个文件
java:36个
jpg:5个
html:4个
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
0 下载量 37 浏览量
2022-06-27
15:31:32
上传
评论
收藏 299KB ZIP 举报
温馨提示
jseckill:Java实现的秒杀网站,基于Spring Boot 2.X。 jseckill:Seckill website implemented with Java, based on Spring Boot 2.X. 秒杀过程 秒杀进行的过程包含两步骤: 步骤一(秒杀):在Redis里进行秒杀。 这个步骤用户并发量非常大,抢到后,给与30分钟的时间等待用户付款, 如果用户过期未付款,则Redis库存加1 ,算用户自动放弃付款。 步骤二(付款):用户付款成功后,后台把付款记录持久化到MySQL中,这个步骤并发量相对小一点,使用数据库的事务解决数据一致性问题
资源推荐
资源详情
资源评论
收起资源包目录
jseckill-master.zip (67个子文件)
jseckill-master
SOURCE-README.md 10KB
.gitignore 292B
README.md 13KB
pom.xml 600B
LICENSE 11KB
.gitattributes 87B
sql
seckill.sql 2KB
pay_order.sql 932B
jseckill-backend
.gitignore 274B
pom.xml 5KB
src
test
java
com
liushaoming
jseckill
backend
service
impl
MqProducerTest.java 681B
main
resources
static
image
sys
forkme.png 9KB
js
seckill.js 7KB
config
mapping
PayOrderDAO.xml 1KB
SeckillDAO.xml 1KB
application-dev.properties 4KB
application.properties 481B
templates
list.html 3KB
detail.html 4KB
common
head.html 552B
index.html 160B
java
com
liushaoming
jseckill
backend
bean
ZKConfigBean.java 1KB
MQConfigBean.java 1KB
dao
cache
RedisDAO.java 5KB
PayOrderDAO.java 734B
SeckillDAO.java 1KB
boot
InitTask.java 2KB
AppContextHolder.java 1KB
exception
SeckillException.java 824B
mq
MQProducer.java 2KB
MQConsumer.java 5KB
MQChannelManager.java 2KB
dto
SeckillExecution.java 2KB
SeckillResult.java 1KB
SeckillMsgBody.java 573B
Exposer.java 2KB
singleton
MyRuntimeSchema.java 827B
distlock
CuratorClientManager.java 2KB
controller
HomeController.java 375B
SeckillController.java 5KB
ApiController.java 1KB
constant
RedisKeyPrefix.java 285B
RedisKey.java 216B
config
RedisCacheConfig.java 2KB
ZookeeperConfig.java 1KB
MQConfig.java 3KB
enums
AckAction.java 108B
SeckillStateEnum.java 1KB
JseckillBackendApp.java 440B
service
SeckillService.java 1KB
AccessLimitService.java 211B
impl
SeckillServiceImpl.java 12KB
AccessLimitServiceImpl.java 715B
entity
PayOrder.java 1KB
Seckill.java 2KB
doc
other.txt 139B
image
demo-3.jpg 16KB
arch-seckill.png 29KB
quickstart-0.png 19KB
demo-2.jpg 20KB
demo-1.jpg 25KB
group-qrcode.png 7KB
public-account.jpg 26KB
arch-1.jpg 27KB
start.sh 93B
readme
source.vsdx 71KB
codesegment
SeckillServiceImpl.java 11KB
共 67 条
- 1
资源评论
码农.one
- 粉丝: 7
- 资源: 345
下载权益
C知道特权
VIP文章
课程特权
开通VIP
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功