java基于redis事务的秒杀实现详解编程语言

package com.vian.user.service; 
 
import org.junit.Test; 
import org.springframework.util.CollectionUtils; 
import redis.clients.jedis.Jedis; 
import redis.clients.jedis.JedisPool; 
import redis.clients.jedis.JedisPoolConfig; 
import redis.clients.jedis.Transaction; 
 
import java.io.IOException; 
import java.util.List; 
import java.util.concurrent.CountDownLatch; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
 
/** 秒杀测试 */ 
public class SecondKillTest { 
  @Test 
  public void getResult() { 
    Jedis jedis = JedisPoolUtil.getJedis(); 
    String goodsResult = jedis.get("goodsResult:user102"); 
    System.out.println(goodsResult); 
  } 
 
  @Test 
  public void test() throws IOException, InterruptedException { 
    /** 初始化商品 */ 
    initGoods(); 
 
    /** 1000线程抢购100个商品 */ 
    ExecutorService executorService = Executors.newFixedThreadPool(20); 
    CountDownLatch count = new CountDownLatch(10000); 
    long startTime = System.currentTimeMillis(); 
    for (int i = 0; i < 10000; i++) { 
      executorService.execute(new SecondKillHandlder("user" + i)); 
      count.countDown(); 
    } 
    executorService.shutdown(); 
    count.await(); 
    long time = System.currentTimeMillis() - startTime; 
    System.out.println("共耗时:" + time + "毫秒"); 
    // JedisPoolUtil.close(); 
    System.in.read(); 
  } 
 
  /** 初始化商品数量 */ 
  private void initGoods() { 
    Jedis jedis = JedisPoolUtil.getJedis(); 
    jedis.set("goods:iphone8", "100"); // 设置100个商品 
    JedisPoolUtil.returnRes(jedis); 
  } 
 
  /** 秒杀处理线程 */ 
  private static class SecondKillHandlder implements Runnable { 
    String goodsKey = "goods:iphone8"; // 监视的key 当前秒杀商品的数量 
    Jedis jedis; 
    String userName; 
 
    public SecondKillHandlder(String userName) { 
      this.userName = userName; 
    } 
 
    @Override 
    public void run() { 
      while (true) { 
        try { 
          jedis = JedisPoolUtil.getJedis(); 
          // watch 监视一个key,当事务执行之前这个key发生了改变,事务会被打断 
          jedis.watch(goodsKey); 
          int currentGoodsCount = Integer.parseInt(jedis.get(goodsKey)); // 当前剩余商品数量 
          if (currentGoodsCount <= 0) { 
            System.out.println("商品已抢完," + userName + "---> 抢购失败 XXX"); 
            break; 
          } 
          Transaction tran = jedis.multi(); // 开启事务 
          tran.incrBy(goodsKey, -1); // 商品数量-1 
          List<Object> exec = tran.exec(); // 执行事务 
          if (CollectionUtils.isEmpty(exec)) { 
            System.out.println(userName + "---> 抢购失败,继续抢购"); 
            Thread.sleep(1); 
          } else { 
            exec.forEach( 
                succ -> { 
                  String succStr = 
                      userName 
                          + "===========================> 抢购到第【" 
                          + ((100 - currentGoodsCount) + 1) 
                          + "】份商品,该商品剩余:" 
                          + succ.toString(); 
                  System.out.println(succStr); 
                  jedis.set("goodsResult:" + userName, succStr); // 业务代码,处理抢购成功 
                }); 
            break; 
          } 
        } catch (Exception e) { 
          e.printStackTrace(); 
        } finally { 
          if (jedis != null) { 
            jedis.unwatch(); 
            JedisPoolUtil.returnRes(jedis); 
          } 
        } 
      } 
    } 
  } 
 
  private static class JedisPoolUtil { 
    private static JedisPool pool; 
 
    private static void createJedisPool() { 
      // 建立连接池配置参数 
      JedisPoolConfig config = new JedisPoolConfig(); 
      // 设置最大连接数 
      config.setMaxTotal(100); 
      // 设置最大阻塞时间,记住是毫秒数milliseconds 
      config.setMaxWaitMillis(1000); 
      // 设置空间连接 
      config.setMaxIdle(10); 
      // 创建连接池 
      pool = new JedisPool(config, "192.168.31.201", 6379, 2000, null, 3); 
    } 
 
    /** 在多线程环境同步初始化 */ 
    private static synchronized void poolInit() { 
      if (pool == null) createJedisPool(); 
    } 
 
    /** 
     * 获取一个jedis 对象 
     * 
     * @return 
     */ 
    public static Jedis getJedis() { 
 
      if (pool == null) poolInit(); 
      return pool.getResource(); 
    } 
 
    /** 
     * 归还一个连接 
     * 
     * @param jedis 
     */ 
    public static void returnRes(Jedis jedis) { 
      pool.returnResource(jedis); 
    } 
 
    public static void close() { 
      pool.close(); 
    } 
  } 
}

 

java基于redis事务的秒杀实现详解编程语言

java基于redis事务的秒杀实现详解编程语言

 

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/16945.html

(0)
上一篇 2021年7月19日 19:46
下一篇 2021年7月19日 19:46

相关推荐

发表回复

登录后才能评论