redis应用场景之秒杀

redis应用场景之秒杀

redis是一种nosql数据库,多用于网页的缓存,在电商网站的秒杀场景下,频繁访问数据库导致性能的降低,将商品信息存储在redis中是一种可行的方案,并且redis可以添加失效时间,是秒杀场景最佳的数据库选择之一。

redis配置

@Configuration
public class RedisConfig {

    //读取配置文件中的redis的ip地址
    @Value("${spring.redis.host:disabled}")
    private String host;

    @Value("${spring.redis.port:0}")
    private int port;

    @Value("${spring.redis.database:0}")
    private int database;

    @Bean
    public RedisUtil getRedisUtil(){
        if(host.equals("disabled")){
            return null;
        }
        RedisUtil redisUtil=new RedisUtil();
        redisUtil.initPool(host,port,database);
        return redisUtil;
    }

}

redis工具包

public class RedisUtil {

    private JedisPool jedisPool;

    public void initPool(String host,int port ,int database){
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(200);
        poolConfig.setMaxIdle(30);
        poolConfig.setBlockWhenExhausted(true);
        poolConfig.setMaxWaitMillis(10*1000);
        poolConfig.setTestOnBorrow(true);
        jedisPool=new JedisPool(poolConfig,host,port,20*1000);
    }

    public Jedis getJedis(){
        Jedis jedis = jedisPool.getResource();
        return jedis;
    }

}

使用redis进行秒杀

使用redis的事物和watch指令实现秒杀。使用watch是由于redis的事物与mysql等不同,出现异常后并不会回滚,而watch正好可以为Redis事务提供 check-and-set (CAS)行为,如果监视的键发现异常则事物会失效。

@Controller
public class SeckillController {
	@Autowired
    RedisUtil redisUtil;
/***
     * 拼手气秒杀
     * @return
     */
    @RequestMapping("kill")
    @ResponseBody
    public String kill() {
        // 开启商品的监控
        Jedis jedis = redisUtil.getJedis();
        jedis.watch("订单号");
        int stock = Integer.parseInt(jedis.get("订单号"));

        if (stock > 0) {

            Transaction multi = jedis.multi();// 开启事物
            multi.incrBy("订单号", -1);
            List<Object> exec = multi.exec();

            if (exec != null && exec.size() > 0) {
                System.out.println("success," + "库存数量" + stock);
            } else {
                System.out.println("fail");
            }

        }

        jedis.close();

        return null;
    }
  }

使用redisson

配置

@Configuration

public class RedissonConfig {

    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private String port;

    @Bean
    public RedissonClient redissonClient(){
        Config config = new Config();
        config.useSingleServer().setAddress("redis://"+host+":"+port);
        RedissonClient redisson = Redisson.create(config);
        return redisson;
    }
}

秒杀

@Controller
public class SeckillController {

    @Autowired
    RedissonClient redissonClient;

    /***
     * 先到先得式秒杀
     * @return
     */
    @RequestMapping("secKill")
    @ResponseBody
    public String secKill(){

        Jedis jedis = redisUtil.getJedis();

        int stock = Integer.parseInt(jedis.get("订单号"));

        RSemaphore semaphore = redissonClient.getSemaphore("订单号");
        boolean acquire = semaphore.tryAcquire();

        if (acquire){

            System.out.println("success," + "库存数量" + stock);
           
        } else {
            System.out.println("fail");
        }

        jedis.close();

        return null;
    }
}


版权声明:本文为weixin_42968620原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。