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

}

  

posted on 2016-06-27 19:26  左侧码工  阅读(545)  评论(0编辑  收藏  举报