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,(<!-- 
//				配置这个后在方法前加注解@Async该方法就会变成异步的方法
//				 -->
//				<task:executor id="executor" pool-size="5"/>
//				<task:annotation-driven executor="executor"/>)
//				再调用代理会帮我们实现异步
//				goodsService.synDataBase(gid)
//				从redis中获得订单详情及卖出数量再批量插入
			}
			return Integer.parseInt(result.toString());
		}
}

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值