Redis作为缓存可能会出现的问题及解决方案
Redis是个大话题,只要是去面试Java开发,几乎必问。基础一点的问Redis是什么东西?用来做什么?Redis支持哪些数据类型?Redis的性能为什么那么好?复杂一点的就会问到缓存穿透、缓存击穿、缓存雪崩等问题。而我在面试的时候也被问到了Redis为什么用来做缓存的问题。
所以我觉得很有必要总结一下Redis作为缓存使用,可能会引发的问题。以达到温故而知新的效果
ps:在本文章中,就不讨论Redis能用来干啥?这种基础问题了
一、Redis简介:
在讨论Redis作为缓存使用,可能会引发的问题之前,我们得了解官方是怎么定义Redis
Redis是一个开源的内存中的数据结构存储系统,它可以用作:数据库、缓存和消息中间件。
它支持多种类型的数据结构,如字符串(Strings),散列(Hash),列表(List),集合(Set),有序集合(Sorted Set或者是ZSet)。
Redis 内置了复制(Replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(Transactions) 和不同级别的磁盘持久化(Persistence),并通过 Redis哨兵(Sentinel)和自动分区(Cluster)提供高可用性(High Availability)。
Redis也提供了两种持久化策略,这些策略可以让用户将自己的数据保存到磁盘上面进行存储。根据实际情况,可以每隔一定时间将数据集以快照的形式保存在磁盘(RDB策略),或者将所有操作成功的命令追加到命令日志中(AOF策略),它会在执行命令时,将被执行的命令复制到硬盘里面,实现实时持久化数据的效果。当然,根据实际开发的需求,你也可以关闭持久化功能,单纯的将Redis作为一个高效的网络的缓存数据功能使用。
二、Redis作为缓存使用,可能会引发的问题(重点)
Redis由C语言开发,并且将数据存储在内存中,可以说Redis完全是基于内存进行操作,对数据读写的速度极快、性能极好。官方提供的数据是可以达到每秒100000+的吞吐量(每秒内查询次数),如此优秀的机制使Redis极其适合作为缓存使用。
1.缓存穿透
程序在处理缓存时,一般是先从缓存查询,如果缓存没有这个key(理解为数据),则会从数据库中查询,并将查询到的数据保存到缓存中去。
好,问题来了,如果有个坏心眼的人向服务器发起请求,去查询一个一定不存在的数据,由于缓存中没有查到对应的数据时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,缓存形同虚设,这就是缓存穿透。
解决方案:
1)最粗暴也是最常用的方法就是,如果一个查询的数据为空(不管是数据不存在还是系统故障),我们就把这个空结果进行缓存,但要把它的过期时间设置得很短,最长不超过5分钟,这样能有效的解决缓存穿透问题。
2)其次,可以采用布隆过滤器,也能解决缓存穿透问题
2.缓存击穿
缓存击穿和缓存穿透在本质上很相似,都是查询数据时缓存失去了作用,导致请求直接去数据库查询数据,但是造成缓存失效的原因却是天差地别。
大量用户在同一时间内访问某热点数据时,存储在缓存中的热点数据却突然失效(过期时间),结果就是大量的请求直接访问数据库,使数据库的压力变大,甚至导致数据库宕机,这就是缓存击穿。
解决方案:比较常用的方法是加互斥锁(mutex)保证数据的一致性。简单地来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去访问数据库,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set另一个请求所需要的数据,当操作返回成功时,再进行访问数据库的操作并回设缓存;否则,就重试整个get缓存的方法。
3.缓存雪崩
如果缓存的数据集中在一段时间内大批失效,而不巧的是在这段时间内又有大量用户发起请求访问数据,这样就会造成大量的缓存击穿,所有的请求都会直接去访问数据库,导致数据库在短时间内宕机,这就是缓存雪崩。
ps:这里我使用了夸张的修辞手法。缓存雪崩不一定会造成数据库宕机,但缓存如果发生雪崩现象,那肯定是很严重的
解决方案:
1)加锁排队。加互斥锁,添加信息队列
2)数据预热。可以通过缓存Reload机制,预先去更新缓存,再即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀
3)设置热点缓存永不过时
笔者: 以上问题及解决方案纯粹个人见解,如果有错误的地方,还请指正
Redis作为缓存可能会出现的问题及解决方案
Redis是个大话题,只要是去面试Java开发,几乎必问。基础一点的问Redis是什么东西?用来做什么?Redis支持哪些数据类型?Redis的性能为什么那么好?复杂一点的就会问到缓存穿透、缓存击穿、缓存雪崩等问题。而我在面试的时候也被问到了Redis为什么用来做缓存的问题。
所以我觉得很有必要总结一下Redis作为缓存使用,可能会引发的问题。以达到温故而知新的效果
ps:在本文章中,就不讨论Redis能用来干啥?这种基础问题了
一、Redis简介:
在讨论Redis作为缓存使用,可能会引发的问题之前,我们得了解官方是怎么定义Redis
Redis是一个开源的内存中的数据结构存储系统,它可以用作:数据库、缓存和消息中间件。
它支持多种类型的数据结构,如字符串(Strings),散列(Hash),列表(List),集合(Set),有序集合(Sorted Set或者是ZSet)。
Redis 内置了复制(Replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(Transactions) 和不同级别的磁盘持久化(Persistence),并通过 Redis哨兵(Sentinel)和自动分区(Cluster)提供高可用性(High Availability)。
Redis也提供了两种持久化策略,这些策略可以让用户将自己的数据保存到磁盘上面进行存储。根据实际情况,可以每隔一定时间将数据集以快照的形式保存在磁盘(RDB策略),或者将所有操作成功的命令追加到命令日志中(AOF策略),它会在执行命令时,将被执行的命令复制到硬盘里面,实现实时持久化数据的效果。当然,根据实际开发的需求,你也可以关闭持久化功能,单纯的将Redis作为一个高效的网络的缓存数据功能使用。
二、Redis作为缓存使用,可能会引发的问题(重点)
Redis由C语言开发,并且将数据存储在内存中,可以说Redis完全是基于内存进行操作,对数据读写的速度极快、性能极好。官方提供的数据是可以达到每秒100000+的吞吐量(每秒内查询次数),如此优秀的机制使Redis极其适合作为缓存使用。
1.缓存穿透
程序在处理缓存时,一般是先从缓存查询,如果缓存没有这个key(理解为数据),则会从数据库中查询,并将查询到的数据保存到缓存中去。
好,问题来了,如果有个坏心眼的人向服务器发起请求,去查询一个一定不存在的数据,由于缓存中没有查到对应的数据时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,缓存形同虚设,这就是缓存穿透。
解决方案:
1)最粗暴也是最常用的方法就是,如果一个查询的数据为空(不管是数据不存在还是系统故障),我们就把这个空结果进行缓存,但要把它的过期时间设置得很短,最长不超过5分钟,这样能有效的解决缓存穿透问题。
2)其次,可以采用布隆过滤器,也能解决缓存穿透问题
2.缓存击穿
缓存击穿和缓存穿透在本质上很相似,都是查询数据时缓存失去了作用,导致请求直接去数据库查询数据,但是造成缓存失效的原因却是天差地别。
大量用户在同一时间内访问某热点数据时,存储在缓存中的热点数据却突然失效(过期时间),结果就是大量的请求直接访问数据库,使数据库的压力变大,甚至导致数据库宕机,这就是缓存击穿。
解决方案:比较常用的方法是加互斥锁(mutex)保证数据的一致性。简单地来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去访问数据库,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set另一个请求所需要的数据,当操作返回成功时,再进行访问数据库的操作并回设缓存;否则,就重试整个get缓存的方法。
3.缓存雪崩
如果缓存的数据集中在一段时间内大批失效,而不巧的是在这段时间内又有大量用户发起请求访问数据,这样就会造成大量的缓存击穿,所有的请求都会直接去访问数据库,导致数据库在短时间内宕机,这就是缓存雪崩。
ps:这里我使用了夸张的修辞手法。缓存雪崩不一定会造成数据库宕机,但缓存如果发生雪崩现象,那肯定是很严重的
解决方案:
1)加锁排队。加互斥锁,添加信息队列
2)数据预热。可以通过缓存Reload机制,预先去更新缓存,再即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀
3)设置热点缓存永不过时
笔者: 以上问题及解决方案纯粹个人见解,如果有错误的地方,还请指正
Redis作为缓存可能会出现的问题及解决方案的更多相关文章
- 高并发简单解决方案————redis队列缓存+mysql 批量入库(ThinkPhP)
问题分析 问题一:要求日志最好入库:但是,直接入库mysql确实扛不住,批量入库没有问题,done.[批量入库和直接入库性能差异] 问题二:批量入库就需要有高并发的消息队列,决定采用redis lis ...
- HAProxy 的负载均衡服务器,Redis 的缓存服务器
问答社区网络 StackExchange 由 100 多个网站构成,其中包括了 Alexa 排名第 54 的 StackOverflow.StackExchang 有 400 万用户,每月 5.6 亿 ...
- spring使用redis做缓存
缓存 什么是缓存? 在高并发下,为了提高访问的性能,需要将数据库中 一些经常展现和不会频繁变更的数据,存放在存取速率更快的内存中.这样可以 降低数据的获取时间,带来更好的体验 减轻数据库的压力 缓存适 ...
- 知乎技术分享:从单机到2000万QPS并发的Redis高性能缓存实践之路
本文来自知乎官方技术团队的“知乎技术专栏”,感谢原作者陈鹏的无私分享. 1.引言 知乎存储平台团队基于开源Redis 组件打造的知乎 Redis 平台,经过不断的研发迭代,目前已经形成了一整套完整自动 ...
- Spring Boot + Mybatis + Redis二级缓存开发指南
Spring Boot + Mybatis + Redis二级缓存开发指南 背景 Spring-Boot因其提供了各种开箱即用的插件,使得它成为了当今最为主流的Java Web开发框架之一.Mybat ...
- 从单机到2000万 QPS 并发的 Redis 高性能缓存实践之路
1.引言 知乎存储平台团队基于开源Redis 组件打造的知乎 Redis 平台,经过不断的研发迭代,目前已经形成了一整套完整自动化运维服务体系,提供很多强大的功能.本文作者陈鹏是该系统的负责人,本次文 ...
- c#实例化继承类,必须对被继承类的程序集做引用 .net core Redis分布式缓存客户端实现逻辑分析及示例demo 数据库笔记之索引和事务 centos 7下安装python 3.6笔记 你大波哥~ C#开源框架(转载) JSON C# Class Generator ---由json字符串生成C#实体类的工具
c#实例化继承类,必须对被继承类的程序集做引用 0x00 问题 类型“Model.NewModel”在未被引用的程序集中定义.必须添加对程序集“Model, Version=1.0.0.0, Cu ...
- Redis之缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级
目录 Redis之缓存雪崩.缓存穿透.缓存预热.缓存更新.缓存降级 1.缓存雪崩 2.缓存穿透 3.缓存预热 4.缓存更新 5.缓存降级 Redis之缓存雪崩.缓存穿透.缓存预热.缓存更新.缓存降级 ...
- Redis 多级缓存架构和数据库与缓存双写不一致问题
采用三级缓存:nginx本地缓存+redis分布式缓存+tomcat堆缓存的多级缓存架构 时效性要求非常高的数据:库存 一般来说,显示的库存,都是时效性要求会相对高一些,因为随着商品的不断的交易,库存 ...
随机推荐
- Redis持久性——RDB和AOF
Redis持久性 Redis提供了不同的持久性选项: RDB持久性以指定的时间间隔执行数据集的时间点快照. AOF持久性记录服务器接收的每个写入操作,将在服务器启动时再次播放,重建原始数据集.使用与R ...
- 【WebLogic使用】3.WebLogic配置jndi数据源
参见博客:https://blog.csdn.net/acmman/article/details/70146603 参考视频教程: 一.什么是jndi数据源JNDI是Java命名与目录接口(Java ...
- 设计模式--Builder生成器模式
如果文章中哪里有问题,希望各位大哥大姐指出,小弟十分感激. 正文 什么是生成器模式? 生成器模式就是把生产对象的过程进一步抽取.细化.独立.以往我们生产对象,可能就是在一个小作坊里面从头做到尾.现在用 ...
- Mariadb之显式使用表锁和行级锁
首先我们来看看mariadb的锁定概念,所谓锁就是当一个进程或事务在操作某一资源时,为了防止其他用户或者进程或事务对其进行资源操作,导致资源抢占而发生冲突,通常在A进程操作该资源时,会对该资源进行加锁 ...
- python高阶-Linux基础命令集
声明: 1)仅作为个人学习,如有冒犯,告知速删! 2)不想误导,如有错误,不吝指教! 1: 查看文件信息:ls ls常用参数: 参数 含义 -a 显示指定目录下所有子目录与文件,包括隐藏文件 -l 以 ...
- Python实用笔记 (15)函数式编程——装饰器
什么函数可以被称为闭包函数呢?主要是满足两点:函数内部定义的函数:引用了外部变量但非全局变量. python装饰器本质上就是一个函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外的功能,装饰 ...
- 黑鸟码表BB10S骑行记录导入行者
前言 开始骑车用行者app记录, 后来觉得每次都要开app很麻烦, 于是在骑友的推荐下入手了黑鸟BB10S, 使用了一段时间感觉还不错, 不过也遇到之前大家说的问题, 黑鸟不支持直接导出fit文件, ...
- jquery入门(3)
4.jQuery中的事件绑定 4.1.事件绑定 on方法绑定 $('#box').on('click',function(){ alert(1); }) 直接绑定 $("#box" ...
- Write a program to copy its input to its output, replacing each string of one or more blanks by a single blank.
#include <stdio.h> void main() { int c,c_BCN; while((c=getchar())!=EOF) { if(c!=' ') c_BCN=; i ...
- 01.RabbitMQ简单使用
官网地址:https://www.rabbitmq.com/getstarted.html RabbitMQ 优点: 数据处理异步执行: 应用之间解耦: 流量削峰 1.docker 安装 Rabbit ...