一、缓存雪崩

缓存雪崩表示在某一时间段,缓存集中失效,导致请求全部走数据库,有可能搞垮数据库,使整个服务瘫痪。

使缓存集中失效的原因:

1、redis服务器挂掉了。

2、对缓存数据设置了相同的过期时间,导致某时间段内缓存集中失效。

如何解决缓存集中失效:

1、针对原因1,可以实现redis的高可用,Redis Cluster 或者 Redis Sentinel(哨兵) 等方案。

2、针对原因2,设置缓存过期时间时加上一个随机值,避免缓存在同一时间过期。

<?php

$redis = new Redis();
$redis->connect('127.0.0.1', 6379, 60);
$redis->auth(''); //设置过期时间加上一个随机值
$redis->set('article_content_1', '文章内容', 60 + mt_rand(1, 60));
$redis->set('article_content_2', '文章内容', 60 + mt_rand(1, 60));

3、使用双缓存策略,设置两个缓存,原始缓存和备用缓存,原始缓存失效时,访问备用缓存,备用缓存失效时间设置长点。

//原始缓存
$redis->set('article_content_2', '文章内容', 60);
//设置备用缓存,失效时间设置长点
$redis->set('article_content_backup_2', '文章内容', 1800);

二、缓存穿透

缓存穿透表示查询一个一定不存在的数据,由于没有获取到缓存,所以没写入缓存,导致这个不存在的数据每次都需要去数据库查询,失去了缓存的意义。

请求的数据大量的没有获取到缓存,导致走数据库,有可能搞垮数据库,使整个服务瘫痪。

比如文章表,一般我们的主键ID都是无符号的自增类型,有些人想要搞垮你的数据库,每次请求都用负数ID,而ID为负数的记录在数据库根本就没有。

解决方案:

1、对于像ID为负数的非法请求直接过滤掉,采用布隆过滤器(Bloom Filter)。

2、针对在数据库中找不到记录的,我们仍然将该空数据存入缓存中,当然一般会设置一个较短的过期时间。

//设置文章ID为-10000的缓存为空
$id = -10000;
$redis->set('article_content_' . $id, '', 60); var_dump($redis->get('article_content_' . $id));

  

三、缓存击穿

缓存击穿表示某个key的缓存非常热门,有很高的并发一直在访问,如果该缓存失效,那同时会走数据库,压垮数据库。

缓存击穿与缓存雪崩的区别是这里针对的是某一热门key缓存,而雪崩针对的是大量缓存的集中失效。

解决方案:

1、让该热门key的缓存永不过期。

2、使用互斥锁,通过redis的setnx实现互斥锁。

<?php

function getRedis()
{
$redis = new Redis();
$redis->connect('127.0.0.1', 6379, 60);
return $redis;
} //加锁
function lock($key, $random)
{
$redis = getRedis();
//设置锁的超时时间,避免释放锁失败,del()操作失败,产生死锁。
$ret = $redis->set($key, $random, ['nx', 'ex' => 3 * 60]);
return $ret;
} //解锁
function unLock($key, $random)
{
$redis = getRedis();
//这里的随机数作用是,防止更新缓存操作时间过长,超过了锁的有效时间,导致其他请求拿到了锁。
//但上一个请求更新缓存完毕后,如果不加判断直接删除锁,就会误删其他请求创建的锁。
if ($redis->get($key) == $random) {
$redis->del($key);
}
} //从缓存中获取文章数据
function getArticleInCache($id)
{
$redis = getRedis();
$key = 'article_content_' . $id;
$ret = $redis->get($key);
if ($ret === false) {
//生成锁的key
$lockKey = $key . '_lock';
//生成随机数,用于设置锁的值,后面释放锁时会用到
$random = mt_rand();
//拿到互斥锁
if (lock($lockKey, $random)) {
//这里是伪代码,表示从数据库中获取文章数据
$value = $db->getArticle($id);
//更新缓存,过期时间可以根据情况自已调整
$redis->set($key, $value, 2 * 60);
//释放锁
unLock($lockKey, $random);
} else {
//等待200毫秒,然后重新获取缓存值,让其他获取到锁的进程取得数据并设置缓存
usleep(200);
getArticleInCache($id);
}
} else {
return $ret;
}
}

redis缓存雪崩,缓存穿透,缓存击穿的解决方法的更多相关文章

  1. 8.了解什么是 redis 的雪崩、穿透和击穿?redis 崩溃之后会怎么样?系统该如何应对这种情况?如何处理 redis 的穿透?

    作者:中华石杉 面试题 了解什么是 redis 的雪崩.穿透和击穿?redis 崩溃之后会怎么样?系统该如何应对这种情况?如何处理 redis 的穿透? 面试官心理分析 其实这是问到缓存必问的,因为缓 ...

  2. redis缓存雪崩、穿透、击穿概念及解决办法

    缓存雪崩 对于系统 A,假设每天高峰期每秒 5000 个请求,本来缓存在高峰期可以扛住每秒 4000 个请求,但是缓存机器意外发生了全盘宕机.缓存挂了,此时 1 秒 5000 个请求全部落数据库,数据 ...

  3. Redis 缓存雪崩、穿透、击穿

    缓存雪崩 定义: 同一时间所有 key 大面积失效,比如网站首页的数据基本上都是同一批次去缓存的. 解决方法: ① 存的时候设定随机的失效时间. ② 服务做熔断处理(异常或着慢查询 Hystrix 限 ...

  4. 什么是 redis 的雪崩、穿透和击穿?

    缓存雪崩 对于系统 A,假设每天高峰期每秒 5000 个请求,本来缓存在高峰期可以扛住每秒 4000 个请求,但是缓存机器意外发生了全盘宕机.缓存挂了,此时 1 秒 5000 个请求全部落数据库,数据 ...

  5. Redis 雪崩、穿透和击穿

    https://github.com/doocs/advanced-java/blob/master/docs/high-concurrency/redis-caching-avalanche-and ...

  6. 什么是redis的雪崩和穿透

    缓存雪崩 如何应对缓存雪崩 首先要保证redis的高可用,可以使用redis cluster,开启redis持久化,redis之前要使用本地缓存,请求先走本地缓存,没找到再走redis 如果还是出现了 ...

  7. SRX550路由器缓存满了无法在web页面操作解决方法

    SRX550路由器缓存满了无法在web页面操作解决方法   首页出现下图为满的标志,我这个文档就是解决这中情况,让web页面可以操作的 1.  打开命令行,输入用户密码,进入路由器 注意:这里使用te ...

  8. Redis 雪崩、穿透、击穿、并发、缓存讲解以及解决方案

    1.缓存雪崩 数据未加载到缓存中,或者缓存同一时间大面积的失效,从而导致所有请求都去查数据库,导致数据库CPU和内存负载过高,甚至宕机. 比如一个雪崩的简单过程 1.redis集群大面积故障 2.缓存 ...

  9. Redsi缓存问题(穿透,击穿,雪崩)以及解决办法(分布式锁)【高并发问题】

    Redsi常见问题 缓存在高平发和安全压力下的一些问题 缓存击穿 是某一个热点key在高并发访问的情况下,突然失效,导致大量的并发大金mysql数据库的情况 缓存穿透 是利用redis和mysql的机 ...

随机推荐

  1. VS2017 ASP.NET MVC 5.0 开部署问题汇总

    1[SqlException (0x80131904): 拒绝了对对象 '****' (数据库 '***',架构 'dbo')的 EXECUTE 权限.] “/”应用程序中的服务器错误. SQL 20 ...

  2. VC工程产生文件后缀名解释

    [原文出自http://hi.baidu.com/zj0932zj/blog/item/b55f33cc7753c01700e92870.html ] .APS:存放二进制资源的中间文件,VC把当前资 ...

  3. Abp Area View文件无法调用@L方法

    需要再Area中对应的 web.config文件中 修改 <pages pageBaseType="zzz.Web.Views.zzzWebViewPageBase">

  4. centos7 设置nginx和php开机自启动

    nginx开机自启动 首先我是源码安装的,需要手动建立nginx.service服务文件 cd /lib/systemd/system touch nginx.service nginx.servic ...

  5. faiss索引基于数量级和内存限制的选择

    它是一个能使开发者快速搜索相似多媒体文件的算法库.而该领域一直是传统的搜索引擎的短板.借助Faiss,Facebook 在十亿级数据集上创建的最邻近搜索(nearest neighbor search ...

  6. LevelDB源码分析-Open

    Open LevelDB的初始化主要由Open函数实现: Status DB::Open(const Options &options, const std::string &dbna ...

  7. ArcPy开发教程2-管理地图文档1

    联系方式:谢老师,135-4855-4328,xiexiaokui#qq.com ArcPy开发教程2-管理地图文档1 第二次课:2019年2月26日上午第二节 讲解: 地图文档:Map docume ...

  8. vs中添加库文件WinMM.Lib

    C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Lib\WinMM.Lib;

  9. Mysql的隔离级别

    一.首先什么是事务? 事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消.也就是事务具有原子性,一个事务中的一系列的操作要么全部成功,要么一个都不做. 事 ...

  10. iview table中使用Poptip

    h('Poptip', { props: { confirm: true, // 'ok-text':"yes", // 'cancel-text':"no", ...