Redis-秒杀场景应用
Redis Util实现
package test.jedis;
import java.util.List;
import java.util.Set;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;
public class JedisUtil {
public static Jedis redis = new Jedis("localhost", 6379);// 连接redis
static{
//初始化购物数据
redis.set("buy:number:1", "10000");
}
/**
* 执行事务的过程其他客户端改变了其中的key值,解决数据一致性问题
* 通过watch 对key的监控来实现其他客户端修改数据后,事务取消
* 用法 首先用watch 开始对key的监控 在开启事务,顺序一定要先监控在执行事务
* */
public synchronized static String buy_trans(String userId) throws InterruptedException{
//1、通过对keys 的设计保证 每个用户只能购买一个
if(!redis.exists(userId)){
//2、当数量不购时提示 秒杀完
if(Integer.parseInt(redis.get("buy:number:1"))>0){
//3、redis 事务 监控数量的变化key=buy:number:1 监控1号商品的数量变化
redis.watch("buy:number:1");
//4、开启事务
Transaction tx = redis.multi();
//5、购买用户购买 成功 成功购买
tx.incr(userId);
//6、设置数量减1
tx.decr("buy:number:1");
//7、执行事务
List<Object> results = tx.exec();
}else{
return "数量不足";
}
redis.disconnect();
return "抢购购买成功";
}else{
return "该用户已经购买了";
}
}
public static Set<String> getKeys(String keys){
return redis.keys(keys);
}
}
Controller 端实现
package com.sf.fs.view;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.sf.fs.service.SeckillService;
/**
* seckill test
* */
@Controller
public class SeckillController {
private SeckillService seckillService;
public void setSeckillService(SeckillService seckillService) {
this.seckillService = seckillService;
}
/**
* 抢购方法
* */
@RequestMapping("/buying")
public String buying(HttpServletRequest req){
//测试用于方便测试用sessionid 作为用户id
String sessionId=req.getSession().getId();
//存储的key 是 user:sessionId
String msg=seckillService.buying("user:"+sessionId);
System.out.println("返回的操作结果:"+msg);
return "succeed";
}
/**
* 测试成功抢购的用户数,是否会出现超卖
* */
@RequestMapping("/result")
public void getResult(HttpServletRequest req){
Set<String> sets=seckillService.getUsers("user:*");
System.out.println("成功秒杀到的用户数:"+sets.size());
}
}
Service 实现
package com.sf.fs.service.impl;
import java.util.List;
import java.util.Set;
import com.sf.fs.service.SeckillService;
import test.jedis.JedisUtil;
public class SeckillServiceImpl implements SeckillService {
public static int number=100;
private JedisUtil jedisUtil;
public void setJedisUtil(JedisUtil jedisUtil) {
this.jedisUtil = jedisUtil;
}
@Override
public String buying(String key) {
try {
return jedisUtil.buy_trans(key);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "操作失败";
}
public Set<String> getUsers(String prefixKey){
return jedisUtil.getKeys(prefixKey);
}
}
浙公网安备 33010602011771号