当前位置:网站首页>[redis]redis6 transaction operations

[redis]redis6 transaction operations

2022-06-22 21:10:00 fate _ zore

Redis6 Transaction operation of

Redis The definition of the transaction

image-20220619152757114

Redis A transaction is a separate isolation operation : All commands in the transaction are serialized 、 To execute in order . Transaction is in the process of execution , Will not be interrupted by command requests from other clients .

Redis The main function of business is Concatenate multiple commands Prevent other orders from jumping in line .

Multi、Exec、discard

From input Multi Command start , All the entered commands will enter the command queue in turn , But will not execute , Until input Exec after ,Redis The previous commands in the command queue will be executed successively .

In the process of team formation, you can go through discard To give up team building .

image-20220619152848021

Wrong handling of transactions

  • There was a report error on a command in the team , During execution, all queues of the whole are cancelled

image-20220619152910457

  • If an error is reported in a command during execution , Only the wrong command will not be executed , And other orders will be executed , No rollback .

image-20220619152936595

Transaction conflict

Example

A request wants to reduce the amount 8000

A request wants to reduce the amount 5000

A request wants to reduce the amount 1000

image-20220619164733463

The idea of two locks

image-20220619153547188

Pessimistic locking

Pessimistic locking (Pessimistic Lock), seeing the name of a thing one thinks of its function , Is very pessimistic , Every time I go to get the data, I think others will modify it , So every time I get the data, I lock it , So that if people want to take this data, they will block Until it gets the lock . There are many lock mechanisms used in traditional relational databases , such as Row lock , Table locks etc. , Read the lock , Write lock etc. , It's all locked before the operation .

Optimism lock

Optimism lock (Optimistic Lock), seeing the name of a thing one thinks of its function , Is very optimistic , Every time I go to get the data, I think other people won't modify it , So it won't lock , But in the process of updating, we will judge whether other people have updated this data during this period , You can use mechanisms like version numbers . Optimistic lock is suitable for multi read applications , This can improve throughput .Redis It's using this check-and-set The mechanism implements the .

WATCHkey [key …]

In execution multi Before , Execute first watch key1 [key2], You can watch one ( Or more ) key , If you're in business This before execution ( Or these ) key Altered by other orders , Then the business will be interrupted .

unwatch

Cancel WATCH Command to all key Surveillance .

If in execution WATCH After the command ,EXEC Order or DISCARD If the order is executed first , Then there's no need to execute UNWATCH 了 .

Redis Three characteristics of transaction

Ø Separate isolation operation

  • All commands in the transaction are serialized 、 To execute in order . Transaction is in the process of execution , Will not be interrupted by command requests from other clients .

Ø There is no concept of isolation level

  • The commands in the queue are not actually executed until they are submitted , Because no instruction is actually executed before the transaction is committed

Ø There is no guarantee of atomicity

  • If a command fails in a transaction , Subsequent orders will still be executed , No rollback

Second kill case

Ideas

image-20220619173036319

  1. Pass in uid and prodid( And verify )
  2. according to uid and prodid Generate key
  3. Inventory judgment (null Not yet begun ,0 end ), Repeat second kill judgment
  4. Second kill of users , stock –
  5. The user enters the seckill success list

Code :

public static boolean doSecKill(String uid,String prodid) throws IOException {
    
   //1 uid and prodid Judge not empty 
   if(uid == null || prodid == null) {
    
      return false;
   }

   //2  Connect redis
   //Jedis jedis = new Jedis("192.168.44.168",6379);
   // Get through connection pool jedis object 
   JedisPool jedisPoolInstance = JedisPoolUtil.getJedisPoolInstance();
   Jedis jedis = jedisPoolInstance.getResource();

   //3  Splicing key
   // 3.1  stock key
   String kcKey = "sk:"+prodid+":qt";
   // 3.2  Second kill successful users key
   String userKey = "sk:"+prodid+":user";

   // Monitor inventory 
   jedis.watch(kcKey);

   //4  Get inventory , If inventory null, The second kill hasn't started yet 
   String kc = jedis.get(kcKey);
   if(kc == null) {
    
      System.out.println(" The second kill hasn't started yet , Please wait ");
      jedis.close();
      return false;
   }

   // 5  Judge whether the user repeats the second kill operation 
   if(jedis.sismember(userKey, uid)) {
    
      System.out.println(" It's a second kill , You can't repeat the second kill ");
      jedis.close();
      return false;
   }

   //6  Judge if the quantity of goods , Inventory quantity is less than 1, End of seckill 
   if(Integer.parseInt(kc)<=0) {
    
      System.out.println(" The second kill is over ");
      jedis.close();
      return false;
   }

   //7  Second kill process 
   // With a transaction 
   Transaction multi = jedis.multi();

   // Team operation 
   multi.decr(kcKey);
   multi.sadd(userKey,uid);

   // perform 
   List<Object> results = multi.exec();

   if(results == null || results.size()==0) {
    
      System.out.println(" The second kill failed ....");
      jedis.close();
      return false;
   }

   //7.1  stock -1
   //jedis.decr(kcKey);
   //7.2  Add successful users to the list 
   //jedis.sadd(userKey,uid);

   System.out.println(" The second kill succeeded ..");
   jedis.close();
   return true;
}

You can solve the link timeout problem through the thread pool

public class JedisPoolUtil {
    
   private static volatile JedisPool jedisPool = null;

   private JedisPoolUtil() {
    
   }

   public static JedisPool getJedisPoolInstance() {
    
      if (null == jedisPool) {
    
         synchronized (JedisPoolUtil.class) {
    
            if (null == jedisPool) {
    
               JedisPoolConfig poolConfig = new JedisPoolConfig();
               poolConfig.setMaxTotal(200);
               poolConfig.setMaxIdle(32);
               poolConfig.setMaxWaitMillis(100*1000);
               poolConfig.setBlockWhenExhausted(true);
               poolConfig.setTestOnBorrow(true);  // ping PONG
             
               jedisPool = new JedisPool(poolConfig, "192.168.44.168", 6379, 60000 );
            }
         }
      }
      return jedisPool;
   }

   public static void release(JedisPool jedisPool, Jedis jedis) {
    
      if (null != jedis) {
    
         jedisPool.returnResource(jedis);
      }
   }

}

have access to lua To solve the remaining inventory problems

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='sk:'..prodid..\":qt\";\r\n" + 
         "local usersKey='sk:'..prodid..\":usr\";\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= .secKillScript;
      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(" Empty !!");
      }else if("1".equals( reString )  )  {
    
         System.out.println(" Panic buying !!!!");
      }else if("2".equals( reString )  )  {
    
         System.err.println(" The user has robbed !!");
      }else{
    
         System.err.println(" Panic buying exception !!");
      }
      jedis.close();
      return true;
   }
}

原网站

版权声明
本文为[fate _ zore]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/173/202206221944520173.html