Redis系列(八)--缓存穿透、雪崩、更新策略
1、缓存更新策略
1、LRU/LFU/FIFO算法剔除:例如maxmemory-policy
2、超时剔除,过期时间expire,对于一些用户可以容忍延时更新的数据,例如文章简介内容改了几个字
3、主动更新:代码控制生命周期,对于一些必须实时更新的数据,例如金额
| 策略 | 一致性 | 维护成本 |
| LRU/LFU/FIFO算法剔除 | 最差 | 低 |
| 超时剔除 | 较差 | 低 |
| 主动更新 | 强 | 高 |
2、缓存粒度问题
1、通用性:全量属性最好
2、占用空间:部分属性最好
3、代码维护:表面上看全量属性最好
大部分应用来说都是缓存部分属性
3、缓存穿透
指查询一个一定不存在的数据,由于缓存是不命中时,出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次
请求都要到存储层去查询,失去了缓存的意义。在流量大时,可能DB就挂掉了,要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞。
优化到极致的mysql的数据库连接为300-700之间,300为机械硬盘数据,700为固态硬盘数据
原因:
1、业务代码有问题,直接返回了,没有写cache层
2、恶意攻击、爬虫等
如何发现:
1、业务的响应时间,通过监控系统
2、业务本身的问题
3、相关指标:总调用数、缓存层命中数、存储层命中数
解决方法:
处理缓存穿透的方法有很多,其实无外乎就是对数据进行过滤筛选,把真正有效的数据进行访问,无效数据直接过滤掉。
1、缓存空对象
设置过期时间,过期时间会很短,最长不超过五分钟,用来减少storage压力,这样需要更多的键,缓存和存储层短期数据不一致
2、布隆过滤器拦截
将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。
3、对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃
4、缓存雪崩
cache层承受大量请求,当cache服务异常、脱机,流量直接压向DB,造成级联故障。
缓存集中在一段时间内失效,新的缓存未到,或者Redis缓存宕机,发生大量的缓存穿透,所有的查询都落在数据库上,造成了缓存雪崩
优化方案:
1、保证缓存高可用性。master-slave、sentinel、cluster
2、依赖隔离组件(线程池/信号量组件)为后端限流,例如Hystrix,还有本地encache缓存
3、提前演练
4、Redis持久化,快速恢复缓存数据
解决办法:
1、在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。
2、可以通过缓存reload机制,预先去更新缓存,再即将发生大并发访问前手动触发加载缓存 不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀
做二级缓存,或者双缓存策略。A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期。
5、缓存预热
缓存预热就是系统上线后,将相关的缓存数据直接加载到缓存系统。这样避免,用户请求的时候,再去加载相关的数据。
解决思路:
1、直接写个缓存刷新页面,上线时手工操作下。
2、数据量不大,可以在WEB系统启动的时候加载。
3、定时刷新缓存。
6、缓存过期策略
除了缓存服务器自带的缓存失效策略之外(Redis默认的有6中策略可供选择),我们还可以根据具体的业务需求进行自定义的缓存淘汰,常见的
策略有两种:
(1)定时删除
Redis将每个设置过期时间的key放到一个独立的字典中,以后定期遍历字典删除过期的key
Redis默认100ms进行一次过期扫描,不会扫描字典中所有的key,而是采用贪心算法。从字典中随机20个key,删除20个key里面过期的key,如果
过期的key的比率超过1/4就重复之前的步骤
(2)惰性删除
当有用户请求过来时,再判断这个请求所用到的缓存是否过期,过期的话就去底层系统得到新数据并更新缓存
对比:
两者各有优劣,第一种的缺点是维护大量缓存的key是比较麻烦的,第二种的缺点就是每次用户请求过来都要判断缓存失效,逻辑相对比较复杂!
可以采用定期删除+惰性删除两种策略
7、内存淘汰策略
Redis的数据都是放在内存中的,如果Redis能使用10G内存,但是数据却又20G,这时候就需要干掉10G数据,去掉不常用的数据,保留常用的数据
Redis提供的内存淘汰策略有如下几种:
1、no-eviction 不会继续服务写请求 (DEL 请求可以继续服务),读请求可以继续进行。这样可以保证不会丢失数据,但是会让线上的业务不能
持续进行。这是默认的淘汰策略。
2、volatile-lru 尝试淘汰设置了过期时间的 key,最少使用的 key 优先被淘汰。没有设置过期时间的 key 不会被淘汰,这样可以保证需要持
久化的数据不会突然丢失。(这个是使用最多的)
3、volatile-ttl 跟上面一样,除了淘汰的策略不是 LRU,而是 key 的剩余寿命 ttl 的值,ttl 越小越优先被淘汰。
4、volatile-random 跟上面一样,不过淘汰的 key 是过期 key 集合中随机的 key。
5、allkeys-lru 区别于 volatile-lru,这个策略要淘汰的 key 对象是全体的 key 集合,而不只是过期的 key 集合。这意味着没有设置过期
时间的 key 也会被淘汰。
6、allkeys-random 跟上面一样,不过淘汰的策略是随机的 key。allkeys-random 跟上面一样,不过淘汰的策略是随机的 key。
lru策略可以保证Redis中的数据都是近期使用频率比较高的数据,也就是热点数据
策略使用规则:
1、如果数据访问分布差别很大,就是用allkeys-lru
2、如果数据访问分布均匀,访问频率差不多,使用allkeys-random
7、缓存降级
当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损
服务。系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级。
降级的最终目的是保证核心服务可用,即使是有损的。而且有些服务是无法降级的(如加入购物车、结算)。
在进行降级之前要对系统进行梳理,看看系统是不是可以丢卒保帅;从而梳理出哪些必须誓死保护,哪些可降级;
比如可以参考日志级别设置预案:
(1)一般:比如有些服务偶尔因为网络抖动或者服务正在上线而超时,可以自动降级
(2)警告:有些服务在一段时间内成功率有波动(如在95~100%之间),可以自动降级或人工降级,并发送告警
(3)错误:比如可用率低于90%,或者数据库连接池被打爆了,或者访问量突然猛增到系统能承受的最大阀值,此时可以根据情况自动降级或
者人工降级
(4)严重错误:比如因为特殊原因数据错误了,此时需要紧急人工降级
8、无底洞问题
由Facebook产生的,有3000个memcache节点,性能却下降了,例如mget、mset等时间复杂度从O(1)到O(Node)
优化:
1、优化命令:keys、hgetall、bigkey
2、减少网络通信时间
3、降低接入成本:例如客户端长连接、连接池、NIO等
4、热点key重建优化:高并发情况下,可能出现很多线程重建缓存的情况
热点key+较长的重建时间
1、三个目标:
减少重缓存的次数
数据尽可能一致
减少潜在危险
2、两个解决
互斥锁(mutext key)
setex、setnx能够保证原子性
永远不过期:给每个value设置逻辑过期时间
Redis系列(八)--缓存穿透、雪崩、更新策略的更多相关文章
- Redis系列三 - 缓存雪崩、击穿、穿透
前言 从学校出来,做开发工作也有一定时间了,最近有想系统地进一步深入学习,但发现基础知识不够扎实,故此来回顾基础知识,进一步巩固.加深印象. 最初开始接触编程时,总是自己跌跌撞撞.不断摸索地去学习,再 ...
- 深入了解Redis(7)-缓存穿透,雪崩,击穿
redis作为一个内存数据库,在生产环境中使用会遇到许多问题,特别是像电商系统用来存储热点数据,容易出现缓存穿透,雪崩,击穿等问题.所以实际运用中需要做好前期处理工作. 一.缓存雪崩 1.概念 缓存雪 ...
- NoSQL & Redis 介绍、缓存穿透 & 击穿 & 雪崩
1. NoSql 简介 2. Redis 简介 2.1 Redis 的起源 2.2 缓存过期 & 缓存淘汰 3. 缓存异常 1)缓存穿透 2)缓存击穿 3)缓存雪崩 4)总结 1. NoSQL ...
- Redis系列八 使用Jedis
使用Jedis jar操作Redis 1.配置redis.conf文件,修改 2.建java工程,加入 jedis jar包 3.代码示例: package com.ntjr.redis; impor ...
- Redis系列八:redis主从复制和哨兵
一.Redis主从复制 主从复制:主节点负责写数据,从节点负责读数据,主节点定期把数据同步到从节点保证数据的一致性 1. 主从复制的相关操作 a,配置主从复制方式一.新增redis6380.conf, ...
- Redis系列(八):发布与订阅
Redis的发布与订阅,有点类似于消息队列,发送者往频道发送消息,频道的订阅者接收消息. 1. 发布与订阅示例 首先,在本机开启第1个Redis客户端,执行如下命令订阅blog.redis频道: SU ...
- Redis缓存雪崩,缓存穿透,热点key解决方案和分析
缓存穿透 缓存系统,按照KEY去查询VALUE,当KEY对应的VALUE一定不存在的时候并对KEY并发请求量很大的时候,就会对后端造成很大的压力. (查询一个必然不存在的数据.比如文章表,查询一个不存 ...
- Redis缓存穿透、缓存击穿以及缓存雪崩
作为一个内存数据库,redis也总是免不了有各种各样的问题,这篇文章主要是针对其中三个问题进行讲解:缓存穿透.缓存击穿和缓存雪崩.并给出一些解决方案.这三个问题是基本问题也是面试常问问题. 这篇文章我 ...
- Redis基础用法、高级特性与性能调优以及缓存穿透等分析
一.Redis介绍 Redis是一个开源的,基于内存的结构化数据存储媒介,可以作为数据库.缓存服务或消息服务使用.Redis支持多种数据结构,包括字符串.哈希表.链表.集合.有序集合.位图.Hype ...
随机推荐
- mac终端配置Android ADB命令
不得不说mac是一款开发利器,不仅可以开发ios,而且对于Android开发也是不错的选择,下面我就对mac配置adb命令,进行简要的说明.下面我将一下mac环境下的配置步骤:1.在自己的目录(hom ...
- lydsy1013: [JSOI2008]球形空间产生器sphere 高斯消元
题链:http://www.lydsy.com/JudgeOnline/problem.php?id=1013 1013: [JSOI2008]球形空间产生器sphere 时间限制: 1 Sec 内 ...
- 【HNOI模拟By lyp】Day2
1 toad1.1 题目描述 有 n 个石子, A B 两人博弈, A 先手. A 首先取若干个石子(至少一个,不能取完),然后B和A 再轮流取石子,每次取的石子不能超过 axb ( x 表示上次取的 ...
- gcc优化选项解析
1 -fno-defer-pop 函数返回的时候,就立即将栈里面放置的该函数的参数pop出来.这样可以避免函数参数占用过多的栈空间. 2 -fforward-propagate ? 3 -ffp-co ...
- TI BLE STACK - OSAL
TI 的OSAL做的很不错,不过看起来也挺费劲可能自己水平太差吧,网上买的谷雨的开发板觉得确实挺不错的. 做点学习笔记,首先是记录OSAL里执行的顺序流程,主要是task ,event,message ...
- 利用 BASE64Encoder 对字符串进行加密 BASE64Decoder进行解密
转自:https://blog.csdn.net/chenyongtu110/article/details/51694323
- 在Android.mk文件中输出打印消息 (转载)
转自:http://blog.csdn.net/xiaibiancheng/article/details/8479694 在进行Android NDK的开发当中有时想看看Android.mk文件当中 ...
- 《Maven实战》(许晓斌)导读(读书笔记&第二次读后感)
第一章 Maven简介 Maven是构建工具,但同时还是jar包管理工具.项目信息管理工具 与Make.Ant比较,更为先进 第二章 Maven的安装和配置 Windows和Unix上安装都很简单,下 ...
- 转 Shell调试篇
检查语法 -n选项只做语法检查,而不执行脚本. sh -n script_name.sh 启动调试 sh -x script_name.sh 进入调试模式后,Shell依次执行读入的语句,产生的输出中 ...
- 407 Trapping Rain Water II 接雨水 II
给定一个m x n的矩阵,其中的值均为正整数,代表二维高度图每个单元的高度,请计算图中形状最多能接多少体积的雨水.说明:m 和 n 都是小于110的整数.每一个单位的高度都大于0 且小于 20000. ...