Advantages of LUA scripts in Redis
– Write a complex or multi-step redis operation as a script, and submit it to redis for execution at one time, reducing the number of repeated connections to redis. Improve performance.
– LUA scripts are similar to redis transactions, have certain atomicity, will not be queued by other commands, and can complete some redis transactional operations.
– But pay attention to the lua script function of redis, which can only be used in versions above Redis 2.6.
-Use lua scripts to eliminate users and solve the problem of overselling.
SecKillController3
package com.junsang.jedisdemo01.demos.controller; import com.junsang.jedisdemo01.demos.config.SecKill_redisByScript; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.io.IOException; import java.util.Random; @RestController public class SecKillController3 { @PostMapping(value = "/skv3") public String skhan(@RequestParam("prodid")String prodid){ try { String userid = new Random(). nextInt(50000) + ""; boolean b = SecKill_redisByScript.doSecKill(userid, prodid); System.out.println("second kill result" + b); } catch (IOException e) { e.printStackTrace(); } return null; } }
Jedis connection pool
package com.junsang.jedisdemo01.demos.utils; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; /** * Jedis connection pool */ public class JedisPoolUtils { //Redis server IP address private static String ADDR = "10.70.20.47"; //Redis port number private static int PORT = 6379; // The maximum number of available connection instances, the default value is 8 // If the assignment is -1, it means no limit // If the connection pool has allocated maxActive Jedis instances. At this time, the state of the connection pool is exhausted (exhausted) private static int MAX_ACTIVE = 20; //Control how many Jedis instances are idle (idle) in a connection pool, and the default value is also 8 private static int MAX_IDLE = 5; private static int MIN_IOLE = 0; //The maximum time to wait for an available connection. The unit is milliseconds. The default value is -1, which means never timeout //If the waiting time is exceeded, JedisConnectionException is thrown directly private static int MAX_WAIT = -1; // When allocating a Jedis instance. Whether to perform verification operation in advance //If true, all Jedis instances obtained are available private static boolean TEST_ON_BORROW = true; //Whether to check connection availability (ping()) when returning a Jedis instance to the connection pool private static boolean TEST_ON_RETURN = true; private static JedisPool jedisPool = null; /** * Initialize the Redis connection pool * * @return */ public static JedisPool getJedisPoolInstance() { if (null == jedisPool) { //sync lock synchronized(JedisPoolUtils. class) { if (null == jedisPool) { //Jedis connection pool configuration JedisPoolConfig poolConfig = new JedisPoolConfig(); poolConfig.setMaxTotal(MAX_ACTIVE); poolConfig.setMaxIdle(MAX_IDLE); poolConfig.setMaxWaitMillis(MAX_WAIT); poolConfig.setMinIdle(MIN_IOLE); poolConfig.setTestOnBorrow(TEST_ON_BORROW); poolConfig.setTestOnReturn(TEST_ON_RETURN); jedisPool = new JedisPool(poolConfig, ADDR, PORT,1800000,"123456"); } } } return jedisPool; } /** * Get the Jedis instance * * @return */ public synchronized static Jedis getJedis() { try { if (jedisPool != null) { Jedis resource = jedisPool. getResource(); return resource; } else { return null; } } catch (Exception e) { e.printStackTrace(); return null; } } /** * Release Jedis resources * * @param jedis */ public static void releaseResource(final Jedis jedis) { if (jedis != null) { jedisPool. close(); } } public static void main(String[] args) { JedisPool jedisPool = JedisPoolUtils.getJedisPoolInstance(); JedisPool jedisPool2 = JedisPoolUtils.getJedisPoolInstance(); System.out.println(jedisPool == jedisPool2); Jedis jedis = null; try { jedis = JedisPoolUtils. getJedis(); jedis.set("message", "Redis connection pool"); System.out.println(jedis.get("message")); } catch (Exception e) { e.printStackTrace(); } finally { //Release the Jedis instance JedisPoolUtils. releaseResource(jedis); } } }
SecKill_redisByScript
package com.junsang.jedisdemo01.demos.config; import java.io.IOException; import com.junsang.jedisdemo01.demos.utils.JedisPoolUtils; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; public class SecKill_redisByScript { static String secKillScript = "local userid=KEYS[1];\r\ " + // define the first variable "local prodid=KEYS[2];\r\ " + // define the second variable "local qtkey='sk:'..prodid..":qt";\r\ " + // inventory key "local usersKey='sk:'..prodid..":usr";\r\ " + // key of the user who successfully kills in seconds "local userExists=redis.call("sismember",usersKey,userid);\r\ " + //sismember detects whether the key exists in the collection "if tonumber(userExists)==1 then \r\ " + // If the result of the above line is 1, it means that the user has snapped up, then return 2 directly " return 2;\r\ " + "end\r\ " + "local num= redis.call("get" ,qtkey);\r\ " + // get inventory "if tonumber(num)<=0 then \r\ " + // if inventory<=0 " return 0;\r\ " + // directly return 0, the inventory is 0, and the rush purchase is empty "else \r\ " + " redis.call("decr",qtkey);\r\ " + // inventory -1 " redis.call("sadd",usersKey,userid);\r\ " + // user + 1 "end\r\ " + "return 1"; static String secKillScript2 = "local userExists=redis.call("sismember","{sk}:0101:usr",userid);\r\ " + "return 1"; /** * Serious spike function * @param uid * @param prodid * @return * @throws IOException */ public static boolean doSecKill(String uid,String prodid) throws IOException { JedisPool jedispool = JedisPoolUtils.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("Already sold out!!"); }else if("1".equals( reString ) ) { System.out.println("Purchase success!!!"); }else if("2". equals( reString ) ) { System.err.println("The user has robbed!!"); }else{ System.err.println("Purchasing exception!!"); } jedis. close(); return true; } }