当前位置:网站首页>redis分布式锁
redis分布式锁
2022-08-11 05:12:00 【匿名热心市民】
压测工具JMeter





测试

我们看到同一个库存被使用了n次。以及数据库中库存为负数。 线程安全问题导致。
使用 synchronized 或者lock锁
解决方案: 使用 synchronized 或者lock锁
package com.ykq.distrinctlock.service.impl;
import com.ykq.distrinctlock.dao.ProductStockDao;
import com.ykq.distrinctlock.service.ProductStockService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ProductStockServiceImpl2 implements ProductStockService {
@Autowired
private ProductStockDao productStockDao;
@Override
public String decreaseStock(Integer productId) {
synchronized (this) {
//查看该商品的库存数量
Integer stock = productStockDao.findStockByProductId(productId);
if (stock > 0) {
//修改库存每次-1
productStockDao.updateStockByProductId(productId);
System.out.println("扣减成功!剩余库存数:" + (stock - 1));
return "success";
} else {
System.out.println("扣减失败!库存不足!");
return "fail";
}
}
}
}使用synchronized 或者lock锁 如果我们搭建了项目集群,那么该锁无效。
使用idea开集群项目





Win版nginx使用



重新测试

发现又出现: 重复数字以及库存为负数。
解决:
将redis作为锁使用

redis的解决分布式锁的bug。
Redis分布式锁不能解决超时的问题,分布式锁有一个超时时间,程序的执行如果超出了锁的超时时间就会出现问题。

解决方案:
可以使用:redission依赖,redission解决redis超时问题的原理。
redission分布式锁

为持有锁的线程开启一个守护线程,守护线程会每隔10秒检查当前线程是否还持有锁,如果持有则延迟生存时间。
添加依赖
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.13.4</version>
</dependency>添加配置类
获取redisson对象并交于spring容器管理
@Bean
public Redisson redisson(){
Config config =new Config();
config.useSingleServer().
setAddress("redis://localhost:6379").
//redis默认有16个数据库
setDatabase(0);
return (Redisson) Redisson.create(config);
}
加锁
@Service
public class ProductStockServiceImpl_redission implements ProductStockService {
@Autowired
private ProductStockDao productStockDao;
@Autowired
/*获取Redisson对象*/
private Redisson redisson;
@Override
public String decreaseStock(Integer productId) {
/*获取锁对象*/
RLock mylock = redisson.getLock("abc::"+productId);
try {
/*设置锁时长*/
mylock.lock(30, TimeUnit.SECONDS);
//查看该商品的库存数量
Integer stock = productStockDao.findStockByProductId(productId);
if (stock > 0) {
//修改库存每次-1
productStockDao.updateStockByProductId(productId);
System.out.println("扣减成功!剩余库存数:" + (stock - 1));
return "success";
} else {
System.out.println("扣减失败!库存不足!");
return "fail";
}
}finally {
/*释放锁*/
mylock.unlock();
}
}
}
结果

缓存穿透
1. 数据库中没有该记录,缓存中也没有该记录,这时由人恶意大量访问这样的数据。这样就会导致该请求绕过缓存,直接访问数据,从而造成数据库压力过大。
解决办法
[1]在controller加数据校验。
[2]我们可以在redis中存入一个空对象,而且要设置过期时间不能太长。超过5分钟
[3]我们使用布隆过滤器。底层:有一个bitmap数组,里面存储了该表的所有id.
存入空对象方式
这样他就进不去数据库了

布隆过滤器
//伪代码
String get(String key) { //布隆过滤器钟存储的是数据库表钟对应的id
String value = redis.get(key); //先从缓存获取。
if (value == null) { //缓存没有命中
if(!bloomfilter.mightContain(key)){//查看布隆过滤器钟是否存在
return null;
}else{
value = db.get(key); //查询数据库
redis.set(key, value);
}
}
return value;
}缓存击穿
缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。
缓存击穿解决方案:
1.设置永久不过期。【这种只适合内存】
2.使用互斥锁(mutex key)业界比较常用的做法。

缓存雪崩
缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是, 缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
1.什么下会发生缓存雪崩:
[1]项目刚上线,缓存中没有任何数据
[2]缓存出现大量过期。
[3]redis宕机
2.解决办法:
1.上线前预先把一些热点数据放入缓存。
2.设置过期时间为散列值
3.搭建redis集群
Redis 淘汰策略有哪些

边栏推荐
- 你务必得明白——JSP的九大内置对象与四大域对象
- Development Tools Lecture 7: Alibaba Cloud Log Query and Analysis
- 交换机和路由器技术-31-扩展ACL
- oracle表空间与用户的创建
- C语句:数据存储
- [No 2022 Shanghai Security Officer A Certificate Exam Question Bank and Mock Exam
- Idea essential skills to improve work efficiency
- MySQL存储引擎概念
- 2021年网络规划设计师下午案例题
- 2022 Quality Officer-Civil Construction Direction-General Basic (Quality Officer) Exam Mock 100 Questions and Online Mock Exam
猜你喜欢

交换机和路由器技术-30-标准ACL

网络技能树

关于ie下href有中文出现RFC 7230 and RFC 3986问题的研究

Switch and Router Technology-27-OSPF Route Redistribution

玩转mysql之查看mysql版本号
![[Embedded open source library] The use of MultiButton, an easy-to-use event-driven button driver module](/img/7b/e265305df01eb405a131d0de2154d3.png)
[Embedded open source library] The use of MultiButton, an easy-to-use event-driven button driver module

【嵌入式开源库】MultiTimer 的使用,一款可无限扩展的软件定时器

BGP综合实验

Switches and routers technologies - 30 - standard acls

应用层协议——DNS
随机推荐
交换机和路由器技术-32-命名ACL
paddlepaddle implements CS_CE Loss and incorporates PaddleClas
论文笔记:BBN: Bilateral-Branch Network with Cumulative Learningfor Long-Tailed Visual Recognition
你务必得明白——JSP的九大内置对象与四大域对象
ERROR: Could not install packages due to an OSError: [Errno 2] 没有那个文件或目录: ‘/data/xxxx
Application layer protocol - DNS
MySQL存储引擎概念
用白嫖的Adobe正版软件,减少应届毕业生的慢就业、不就业等现象
让你代码越来越高大上的技巧——代码规范,你得知道
HAVE FUN | “SOFA 星球”飞船计划、源码解析活动最新进展
Switches and routers technology - 26 - configure OSPF peripheral area
Idea essential skills to improve work efficiency
K8s复习笔记7--Redis单机和Redis-cluster的K8S实现
每周推荐短视频:你常用的拍立淘,它的前身原来是这样的!
宝塔Linux环境下redis开启多端口
You must understand - the nine built-in objects and four domain objects of JSP
2.2 user manual] [QNX Hypervisor 10.15 vdev timer8254
分库分表ShardingSphere-JDBC笔记整理
【ARM】rk3399挂载nfs报错
[No 2022 Shanghai Security Officer A Certificate Exam Question Bank and Mock Exam