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版权协议,转载请附上原文出处链接和本声明。