intitle 网站建设,wordpress 不提示更新,wordpress4.9.8优化,软装设计师需要具备的能力redis分布式锁故事背景什么是Redis分布式锁业务场景未加任何锁的代码单机情况下JVM级别加锁多服务部署总结提升故事背景
本篇文章是redis实战系列的第二篇文章。本章的主要内容是Redis分布式锁的相关知识。本篇文章将告诉你什么是分布式锁#xff0c;结合一个业务场景#x…
redis分布式锁故事背景什么是Redis分布式锁业务场景未加任何锁的代码单机情况下JVM级别加锁多服务部署总结提升故事背景
本篇文章是redis实战系列的第二篇文章。本章的主要内容是Redis分布式锁的相关知识。本篇文章将告诉你什么是分布式锁结合一个业务场景先带大家看看单机上是如何实现锁功能的。学完本篇你可以了解到什么是锁为什么要加锁。
什么是Redis分布式锁
Redis分布式锁是一种基于Redis实现的分布式锁机制它可以保证在分布式环境中同一时刻只有一个客户端能够获取到锁从而避免了多个客户端同时对同一资源进行修改的问题。 接下来我将结合一个秒杀的例子讲述如果实现Redis的分布式锁。
业务场景
秒杀场景是一个非常经典的需要使用锁的场景。 假设有一个商品限时秒杀的业务场景多个用户同时在秒杀开始时间内尝试购买该商品但是该商品数量有限只有一定数量的用户可以购买成功其他用户则购买失败。 为了保证秒杀的公平性与真确性这个时候我们就要通过锁来对商品的数量进行访问
未加任何锁的代码
结合上面的业务场景我们来先来实现一个未加任何锁的代码简单实现一下这个小需求
首先在redis里添加了 key值为 stock value值 为 200 的数据模拟我们要秒杀的商品数量为200 2.编写业务逻辑代码
RestController
RequestMapping(/test)
public class IndexController {// 自动注入 StringRedisTemplate 对象Autowiredprivate StringRedisTemplate stringRedisTemplate;// 处理 HTTP GET 请求路径是 /test/lockGetMapping(lock)public String deductStock() {// 获取当前库存String stock1 stringRedisTemplate.opsForValue().get(stock);if( stock1 null){System.out.println(秒杀未开始);return end;}int stock Integer.parseInt(stringRedisTemplate.opsForValue().get(stock));if (stock 0) {// 扣减库存int realStock stock - 1;// 更新库存stringRedisTemplate.opsForValue().set(stock, realStock );System.out.println(扣减成功剩余的库存为 realStock);} else {System.out.println(扣减失败库存不足);}return end;}}
上述是根据我们的业务进行的一个简单的实现在这个实现里未对代码进行加锁。这段代码将会出现很经典的超卖问题。我们来压测一下接口看一下效果 3. 接口压测模拟并发 在这里我们使用的ApiPost进行一键压测。让我们一起来看一下结果吧 我们发现50个请求进来之后如果是正常的情况下是应该减少50个库存每个请求获得1个商品。可以根据结果看我们的50个请求获得了5个商品。同一个商品卖给了多个用户。列如 195号商品同时卖给了10个人。 那么我们该如何去解决这个问题呢
单机情况下JVM级别加锁
首先我们来看一下如果是单机项目只部署在一台机器上如何给我们的代码加锁解决上述问题。 使用 synchronized 进行jvm级别加锁。
代码
synchronized (this){// 获取当前库存String stock1 stringRedisTemplate.opsForValue().get(stock);if( stock1 null){System.out.println(秒杀未开始);return end;}int stock Integer.parseInt(stringRedisTemplate.opsForValue().get(stock));if (stock 0) {// 扣减库存int realStock stock - 1;// 更新库存stringRedisTemplate.opsForValue().set(stock, realStock );System.out.println(扣减成功剩余的库存为 realStock);} else {System.out.println(扣减失败库存不足);}}代码非常的简单使用 synchronized 关键字将我们的业务逻辑进行包裹即可。 synchronized保证同一时刻只有一个线程执行被synchronized修饰的代码块或方法从而避免多个线程同时对共享资源进行修改而导致的数据不一致的问题。 2. 运行结果 从结果上来看通过synchronized 可以在jvm级别上进行上锁。但是我们实际的生产环境中很少有部署单机服务的。如果我们部署了多个服务那么通过synchronized 是肯定无法影响另一条机器上的请求的。
多服务部署 假设我们部署了两个服务部署在tomcat1和tomcat2上使用nginx做负载。此时仅仅通过synchronized 只能保持 tomcat1自己本身。tomcat2自己本身的数据被锁住。如果两个服务同时提供服务仍然会产生我们上述的超卖问题。
总结提升
本文我们主要讲了锁的概念为什么要加锁单机上jvm级别的加锁多服务部署的话我们现在的代码存在的问题。接下来我会讲解如何解决我们这次遗留的问题在分布式环境下如何加锁如何解决可能会存在的问题。 专栏地址