Java秒杀系统⽅案优化⾼性能⾼并发实战(已完成)1:商品列表
2:商品详情判断是否可以开始秒杀,
要考虑校验活动的商品id和商品秒杀时间是否有效
商品详情判断是否可以开始秒杀,
未开始不显⽰秒杀按钮显⽰倒计时,
开始显⽰秒杀按钮,同时会显⽰验证码输⼊框以及验证码图⽚
(会通过userid和productid作为key验证码结果作为value存储在redis中),
当点击秒杀按钮的时候会⾸先判断验证码是否正确,如果正确会返回⼀个加密的秒杀地址(通过商品id和⽤户id规则)同时存储在redis中
拿着返回的秒杀地址去请求的时候判断秒杀地址是否合法,合法的话继续秒杀不合法终⽌秒杀执⾏
如果判断当前内存中的标识已经没有库存就返回秒杀完毕
否则继续判断redis中的库存-1如果当前值⼩于0的话把内存中的标识设置为已没有库存,
否则通过redis判断是否已经秒杀过,如果没有秒杀过就进⼊消息队列
消费端
判断是否有库存
判断是否已经秒杀到了
减库存,要保证库存不能⼩于0,下订单,(减库存,下订单要在⼀个事务中,同时有个主键唯⼀索引在⽤户id和商品id在写⼊订单表的时候)写⼊秒杀订单,结束不显⽰秒杀按钮
1:springboot thymeleaf配置
spring.thymeleaf.cache=false
t-type=text/html
abled=true
ding=UTF-8
de=HTML5
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
2:mybatis druid redis 配置
# mybatis
mybatis.mapperLocations = classpath:com/imooc/miaosha/dao/*.xml
# druid
spring.datasource.url=jdbc:mysql://192.168.220.128:3306/miaosha?useUnicode=true&characterEnc
oding=utf-8&allowMultiQueries=true&useSSL=false spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.sql.jdbc.Driver
pe=com.alibaba.druid.pool.DruidDataSource
spring.datasource.filters=stat
spring.datasource.maxActive=2
spring.datasource.initialSize=1
spring.datasource.maxWait=60000
spring.datasource.minIdle=1
spring.datasource.timeBetweenEvictionRunsMillis=60000
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=select 'x'
stWhileIdle=true
stOnBorrow=false
stOnReturn=false
spring.datasource.poolPreparedStatements=true
spring.datasource.maxOpenPreparedStatements=20
#redis
redis.host=192.168.220.128
redis.port=6379
redis.timeout=3
redis.password=123456
redis.poolMaxTotal=10
redis.poolMaxIdle=10
redis.poolMaxWait=3
需要引⼊以下依赖
<dependency>
<groupId&batis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.5</version>
</dependency>
demo
DemoController类
@Controller
@RequestMapping("/demo")
public class DemoController {
@RequestMapping("/")
@ResponseBody
String home() {
return "Hello World!";
}
//1.rest api json输出 2.页⾯
@RequestMapping("/hello")
@ResponseBody
public Result<String> hello() {
return Result.success("hello,imooc");
// return new Result(0, "success", "hello,imooc"); }
@RequestMapping("/helloError")
@ResponseBody
public Result<String> helloError() {
(CodeMsg.SERVER_ERROR); //return new Result(500102, "XXX");
}
@RequestMapping("/thymeleaf")
public String thymeleaf(Model model) {
model.addAttribute("name", "Joshua");
return "hello";
}
}
public class Result<T> {
private int code;
private String msg;
private T data;
/**
* 成功时候的调⽤
* */
public static <T> Result<T> success(T data){
return new Result<T>(data);
}
/**
* 失败时候的调⽤
* */
public static <T> Result<T> error(CodeMsg codeMsg){ return new Result<T>(codeMsg);
}
private Result(T data) {
this.data = data;
}
private Result(int code, String msg) {
this.msg = msg;
}
private Result(CodeMsg codeMsg) {
if(codeMsg != null) {
this.msg = Msg();
}
}
}
public void setCode(int code) {
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
public class CodeMsg {
private int code;
private String msg;
//通⽤的错误码
public static CodeMsg SUCCESS = new CodeMsg(0, "success");
public static CodeMsg SERVER_ERROR = new CodeMsg(500100, "服务端异常");
public static CodeMsg BIND_ERROR = new CodeMsg(500101, "参数校验异常:%s");
//登录模块 5002XX
public static CodeMsg SESSION_ERROR = new CodeMsg(500210, "Session不存在或者已经失效"); public static CodeMsg PASSWORD_EMPTY = new CodeMsg(500211, "登录密码不能为空");
public static CodeMsg MOBILE_EMPTY = new CodeMsg(500212, "⼿机号不能为空");
public static CodeMsg MOBILE_ERROR = new CodeMsg(500213, "⼿机号格式错误");
public static CodeMsg MOBILE_NOT_EXIST = new CodeMsg(500214, "⼿机号不存在");
public static CodeMsg PASSWORD_ERROR = new CodeMsg(500215, "密码错误");
//商品模块 5003XX
//订单模块 5004XX
//秒杀模块 5005XX
private CodeMsg( ) {
}
private CodeMsg( int code,String msg ) {
this.msg = msg;
thyme}
public int getCode() {
return code;
}
public void setCode(int code) {
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public CodeMsg args) {
int code = de;
String message = String.format(this.msg, args);
return new CodeMsg(code, message);
}
@Override
public String toString() {
return "CodeMsg [code=" + code + ", msg=" + msg + "]";
}
}
3:dao层访问代码
@Mapper
@Select("select * from user where id = #{id}")
public User getById(@Param("id")int id );
@Insert("insert into user(id, name)values(#{id}, #{name})")
public int insert(User user);
}
4:redis config配置
需要引⼊以下依赖
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.38</version>
</dependency>
@Component
@ConfigurationProperties(prefix="redis")
public class RedisConfig {
private String host;
private int port;
private int timeout;//秒
private String password;
private int poolMaxTotal;
private int poolMaxIdle;
private int poolMaxWait;//秒
}
5: redis JedisPool 配置
@Service
public class RedisPoolFactory {
@Autowired
RedisConfig redisConfig;
@Bean
public JedisPool JedisPoolFactory() {
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.PoolMaxIdle());
poolConfig.PoolMaxTotal());
poolConfig.PoolMaxWait() * 1000);
JedisPool jp = new JedisPool(poolConfig, Host(), Port(), Timeout()*1000, Password(), 0);
return jp;
}
}
6:redis service
@Service
public class RedisService {
@Autowired
JedisPool jedisPool;
/**
* 获取当个对象
* */
public <T> T get(KeyPrefix prefix, String key, Class<T> clazz) {
Jedis jedis = null;
try {
jedis = Resource();
//⽣成真正的key
String realKey = Prefix() + key;
String str = (realKey);
T t = stringToBean(str, clazz);
return t;
}finally {
returnToPool(jedis);
}
}
* 设置对象
* */
public <T> boolean set(KeyPrefix prefix, String key, T value) { Jedis jedis = null;
try {
jedis = Resource();
String str = beanToString(value);
if(str == null || str.length() <= 0) {
return false;
}
//⽣成真正的key
String realKey = Prefix() + key;
int seconds = pireSeconds();
if(seconds <= 0) {
jedis.set(realKey, str);
}else {
jedis.setex(realKey, seconds, str);
}
return true;
}finally {
returnToPool(jedis);
}
}
/**
* 判断key是否存在
* */
public <T> boolean exists(KeyPrefix prefix, String key) {
Jedis jedis = null;
try {
jedis = Resource();
//⽣成真正的key
String realKey = Prefix() + key;
return ists(realKey);
}finally {
returnToPool(jedis);
}
}
/**
* 增加值
* */
public <T> Long incr(KeyPrefix prefix, String key) {
Jedis jedis = null;
try {
jedis = Resource();
//⽣成真正的key
String realKey = Prefix() + key;
return jedis.incr(realKey);
}finally {
returnToPool(jedis);
}
}
/**
* 减少值
* */
public <T> Long decr(KeyPrefix prefix, String key) {
Jedis jedis = null;
try {
jedis = Resource();
//⽣成真正的key
String realKey = Prefix() + key;
return jedis.decr(realKey);
}finally {
returnToPool(jedis);
}
}
private <T> String beanToString(T value) {
if(value == null) {
return null;
}
Class<?> clazz = Class();
if(clazz == int.class || clazz == Integer.class) {
return ""+value;
}else if(clazz == String.class) {
return (String)value;
}else if(clazz == long.class || clazz == Long.class) {
return ""+value;
}else {
JSONString(value);
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论