利用redis的lua实现防止超买的一段小程序(和测试程序在一起)

private static AtomicLong salesCount = new AtomicLong(100000);

 private final String updateStockHold = "local key = KEYS[1] \n"

 + "local count = ARGV[1] \n"

 + "redis.call('decrby', key, count) \n"

 + "local afterCount = redis.call('get', key) \n"

 + "if (tonumber(afterCount) < 0) then \n"

 + " redis.call('incrby', key, count) \n"

 + " return afterCount \n"

 + "else \n"

 + " return afterCount \n"

 + "end \n";


 @Test

 public void testRedisService() throws InterruptedException, BrokenBarrierException {

        Jedis jedis = setupSentinelPool();

 jedis.set("iphone_count", "100000");


 final CyclicBarrier cyclicBarrier =new CyclicBarrier(21);

 ExecutorService executorService = Executors.newFixedThreadPool(20);

 int times = 20;

 while (times > 0) {

            Thread.sleep(10);

 executorService.submit(new Runnable() {

                @Override

 public void run() {

                    Jedis jedis = setupSentinelPool();

 int runTimes = 3000;

 try {

                        cyclicBarrier.await();

 } catch (InterruptedException e) {

                        e.printStackTrace();

 } catch (BrokenBarrierException e) {

                        e.printStackTrace();

 }

                    while (runTimes > 0) {

                        int count = 1;

 String luaAcquireLockSHA = jedis.scriptLoad(updateStockHold);

 Object obj = jedis.evalsha(luaAcquireLockSHA, 1, "iphone_count", String.valueOf(count));

 System.out.println("After Update Count:" + obj);

// System.out.println("After Update Count : " + jedis.get("iphone_count"));

 runTimes--;

 if (Long.parseLong(obj.toString()) >= 0) {

                            salesCount.addAndGet(-1);

 }else {

                            break;

 }

                        if(Thread.currentThread().isInterrupted()){

                            break;

 }

                    }

                }

            });

 times--;

 }

        cyclicBarrier.await();

 System.out.println("Start Time Unit " + new Date());

 executorService.awaitTermination(1, TimeUnit.SECONDS);

 executorService.shutdownNow();

 System.out.println("End Time Unit " + new Date());


 Thread.sleep(100);

 System.out.println("Final Result : " + jedis.get("iphone_count"));

 System.out.println("Final Result Expected: " + salesCount.get());


 }


    private Jedis setupSentinelPool() {

        try {

            // 1.配置Apache-Commons连接池属性

 GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();

 poolConfig.setMaxTotal(1);

 poolConfig.setMaxIdle(1);

 poolConfig.setMinIdle(1);

 poolConfig.setBlockWhenExhausted(true);

 poolConfig.setMaxWaitMillis(500);

 poolConfig.setLifo(false);

 poolConfig.setTestOnBorrow(false);

 poolConfig.setTestOnReturn(false);

 poolConfig.setTestWhileIdle(true);

 poolConfig.setTimeBetweenEvictionRunsMillis(30000);

 poolConfig.setNumTestsPerEvictionRun(-1);

 poolConfig.setMinEvictableIdleTimeMillis(60);


 // 2.获取Sentinel地址

 String[] addrs = redisCacheConfig.getSentinels().split(";");

 Set<String> sentinelSet = new HashSet<String>();

 for (String addr : addrs) {

                sentinelSet.add("172.19.9.230:6601");

 }


            JedisSentinelPool pool = new JedisSentinelPool("mkt-cache", sentinelSet, poolConfig,

 2000, "redis1");

 logger.info("[CACHE]JedisSentinelPool init completed.");


 return pool.getResource();


 } catch (Throwable e) {

            // logger.error("[CACHE]init fail", e);

 throw new InitializationException("RedisClient init fail", e);

 } finally {


        }

    }


你可能感兴趣的:(利用redis的lua实现防止超买的一段小程序(和测试程序在一起))