redis实现秒杀功能例子(采用lua的原子性保证数据的一致性)

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import redis.clients.jedis.Jedis;

@Service
public class RedisServiceImpl {
@Autowired
private RedisTemplate template;

//lua脚本
private String script = "local number = ARGV[1] \n" +
		"local gsave = redis.call('hget','goods_'..KEYS[1],'gsave') \n" +
		"if gsave < number then \n" +
		"return 2 \n" +
		"end\n" +
		"gsave = gsave - number \n" +
		"redis.call('hset','goods_'..KEYS[1],'gsave',gsave)\n" +
		"redis.call('rpush','orders_'..KEYS[1],ARGV[2])\n" +
		"if gsave <= 0 then\n" +
		"return 0\n"+
		"else \n" +
		"return 1\n" +
		"end";
		
	private String sha1 = null;
	
	//lua脚本-原子性保证了数据的一致性
	public int miaosha(Integer gid, Integer number, Integer uid){
		Jedis jedis = (Jedis)template.getConnectionFactory().getConnection().getNativeConnection();
		//加载脚本
		if(sha1 == null){
			sha1 = jedis.scriptLoad(script);
		}
		//执行脚本
		String orderinfo = uid + "-" +number + "-" +System.currentTimeMillis();//订单信息
		Long result = (Long)jedis.evalsha(sha1, 1,gid+"",number+"",orderinfo);
		//抢购结束
		if(result == 0){

// 异步去执行插入数据库的方法
// 注入IGoodsService,(
// <task:executor id=“executor” pool-size=“5”/>
// <task:annotation-driven executor=“executor”/>)
// 再调用代理会帮我们实现异步
// goodsService.synDataBase(gid)
// 从redis中获得订单详情及卖出数量再批量插入
}
return Integer.parseInt(result.toString());
}
}

转载博客: https://blog.csdn.net/futao127/article/details/80617214

猜你喜欢

转载自blog.csdn.net/u014644709/article/details/86569525