redis-事务解决高并发问题

1,Redis事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。

2,Redis事务的主要作用就是串联多个命令防止别的命令插队

3,从输入Multi命令开始,Exec开始执行,discard结束

4,关于高并发问题事务时如何解决的

       例如秒杀20个商品,会出现的问题,1,库存会出现复数,为何会这样呢?因为如30个用户同时拿到数据,都会进行减1操作,库存就会出现-10;

                                                                 2, 库存剩余问题

       那如何解决呢?

             解决超卖问题?思路是 利用redis   watch监听商品变化,把需要减商品的步骤放入multi中,当watch(key) 发生变化时,会自动取消事务,但是这样

        会出现问题2,商品库存遗留问题,因为比如我们设置并发量为200,其中只有1个人能够成功,这样就会出现遗留问题,

       解决库存剩余问题 我是利用lua脚本解决的,LUA脚本是类似redis事务,有一定的原子性,不会被其他命令插队,可以完成一些redis事务性的操作。

详情见下面代码:

         


public class SecKill_redisByScript {

private static final org.slf4j.Logger logger =LoggerFactory.getLogger(SecKill_redisByScript.class) ;

public static void main(String[] args) {


JedisPool jedispool = JedisPoolUtil.getJedisPoolInstance();

Jedis jedis=jedispool.getResource();
System.out.println(jedis.ping());

Set<HostAndPort> set=new HashSet<HostAndPort>();


// doSecKill("201","sk:0101");


}

static String secKillScript ="local userid=KEYS[1];\r\n" +
"local prodid=KEYS[2];\r\n" +
"local qtkey='Seckill:'..prodid..\":kc\";\r\n" +
"local usersKey='Seckill:'..prodid..\":user\";\r\n" +
"local userExists=redis.call(\"sismember\",usersKey,userid);\r\n" +
"if tonumber(userExists)==1 then \r\n" +
" return 2;\r\n" +
"end\r\n" +
"local num= redis.call(\"get\" ,qtkey);\r\n" +
"if tonumber(num)<=0 then \r\n" +
" return 0;\r\n" +
"else \r\n" +
" redis.call(\"decr\",qtkey);\r\n" +
" redis.call(\"sadd\",usersKey,userid);\r\n" +
"end\r\n" +
"return 1" ;

static String secKillScript2 =
"local userExists=redis.call(\"sismember\",\"{sk}:0101:usr\",userid);\r\n" +
" return 1";


public static boolean doSecKill(String uid,String prodid) throws IOException {

JedisPool jedisPool = JedisPoolUtil.getJedisPoolInstance();

Jedis jedis = jedisPool.getResource();

String sha1= jedis.scriptLoad(secKillScript);

Object result= jedis.evalsha(sha1, 2, uid,prodid);


String reString=String.valueOf(result);
if ("0".equals( reString ) ) {
System.err.println("已抢空!!");
}else if("1".equals( reString ) ) {
System.out.println("抢购成功!!!!");
}else if("2".equals( reString ) ) {
System.err.println("该用户已抢过!!");
}else{
System.err.println("抢购异常!!");
}



jedis.close();

return true;

}



}

               

猜你喜欢

转载自www.cnblogs.com/haiquan/p/12462269.html