大家好,redis缓存穿透相信很多的网友都不是很明白,包括redis面试必会6题经典也是一样,不过没有关系,接下来就来为大家分享关于redis缓存穿透和redis面试必会6题经典的一些知识点,大家可以关注收藏,免得下次来找不到哦,下面我们开始吧!
SpringBoot中如何使用缓存来缓解数据库压力
Springboot项目中增加缓存,一般分为本地缓存和分布式缓存。我们开发的顺序一般如下:首先不考虑缓存,将业务逻辑验证正确;然后进行压测,发现性能瓶颈,考虑是增加缓存还是同步转异步进行优化;(3)如果需要加缓存,则优先考虑分布式缓存,最后再考虑增加本地缓存。缓存使用的时候需要注意几个问题1.数据一致性:什么时候写入缓存?什么时候缓存失效?先更新DB再失效缓存2.缓存穿透问题3.大value缓存问题。
我之前写过一个demo说明如何整合springboot和redis,可以看看:
https://www.jianshu.com/p/a2ab17707eff
如何解决Redis缓存和MySQL数据一致性的问题
在高并发的业务场景下,数据库的性能瓶颈往往都是用户并发访问过大。所以,一般都使用redis做一个缓冲操作,让请求先访问到redis,而不是直接去访问MySQL等数据库。从而减少网络请求的延迟响应
数据为什么会不一致这样的问题主要是在并发读写访问的时候,缓存和数据相互交叉执行。
一、单库情况下
同一时刻发生了并发读写请求,例如为A(写)B(读)2个请求
A请求发送一个写操作到服务端,第一步会淘汰cache,然后因为各种原因卡主了,不在执行后面业务(例:大量的业务操作、调用其他服务处理消耗了1s)。
B请求发送一个读操作,读cache,因为cache淘汰,所以为空
B请求继续读DB,读出一个脏数据,并写入cache
A请求终于执行完全,在写入数据到DB
总结:因最后才把写操作数据入DB,并没同步。cache里面一直保持脏数据
脏数据是指源系统中的数据不在给定的范围内或对于实际业务毫无意义,或是数据格式非法,以及在源系统中存在不规范的编码和含糊的业务逻辑。
二、主从同步,读写分离的情况下,读从库而产生脏数据
A请求发送一个写操作到服务端,第一步会淘汰cache
A请求写主数据库,写了最新的数据。
B请求发送一个读操作,读cache,因为cache淘汰,所以为空
B请求继续读DB,读的是从库,此时主从同步还没同步成功。读出脏数据,然后脏数据入cache
最后数据库主从同步完成
总结:这种情况下请求A和请求B操作时序没问题,是主从同步的时延问题(假设1s),导致读请求读取从库读到脏数据导致的不一致
根本原因:
单库下,逻辑处理中消耗1s。可能读到旧数据入缓存
主从+读写分离,在1s的主从同步时延中。读到从库的旧数据入缓存
数据优化方案一、缓存双淘汰法
先淘汰缓存
再写数据库
往消息总线esb发送一个淘汰消息,发送立即返回。写请求的处理时间几乎没有增加,这个方法淘汰了缓存两次。因此被称为“缓存双淘汰法“,而在消息总线下游,有一个异步淘汰缓存的消费者,在拿到淘汰消息在1s后淘汰缓存,这样,即使在一秒内有脏数据入缓存,也能够被淘汰掉。
二、异步淘汰缓存
上述的步骤,都是在业务线里面执行,新增一个线下的读取binlog异步淘汰缓存模块,读取binlog总的数据,然后进行异步淘汰。
1.思路:
MySQLbinlog增量发布订阅消费+消息队列+增量数据更新到redis
1)读请求走Redis:热数据基本都在Redis
2)写请求走MySQL:增删改都操作MySQL
3)更新Redis数据:MySQ的数据操作binlog,来更新到Redis
2.Redis更新
1)数据操作主要分为两块:
一个是全量(将全部数据一次写入到redis)
一个是增量(实时更新)
这里说的是增量,指的是mysql的update、insert、delate变更数据。
这样一旦MySQL中产生了新的写入、更新、删除等操作,就可以把binlog相关的消息推送至Redis,Redis再根据binlog中的记录,对Redis进行更新。就无需在从业务线去操作缓存内容
如有感悟,欢迎关注和交流探讨额
redis为什么把数据放到内存中
这个问题问得有问题!!
首先,redis确实是一个内存型的数据库系统,把大量数据在内存中使用,并快速存取,但是,redis提供了以数据库文件的方式持久化数据的选择,通过使用bgsave,save等命令,可以把缓存中的数据存储到磁盘中进行永久性保存!
把题目换种问法!为什么内存读取比磁盘读取数据速度快?
1,内存是电器元件,利用高低电平存储数据,而磁盘是机械元件(去买电脑的时候写着5400r/min或者7200r/min),电气原件速度超级快,而磁盘因为在每个磁盘块切换的时候,磁头会消耗比较多的时间,也就是IO时间长,所以性能没发比!
2,磁盘的数据进行操作的时候也都是读取到内存中,由CPU进行操作的,所以直接放在内存中的数据,读取速度肯定快了很多很多!
那么内存有哪些缺点呢?
1,丢数据:内存因为是存储的高低电平,断电之后数据全部丢失,而磁盘存储了二进制文件,断电以后数据依然存在!
2,内存贵:一块4G的内存和一个500g的磁盘价格差不多,因为内存设计工艺要求更高,材料也更加昂贵!
所以,不仅仅是redis,几乎所有的缓存系统都会先用到内存作为数据快速读取的基本保证,然后才能有扩展数据持久化的可能!
redis作为分布式的可持久化的单线程的key-value缓存系统,有着大量的优点,吸引着广大开发者的关注,同时在保证数据一致性等问题上通常作为首选条件!
关于redis集群,指令,开启持久化,防止内存穿透等问题,之后会有提及,敬请关注。。。
如何使用RedisTemplate访问Redis数据结构
在springboot项目中,集成各种框架变得非常容易。下面简单介绍一下如何在springboot项目中集成单机模式redis。集群模式也差不多,这里就不过多介绍了。
首先你得安装redis服务,无论在linux还是windows系统上。如果没有安装,请自行百度或使用其他科学网站帮助。随后需要在项目的配置文件中配置redis相关参数以及设置jedis连接池的参数。可参考下图配置方式:由于本人使用了maven方式来构建项目,所以需要在项目的pom文件中加入redis相关依赖。
之后就需要实现redis配置文件类。配置文件的jedis连接池配置就不列出来了,反正就是根本properties文件来一步一步设置,连接工厂也是跟连接池有关。这里重点介绍一下redisTemplate的实现,以及与redis操作工具类的配合使用。可以根据下图来进行个性化设置:实现配置文件后,就可以在redis工具类RedisUtil中使用redisTemplate了。如下图所示:这里redisTemplate实例化是在redis配置类中实现的。直接将RedisUtil通过注解方式直接注入到spring容器中去,在此过程中使用工具类的setRedisTemplate方法实例化RedisTemplate。这样就能直接通过@AutoWired注解去装配Bean了。在RedisUtil工具类中,我们通过redisTemplate去操作数据结构。无论是一般数据(String),还是Map数据结构,还是List数据结构,都有相应的操作方法。如下图:工具类完成后,在相应的服务层使用这个工具类来操作redis的数据结构实现相应业务。以上就是一个redis操作类在speingboot项目中的简单实现。除了数据结构的操作,我们还能使用redis的特性来实现一些业务场景特定的功能。例如使用increment方法实现点赞功能;利用redis单线程特性生成唯一主键;将redis与Lua脚本相结合,实现redis分布式锁,当然这需要考虑到业务时间与过期时间的关系问题。
除此之外,在使用redis过程中应该需要考虑到雪崩、穿透和击穿等问题,这也是在面试过程中经常问到的问题。希望对你有所帮助。
文章分享结束,redis缓存穿透和redis面试必会6题经典的答案你都知道了吗?欢迎再次光临本站哦!