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); } }