1. 程式人生 > >redis實現秒殺功能例子(採用lua的原子性保證資料的一致性)

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