lua脚本操作Redis
一次扣减一个商品库存
* * @Test void test2 ( ) throws IOException { valueOperations. set ( key, 15L ) ; StringBuilder sb = new StringBuilder ( ) ; sb. append ( " local key = KEYS[1] " ) ; sb. append ( " local qty = ARGV[1] " ) ; sb. append ( " local redis_qty = redis.call('get',key) " ) ; sb. append ( " if tonumber(redis_qty) >= tonumber(qty) then " ) ; sb. append ( " redis.call('decrby',key,qty) " ) ; sb. append ( " return -1 " ) ; sb. append ( " else " ) ; sb. append ( " return tonumber(redis_qty) " ) ; sb. append ( " end " ) ; sb. append ( " " ) ; RedisScript < Long > script = RedisScript . of ( sb. toString ( ) , Long . class ) ; ExecutorService executorService = Executors . newCachedThreadPool ( ) ; for ( int i = 1 ; i <= 10 ; i++ ) { int finalI = i; executorService. execute ( ( ) -> { int needQty = RandomUtil . randomInt ( 1 , 5 ) ; Long qty = stringRedisTemplate. execute ( script, CollUtil . newArrayList ( key) , needQty+ "" ) ; if ( qty. intValue ( ) == - 1 ) { System . out. println ( "线程" + finalI + "扣减成功,需求量是:" + needQty) ; } else { System . out. println ( "线程" + finalI + "扣减失败,当前库存变量是:" + qty) ; } } ) ; } System . in. read ( ) ; }
一次扣减多个商品的库存
void test4 ( ) { StringBuilder sb = new StringBuilder ( ) ; sb. append ( " local table = {} " ) ; sb. append ( " local values = redis.call('mget', unpack(KEYS) )" ) ; sb. append ( " for i = 1, #KEYS do " ) ; sb. append ( " if tonumber(ARGV[i]) > tonumber(values[i]) then " ) ; sb. append ( " table[#table + 1] = KEYS[i] .. '=' .. values[i] " ) ; sb. append ( " end " ) ; sb. append ( " end " ) ; sb. append ( " if #table > 0 then " ) ; sb. append ( " return table " ) ; sb. append ( " end " ) ; sb. append ( " for i = 1 , #KEYS do " ) ; sb. append ( " redis.call('decrby',KEYS[i],ARGV[i]) " ) ; sb. append ( " end " ) ; sb. append ( " return {} " ) ; RedisScript < List > luaScript = RedisScript . of ( sb. toString ( ) , List . class ) ; List < StockProduct > stockProducts = new ArrayList < > ( ) ; stockProducts. add ( new StockProduct ( 5 , 1 ) ) ; stockProducts. add ( new StockProduct ( 4 , 2 ) ) ; List < String > keys = stockProducts. stream ( ) . map ( it -> "product." + it. getId ( ) ) . collect ( Collectors . toList ( ) ) ; Object [ ] qtys = stockProducts. stream ( ) . map ( it -> it. getQty ( ) + "" ) . toArray ( ) ; List < String > list = stringRedisTemplate. execute ( luaScript, keys, qtys) ; if ( list. isEmpty ( ) ) { System . out. println ( "库存冻结成功" ) ; } else { for ( String key_qty : list) { String [ ] split = key_qty. split ( "=" ) ; System . out. println ( split[ 0 ] + "库存不足,剩余库存量:" + split[ 1 ] ) ; } } ThreadUtil . safeSleep ( 3000 ) ; }