package com.example.redisdistlock.controller;

import com.example.redisdistlock.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RestController; import java.util.HashMap;
import java.util.Map; @RestController
public class CacheController { @Autowired
private StringRedisTemplate stringRedisTemplate = null; @Autowired
private RedisUtil redisUtil = null; /**
* ****************************** 缓存穿透 ******************************
* 缓存穿透,是指查询一个数据库一定不存在的数据。
* 正常的使用缓存流程大致是,数据查询先进行缓存查询,
* 如果key不存在或者key已经过期,再对数据库进行查询,
* 并把查询到的对象,放进缓存。如果数据库查询对象为空,则不放进缓存。
* 灾难现场:想象一下这个情况,如果传入的参数为-1,会是怎么样?这个-1,就是一定不存在的对象。就会每次都去查询数据库,
* 而每次查询都是空,每次又都不会进行缓存。假如有恶意攻击,就可以利用这个漏洞,对数据库造成压力,甚至压垮数据库。
* 解决方案:如果从数据库查询的对象为空,也放入缓存,只是设定的缓存过期时间较短,比如设置为60秒。
*/ /**
* ****************************** 缓存雪崩 ******************************
* 是指在某一个时间段,缓存集中过期失效。此刻无数的请求直接绕开缓存,直接请求数据库。
* 灾难现场:比如天猫双11,马上就要到双11零点,很快就会迎来一波抢购,这波商品在23点集中的放入了缓存,假设缓存一个小时。
* 那么到了凌晨24点的时候,这批商品的缓存就都过期了。而对这批商品的访问查询,都落到了数据库上,对于数据库而言,就会产生周期性的压力波峰。
* 对数据库造成压力,甚至压垮数据库。
*/ /**
* ****************************** 缓存击穿 ******************************
* 是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。
* 灾难现场:比如某个爆款商品(这种爆款很难对数据库服务器造成压垮性的压力。达到这个级别的公司没有几家的。)但我们也要做好防护方案
* 解决方案:对爆款商品都是早早的做好了准备,让缓存永不过期。即便某些商品自己发酵成了爆款,也是直接设为永不过期。
*/ public Object cacheBreakDown(){
Map<String, Object> map = new HashMap<String, Object>();
try {
Object zhangsan = redisUtil.get("zhangsan");
//System.out.println("zhangsan" + zhangsan); /* 使用双重验证锁解决高并发环境下的缓存穿透问题 */
if (StringUtils.isEmpty(zhangsan)) { // 第一重验证
synchronized (this) {
zhangsan = redisUtil.get("zhangsan");
if (StringUtils.isEmpty(zhangsan)) { // 第二重验证
System.out.println("查询数据库............");
// 缓存为空,则查询数据库将相关数据存储到redis中
redisUtil.set("zhangsan", "张三",10); //10秒后过期
} else {
System.out.println("2 查询缓存............");
}
}
} else {
System.out.println("1 查询缓存............");
} map.put("success", true); ////entity实体类
//User user = new User();
//user.setUserId(1000);
//user.setUserName("张三");
//user.setAddress("深圳市南山区");
//user.setMobile("13988886666");
//redisUtil.set("userInfo", user.toString(), 10); //10秒后过期自动删除
////获取显示
//String str = String.valueOf(redisUtil.get("userInfo"));
//JSONObject jsonObj = new JSONObject(str);
//map.put("userInfo", jsonObj.get("userId"));
} catch (Exception e) {
map.put("success", false);
e.printStackTrace();
} finally {
}
return map;
}
}
    /**
* Redis分布式并发锁(针对业务场景:库存超卖 秒杀 限购等)
*
* @return
*/
@RequestMapping("/reductstore")
@ResponseBody //直接输出字符串
public String ReductStore() {
System.out.println("访问接口");
String lockKey = "lock"; // setnx redisson
RLock lock = redissonClient.getLock(lockKey);
try { int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock")); lock.lock();
if (stock > 0) {
//业务逻辑减少库存
stringRedisTemplate.opsForValue().set("stock", (stock - 1) + "");
System.out.println("扣减库存成功,库存stock:" + (stock - 1));
} else {
System.out.println("商品已售罄");
}
} catch (NumberFormatException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
return "OK";
} /**
* 单体式架构
*
* @return
*/
@RequestMapping("/reduct")
@ResponseBody //直接输出字符串
public String Reduct() {
//System.out.println("访问接口");
try {
synchronized (this) { //jvm核心技术
int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock"));
if (stock > 0) {
//业务逻辑减少库存
stringRedisTemplate.opsForValue().set("stock", (stock - 1) + "");
System.out.println("扣减库存成功,库存stock:" + (stock - 1));
} else {
System.out.println("商品已售罄");
}
}
} catch (NumberFormatException e) {
e.printStackTrace();
} finally {
}
return "OK";
}

  

Java Redis缓存穿透/缓存雪崩/缓存击穿,Redis分布式锁实现秒杀,限购等的更多相关文章

  1. 缓存穿透、雪崩、热点与Redis

    (拼多多问:Redis雪崩解决办法) 导读:互联网系统中不可避免要大量用到缓存,在缓存的使用过程中,架构师需要注意哪些问题?本文以 Redis 为例,详细探讨了最关键的 3 个问题. 一.缓存穿透预防 ...

  2. Redis缓存穿透和雪崩

    缓存穿透 用户想要查询一个数据 在redis缓存数据库中没有获取到 就会向后端的数据库中查询. 当用户很多 都去访问后端数据库的话,这就会给数据库带来很大的压力. 常见场景:秒杀活动 等 解决方法: ...

  3. Redis系列(八)--缓存穿透、雪崩、更新策略

    1.缓存更新策略 1.LRU/LFU/FIFO算法剔除:例如maxmemory-policy 2.超时剔除,过期时间expire,对于一些用户可以容忍延时更新的数据,例如文章简介内容改了几个字 3.主 ...

  4. redis的穿透和雪崩

    穿透: 从缓存中查询一个数据,查到为空,需要每次都去数据库中查询.而从数据库中查询出来也为空,也就不写入缓存.导致一个不存在的数每次都去数据库中查询,造成db系统很大压力 造成缓存穿透 解决:如果从数 ...

  5. Java之——redis并发读写锁,使用Redisson实现分布式锁

    原文:http://blog.csdn.net/l1028386804/article/details/73523810 1. 可重入锁(Reentrant Lock) Redisson的分布式可重入 ...

  6. 基于redis分布式锁实现“秒杀”

    转载:http://blog.5ibc.net/p/28883.html 最近在项目中遇到了类似“秒杀”的业务场景,在本篇博客中,我将用一个非常简单的demo,阐述实现所谓“秒杀”的基本思路. 业务场 ...

  7. 分布式锁实现秒杀 - 基于redis实现

    业务场景 所谓秒杀,从业务角度看,是短时间内多个用户“争抢”资源,这里的资源在大部分秒杀场景里是商品:将业务抽象,技术角度看,秒杀就是多个线程对资源进行操作,所以实现秒杀,就必须控制线程对资源的争抢, ...

  8. 基于redis分布式锁实现“秒杀”(转载)

    转载:http://blog.csdn.net/u010359884/article/details/50310387 最近在项目中遇到了类似“秒杀”的业务场景,在本篇博客中,我将用一个非常简单的de ...

  9. Redis 当成数据库在使用和可靠的分布式锁,Redlock 真的可行么?

    怎样做可靠的分布式锁,Redlock 真的可行么? https://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html ...

随机推荐

  1. 在有多个网卡,配置了多个IP的情况下,python 获取本地网卡的主IP

    如图所示有多个网卡 本地网卡配置了多个IP class Public_IPOp: @staticmethod def GetLocalIP(): rt = [False] # 根节点 reg_root ...

  2. DHCP服务器的架设

    DHCP服务器的架设 一.DHCP服务器的安装要求: 搭建DHCP服务器需要一些必备条件支持,主要有以下方面: 需要一台运行Windows Server系统的服务器,并为其指定静态IP地址. 根据子网 ...

  3. [AIR] NativeExtension在IOS下的开发实例 --- Flex库项目的创建(二)

    来源:http://bbs.9ria.com/thread-102038-1-1.html 上一章,我已经介绍了如果创建IOS库文件,并定义了两个方法ShowIconBadageNumber和Init ...

  4. BBPlus团队ALPFA冲刺(肖文恒)

    ALPHA冲刺博客 第一天:https://www.cnblogs.com/bbplus/p/11931039.html 第二天:https://www.cnblogs.com/bbplus/p/11 ...

  5. PyCharm-安装&调试

    windows安装pycharm 和python的链接: PyCharm:http://www.jetbrains.com/pycharm/ Python:https://www.python.org ...

  6. SQL SERVER-CROSS APPLY

    CROSS APPLY和 OUTER APPLY 区别详解 SQL Server 2005 新增 cross apply 和 outer apply 联接语句,增加这两个东东有啥作用呢? 我们知道有个 ...

  7. Mysql修改binlog日志过期时间

    1.临时生效 # 查看默认设置的过期时间 show variables like "%expire_logs%"; # 设置保留15天 set global expire_logs ...

  8. linux系统编程之文件与io(二)

    今天继续学习文件与io,话不多说,开始进入正题: 文件的read和write系统调用: 说明:函数中出现在size_t和ssize_t是针对系统定制的数据类型:     下面以一个实现文件简单拷贝的示 ...

  9. vue-(过滤器,钩子函数,路由)

    1.局部过滤器 在当前组件内部使用过滤器,修饰一些数据 //声明 filters:{ '过滤器的名字':function(val,a,b){ //a 就是alax ,val就是当前的数据 } } // ...

  10. MySQL 索引原理及慢查询优化

    MySQL凭借着出色的性能.低廉的成本.丰富的资源,已经成为绝大多数互联网公司的首选关系型数据库.虽然性能出色,但所谓“好马配好鞍”,如何能够更好的使用它,已经成为开发工程师的必修课,我们经常会从职位 ...