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;

   }



}