【Redis】什么是Redis缓存 雪崩、穿透、击穿?(一篇文章就够了)

2024-06-10 04:12

本文主要是介绍【Redis】什么是Redis缓存 雪崩、穿透、击穿?(一篇文章就够了),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

什么是Redis?

Redis的正常存储流程?

什么是Redis缓存雪崩?

缓存雪崩

缓存预热

缓存失效时间的随机性

什么是Redis缓存穿透?

缓存穿透

缓存空对象

BloomFilter(布隆过滤器)

什么是Redis缓存击穿?

缓存击穿

互斥锁

逻辑过期时间


什么是Redis?

        Redis:是一种高性能开源的基于内存的,采用键值对存储的非关系型数据库,不保证数据的ACID特性【事务一旦提交,都不会进行回滚】

        采用键值对存储数据在内存或磁盘中,可以对关系型数据库起到补充作用,同时支持持久化[可以将数据保存在可掉电设备中],可以将数据同步保存到磁盘。

说Redis很快是相对于关系型数据库如mysql来说的,主要有以下因素

    第一,数据结构简单,所以速度快【采用键值对的方式】;

    第二,基于内存进行存储,不需要存储数据库,所以速度快;

    第三,采用多路IO复用模型,减少网络IO的时间消耗,避免大量的无用操作,所以速度快;

    第四,单线程避免了线程切换和上下文切换产生的消耗,所以速度快;

Redis的正常存储流程?

        正常流程:当用户访问服务端时,服务端会去访问Redis缓存中是否有该数据的缓存,如果有,就直接返回;如果没有,就去数据库进行查询;查询到结果过后直接返回给客户端,并且将查询的结果数据同步到redis缓存当中。

 

什么是Redis缓存雪崩?

缓存雪崩

        是指在某一时刻缓存中的存储的数据同时大量地失效,而且这些数据都是经常被访问的数据(比如热点文章,热门商品等),这样就会导致大量的请求都会落到数据库上,造成数据库的压力瞬间增大,从而导致服务器宕机,形成一种“雪崩”效应。

        简单来说,就是大量的redis同一时间大面积的失效,大量的请求直接打到数据库上(导致数据库压力飙升),这种现象就是缓存雪崩。

        解决缓存雪崩的方法有很多,其中一种比较常见的方法是采用“缓存预热”和“缓存失效时间的随机性”两种手段来解决。

缓存预热

        是指系统上线后,将相关的缓存数据直接加载到缓存中,这样一来,第一个请求过来的时候,就可以直接在缓存中获取到数据,而不需要去数据库中查询。

缓存失效时间的随机性

        是指在设置缓存的失效时间时,不能够将所有缓存的失效时间都设置为相同的值,而是要在一个合理的时间范围内进行随机,这样可以避免缓存在某一时刻大量失效的情况。

下面是一个采用了缓存预热和缓存失效时间的随机性的Java代码:

public class UserService {private static final Random RANDOM = new Random();private RedisTemplate<String, User> redisTemplate;//可以将所有的初始化需要执行的代码放在一个单独的类中,使用@Scheduled或quartz或xxl-job定时控制执行public UserService(RedisTemplate<String, User> redisTemplate) {this.redisTemplate = redisTemplate;// 缓存预热,将所有用户数据加载到缓存中List<User> users = getUsersFromDB();for (User user : users) {redisTemplate.opsForValue().set(user.getId(), user, getExpireTime());}}public User getUser(String userId) {// 先从缓存中获取数据User user = redisTemplate.opsForValue().get(userId);if (user != null) {return user;}// 缓存中没有数据,则从数据库中查询user = getUserFromDB(userId);if (user != null) {// 将数据放入缓存,并且设置一个随机的失效时间redisTemplate.opsForValue().set(userId, user, getExpireTime());}return user;}private List<User> getUsersFromDB() {// 从数据库中查询所有用户数据// ...}private User getUserFromDB(String userId) {// 从数据库中查询用户数据// ...}private long getExpireTime() {// 在30分钟到1小时之间随机一个时间作为缓存的失效时间return 1800 + RANDOM.nextInt(1800);}}

 

什么是Redis缓存穿透?

缓存穿透

        是指恶意的请求,会故意查询数据库不存在的数据,而这些数据在Redis缓存中也不存在,这样就会导致大量的请求都会落到数据库上,造成数据库的压力瞬间增大,从而导致服务器宕机。

解决缓存穿透的方法有很多,其中一种比较常见的方法是采用“缓存空对象”和“BloomFilter(布隆过滤器)两种手段来解决。

缓存空对象

        是指在查询数据库时,如果发现查询的数据不存在,那么就将这个空对象也缓存起来,这样一来,下次再查询这个不存在的数据时,就可以直接在缓存中获取到空对象,而不需要去数据库中查询。

BloomFilter(布隆过滤器)

        【Redis】布隆过滤器_布隆过滤器需要保存-CSDN博客

        是一种概率性数据结构,可以用于判断一个元素是否存在于一个集合中,它的优势在于空间复杂度低、查询速度快。

下面是一个采用了缓存空对象和BloomFilter的Java代码:

public class UserService {private RedisTemplate<String, User> redisTemplate;private BloomFilter<String> bloomFilter;public UserService(RedisTemplate<String, User> redisTemplate, BloomFilter<String> bloomFilter) {this.redisTemplate = redisTemplate;this.bloomFilter = bloomFilter;// 将所有用户的ID都放入BloomFilter中List<User> users = getUsersFromDB();for (User user : users) {bloomFilter.add(user.getId());}}public User getUser(String userId) {// 先判断BloomFilter中是否存在该IDif (!bloomFilter.mightContain(userId)) {return null;}// 再从缓存中获取数据User user = redisTemplate.opsForValue().get(userId);if (user != null) {return user;}// 缓存中没有数据,则从数据库中查询user = getUserFromDB(userId);if (user != null) {// 将数据放入缓存redisTemplate.opsForValue().set(userId, user, 3600);} else {// 将空对象放入缓存redisTemplate.opsForValue().set(userId, null, 300);}return user;}private List<User> getUsersFromDB() {// 从数据库中查询所有用户数据// ...}private User getUserFromDB(String userId) {// 从数据库中查询用户数据// ...}}
``

 

什么是Redis缓存击穿?

缓存击穿

        是指某个热点数据在缓存中失效了,而且这个数据也是经常被访问的数据,这样就会导致大量的请求都会落到数据库上,造成数据库的压力瞬间增大,从而导致服务器宕机。

解决缓存击穿的方法有很多,其中一种比较常见的方法是采用“互斥锁”和“逻辑过期时间”两种手段来解决。

互斥锁

        是指在查询数据库时,如果发现缓存中的数据已经失效,那么就先获取一个互斥锁,然后再去查询数据库,这样一来,只有一个线程去访问数据库,将查询到的数据同步到缓存当中,其他线程就直接从缓存中获取了,就可以避免大量的请求都会落到数据库上。

逻辑过期时间

        是指在查询数据库时,如果发现缓存中的数据已经失效,那么就先将数据库中的数据缓存起来,但是不将这个数据的过期时间设置为实际的过期时间,而是将过期时间设置为一个较短的时间,这样一来,就可以避免缓存中的数据一直都是“冷”数据。

下面是一个采用了互斥锁和逻辑过期时间的Java代码:

public class UserService {private RedisTemplate<String, User> redisTemplate;private RedissonClient redissonClient;public UserService(RedisTemplate<String, User> redisTemplate, RedissonClient redissonClient) {this.redisTemplate = redisTemplate;this.redissonClient = redissonClient;}public User getUser(String userId) {// 先从缓存中获取数据User user = redisTemplate.opsForValue().get(userId);if (user != null && !user.isExpired()) {return user;}// 获取互斥锁RLock lock = redissonClient.getLock("user:" + userId);try {if (lock.tryLock(10, 5, TimeUnit.SECONDS)) {// 再次从缓存中获取数据user = redisTemplate.opsForValue().get(userId);if (user != null && !user.isExpired()) {return user;}// 从数据库中查询数据user = getUserFromDB(userId);if (user != null) {// 将数据放入缓存,并且设置一个逻辑过期时间redisTemplate.opsForValue().set(userId, user, 3600);user.setExpireTime(System.currentTimeMillis() + 300000);}}} finally {// 释放互斥锁if (lock != null && lock.isHeldByCurrentThread()) {lock.unlock();}}return user;}private User getUserFromDB(String userId) {// 从数据库中查询用户数据// ...}}public class User {private String id;private String name;private long expireTime;public User(String id, String name) {this.id = id;this.name = name;this.expireTime = System.currentTimeMillis() + 300000;}public String getId() {return id;}public String getName() {return name;}public boolean isExpired() {return System.currentTimeMillis() > expireTime;}}

这篇关于【Redis】什么是Redis缓存 雪崩、穿透、击穿?(一篇文章就够了)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1047177

相关文章

Andrej Karpathy最新采访:认知核心模型10亿参数就够了,AI会打破教育不公的僵局

夕小瑶科技说 原创  作者 | 海野 AI圈子的红人,AI大神Andrej Karpathy,曾是OpenAI联合创始人之一,特斯拉AI总监。上一次的动态是官宣创办一家名为 Eureka Labs 的人工智能+教育公司 ,宣布将长期致力于AI原生教育。 近日,Andrej Karpathy接受了No Priors(投资博客)的采访,与硅谷知名投资人 Sara Guo 和 Elad G

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

缓存雪崩问题

缓存雪崩是缓存中大量key失效后当高并发到来时导致大量请求到数据库,瞬间耗尽数据库资源,导致数据库无法使用。 解决方案: 1、使用锁进行控制 2、对同一类型信息的key设置不同的过期时间 3、缓存预热 1. 什么是缓存雪崩 缓存雪崩是指在短时间内,大量缓存数据同时失效,导致所有请求直接涌向数据库,瞬间增加数据库的负载压力,可能导致数据库性能下降甚至崩溃。这种情况往往发生在缓存中大量 k

Redis中使用布隆过滤器解决缓存穿透问题

一、缓存穿透(失效)问题 缓存穿透是指查询一个一定不存在的数据,由于缓存中没有命中,会去数据库中查询,而数据库中也没有该数据,并且每次查询都不会命中缓存,从而每次请求都直接打到了数据库上,这会给数据库带来巨大压力。 二、布隆过滤器原理 布隆过滤器(Bloom Filter)是一种空间效率很高的随机数据结构,它利用多个不同的哈希函数将一个元素映射到一个位数组中的多个位置,并将这些位置的值置

Lua 脚本在 Redis 中执行时的原子性以及与redis的事务的区别

在 Redis 中,Lua 脚本具有原子性是因为 Redis 保证在执行脚本时,脚本中的所有操作都会被当作一个不可分割的整体。具体来说,Redis 使用单线程的执行模型来处理命令,因此当 Lua 脚本在 Redis 中执行时,不会有其他命令打断脚本的执行过程。脚本中的所有操作都将连续执行,直到脚本执行完成后,Redis 才会继续处理其他客户端的请求。 Lua 脚本在 Redis 中原子性的原因

防止缓存击穿、缓存穿透和缓存雪崩

使用Redis缓存防止缓存击穿、缓存穿透和缓存雪崩 在高并发系统中,缓存击穿、缓存穿透和缓存雪崩是三种常见的缓存问题。本文将介绍如何使用Redis、分布式锁和布隆过滤器有效解决这些问题,并且会通过Java代码详细说明实现的思路和原因。 1. 背景 缓存穿透:指的是大量请求缓存中不存在且数据库中也不存在的数据,导致大量请求直接打到数据库上,形成数据库压力。 缓存击穿:指的是某个热点数据在

laravel框架实现redis分布式集群原理

在app/config/database.php中配置如下: 'redis' => array('cluster' => true,'default' => array('host' => '172.21.107.247','port' => 6379,),'redis1' => array('host' => '172.21.107.248','port' => 6379,),) 其中cl

PHP APC缓存函数使用教程

APC,全称是Alternative PHP Cache,官方翻译叫”可选PHP缓存”。它为我们提供了缓存和优化PHP的中间代码的框架。 APC的缓存分两部分:系统缓存和用户数据缓存。(Linux APC扩展安装) 系统缓存 它是指APC把PHP文件源码的编译结果缓存起来,然后在每次调用时先对比时间标记。如果未过期,则使用缓存的中间代码运行。默认缓存 3600s(一小时)。但是这样仍会浪费大量C

java计算机毕设课设—停车管理信息系统(附源码、文章、相关截图、部署视频)

这是什么系统? 资源获取方式在最下方 java计算机毕设课设—停车管理信息系统(附源码、文章、相关截图、部署视频) 停车管理信息系统是为了提升停车场的运营效率和管理水平而设计的综合性平台。系统涵盖用户信息管理、车位管理、收费管理、违规车辆处理等多个功能模块,旨在实现对停车场资源的高效配置和实时监控。此外,系统还提供了资讯管理和统计查询功能,帮助管理者及时发布信息并进行数据分析,为停车场的科学

缓存策略使用总结

缓存是提高系统性能的最简单方法之一。相对而言,数据库(or NoSQL数据库)的速度比较慢,而速度却又是致胜的关键。 如果使用得当,缓存可以减少相应时间、减少数据库负载以及节省成本。本文罗列了几种缓存策略,选择正确的一种会有很大的不同。缓存策略取决于数据和数据访问模式。换句话说,数据是如何写和读的。例如: 系统是写多读少的吗?(例如基于时间的日志)数据是否是只写入一次并被读取多次?(例如用户配