分布式锁的引入
一个很典型的秒杀场景,或者说并发量非常高的场景下,对商品库存的操作,我用一个SpringBoot小项目模拟一下。
用到的技术知识:
- SpringBoot
- Redis
- ZooKeeper
我提前将库存 stock 放在redis,初始值为288:
127.0.0.1:6379> set stock 288 OK 127.0.0.1:6379> get stock "288" 复制代码
扣减库存的api:
@RequestMapping("/v1/reduce") public String reduceStock() { String stockStr = redisTemplate.opsForValue().get("stock"); int stock = Integer.parseInt(stockStr); if (stock > 0) { int realStock = stock - 1; redisTemplate.opsForValue().set("stock", String.valueOf(realStock)); System.out.println(Thread.currentThread().getName() + " 减库存成功,剩余库存:" + realStock); } else { System.out.println("不能再减了,没有库存了!"); } return port + ": reduce stock end"; } 复制代码
单机环境下的高并发:
我用 Apache JMeter 模拟在同一时刻,有 500 个请求打到 /stock/v1/reduce
上进行减库存的操作:
Apache JMeter是Apache组织开发的基于Java的压力测试工具。用它很容易模拟出高并发场景。
Apache JMeter官网: jmeter.apache.org/download_jm…
启动SpringBoot项目,执行压测,运行结果:
500个并发,才扣减了5个!!!BOSS该找你事了!
不过这种情况我们程序员是不会让它出现的,加个 synchronized ,让每个线程拿到锁之后再去扣减库存:
代码实现:
@RequestMapping("/v2/reduce") public String reduceStockV2() { //加线程同步 synchronized (this) { String stockStr = redisT