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. opencv 源码分析 CUDA可分离滤波器设计 ( 发现OpenCV的cuda真TM慢 )

    1. 主函数 void SeparableLinearFilter::apply(InputArray _src, OutputArray _dst, Stream& _stream) { G ...

  2. Dubbo的10种集群容错模式

    学习Dubbo源码的过程中,首先看到的是dubbo的集群容错模式,以下简单介绍10种集群容错模式 1.AvailableCluster 顾名思义,就是可用性优先,遍历所有的invokers,选择可用的 ...

  3. python多进程间通信

    这里使用pipe代码如下: import time from multiprocessing import Process import multiprocessing class D: @stati ...

  4. python下调用c语言代码

    1)首先,创建一个.c文件,其大体内容如下: 2 #include <Python.h> 99 char * extract(char * path)                    ...

  5. C#-判断字符是否是全角半角

    C#字符串的全角是指用二个字节来表示的一个字符 C#字符串的半角是用一个字节来表示的一个字符 这样的话我们就可以用string.length 和System.text.Encoding.Default ...

  6. Linux命令——sync

    参考:A Step-By-Step Guide to Using the Linux sync Command 前言 数据只有被读入内存才能被CPU所处理,但是数据又常常需要由内存写回磁盘当中(例如储 ...

  7. 创建htpasswd文件在nginx (没有 apache)

    Create htpasswd file for nginx (without apache) APACHE NGINX HTACCESS If you're like me, and use Ngi ...

  8. ubuntu---画图工具(类似win中的画图软件)

    参考 https://zhidao.baidu.com/question/622412096845238452.html https://jingyan.baidu.com/article/6525d ...

  9. java线程基础巩固---分析Thread的join方法详细介绍,结合一个典型案例

    关于Thread中的join方法貌似在实际多线程编程当中没怎么用过,在当初学j2se的时候倒时去学习过它的用法,不过现在早已经忘得差不多啦,所以对它再复习复习下. 首先先观察下JDK对它的介绍: 其实 ...

  10. vue之获取原生的dom的方式

    1.获取原生的DOM的方式 <!DOCTYPE html> <html lang="en"> <head> <meta charset=& ...