一、缓存雪崩

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

使缓存集中失效的原因:

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. 通过jedis远程访问redis服务器

    一.jedis简介 类似于mysql数据库,一般开发都需要通过代码去访问redis服务器,对于主流的开发语言,redis提供了访问的客户端接口. https://redis.io/clients 而对 ...

  2. C语言数据结构基础学习笔记——B树

    2-3树:是一种多路查找树,包含2结点和3结点两种结点,其所有叶子结点都在同一层次. 2结点:包含一个关键字和两个孩子(或没有孩子),其左孩子的值小于该结点,右孩子的值大于该结点. 3结点:包含两个关 ...

  3. 使用Linux的环境变量

    许多程序和脚本都使用环境变量来获取系统信息,并存储临时数据和配置信息: 1.什么是环境变量 用来存储关于shell会话和工作环境的信息,就叫做环境变量: bash shell下两种类型: 1.全局变量 ...

  4. Mysql 5 忘记root密码,设置免密登陆

    1.修改my.cnf配置文件 vi /etc/my.cnf #允许免密认证登陆 skip-grant-tables = true 2.重启Mysql数据库并登陆数据库修改root用户密码 system ...

  5. 使用Webupload上传图片到FastDFS分布式文件系统

    使用Webupload插件上传图片到FastDFS分布式文件系统. 前提条件:1.已安装FastDFS分布式文件系统 2.使用webuploader插件上传文件 3.maven工程已引入FastDFS ...

  6. UGUI 5.0 一些笔记

    1.加载资源路径 在Assets路径里创建Resources文件夹 a.加载配置好的界面 GameObject obj = (GameObject)Resources.Load ("conf ...

  7. 关于总结一些CentOS7常用的运维命令

    Centos7日常需要用的运维命令 1.删除0字节文件 find-type f -size 0 -exec rm -rf {} \ 2.查看进程 按内存从大到小排列 ps -e   -o " ...

  8. sql语句应用

    laravel5.6框架中用到的sql语句 //排序 $data=DB::table('admin')->select(array('id','name','password'))->or ...

  9. python 打开文件基础 (笔记)

    1.打开文件:建立文件与程序的关联 open(filenname,mode) filenname:文件名(包括路径):mode :打开模式 模式 打开模式 含义 r 只读,文件不存在则报错 w 只写, ...

  10. [转] ESXI6.5 误将硬盘阵列卡配置为passthru直通模式后, 找不到硬盘的问题

    There is no easy way to do it, it seems. So I wanted to say that I couldn't afford to do an upgrade ...