草庐IT

真1分钟搞懂缓存穿透、缓存击穿、缓存雪崩

緑水長流*z 2023-04-19 原文

💗推荐阅读文章💗

文章目录

四、缓存解决方案

4.1 缓存穿透

4.1.1 现象:

指大量请求来到数据库查询都没有查询到结果,因此不存储在redis中,redis命中率非常低,当redis没有命中,则大量的请求来到了数据库,数据库一直处于被大流量访问状态,很容易压力过载(一般属于恶意攻击)。

4.1.2 方案:

1、在微服务网关或拦截器中设置逻辑监控,必要时采取封ip操作

2、每次将请求的数据都存入redis中并设置过期时间,设置key-null数据(过期时间设置短点,如1分钟),如果大量请求中存在有重复的数据,那么第二次以后的操作都会查询到redis,减少MySQL压力

3、在网关中增加逻辑校验,筛选掉不规则数据,如id<0的数据

4、bitmap白名单策略,将所有数据id存放在bitmaps中,id作为偏移量,存储0/1表示是否存在,存在则放行,不存在则拦截。(这种策略需要提前将所有的id缓存在bitmap中,效率偏低)

4.2 缓存击穿

4.2.1 现象:

指查询某个key(热点数据)在缓存中没有,但数据库有(一般是缓存时间到期),由于这个key是热点数据,在同一时间有大量用户访问这个key,并发量极高,请求发现redis没有,则全部来到数据查询,造成数据库压力瞬间飙升。

4.2.2 方案:

1、如果是整个网站中长期处于热点数据的,可以考虑将数据设置为永不过期

2、如果是需要发布某项活动,造成原本不是热点的key,突然变成热点,可以在活动之前将key的过期时间延长至活动结束。(缓存预热)

3、我们知道缓存击穿的原理实在就是大量并发同时来到cache,同时发现cache中没有数据,全部都去数据库获取了,那么我们可以考虑添加互斥锁,如果已经有请求进来获取数据,发现为空,那么就从数据库去获取数据(这段时间是上锁的)。

代码参考:

public String getData(String key) throws InterruptedException {

    // 首先从缓存读取数据
    String val = getDataFromRedis(key);

    // 如果缓存不存在则去数据库获取
    if (val == null) {
        // 获取锁
        if (lock.tryLock()) {

            // 从数据库获取数据
            val = getDataFromDB(key);

            if (val != null) {
                setCache(key, val);
            }
            
            // 释放锁
            lock.unlock();
        } else {
        	// 其他线程获取锁失败,睡眠100毫秒后尝试重新获取
        	Thread.sleep(100);
        	val = getData(key);
    	}
    } 
    return val;
}

4.3 缓存雪崩

4.3.1 现象:

指某一时间大量缓存过期,请求直接来到数据库,造成数据库压力过载。与缓存击穿不同的是缓存击穿通常是大的并发量访问某一条数据,而某一条数据正好失效。而缓存雪崩是大量的数据同时失效,多个key累加起来的请求流量压力过大。很多数据都查询不到,从而到数据库查询,数据库压力飙升。

4.3.2 方案:

1、将较为重要的数据设置永不过期

2、将缓存数据过期时间设置为随机,防止同一时间大量缓存失效

有关真1分钟搞懂缓存穿透、缓存击穿、缓存雪崩的更多相关文章

  1. ruby - 如何在 Ubuntu 中清除 Ruby Phusion Passenger 的缓存? - 2

    我试过重新启动apache,缓存的页面仍然出现,所以一定有一个文件夹在某个地方。我没有“公共(public)/缓存”,那么我还应该查看哪些其他地方?是否有一个URL标志也可以触发此效果? 最佳答案 您需要触摸一个文件才能清除phusion,例如:touch/webapps/mycook/tmp/restart.txt参见docs 关于ruby-如何在Ubuntu中清除RubyPhusionPassenger的缓存?,我们在StackOverflow上找到一个类似的问题:

  2. ruby-on-rails - Ruby on Rails 计数器缓存错误 - 2

    尝试在我的RoR应用程序中实现计数器缓存列时出现错误Unknownkey(s):counter_cache。我在这个问题中实现了模型关联:Modelassociationquestion这是我的迁移:classAddVideoVotesCountToVideos0Video.reset_column_informationVideo.find(:all).eachdo|p|p.update_attributes:videos_votes_count,p.video_votes.lengthendenddefself.downremove_column:videos,:video_vot

  3. 三分钟集成 TapTap 防沉迷 SDK(Unity 版) - 2

    三分钟集成Tap防沉迷SDK(Unity版)一、SDK介绍基于国家对上线所有游戏必须增加防沉迷功能的政策下,TapTap推出防沉迷SDK,供游戏开发者进行接入;允许未成年用户在周五、六、日以及法定节假日晚上8:00-9:00进行游戏,防沉谜时间段进入游戏会弹窗进行提示!开发环境要求:Unity2019.4或更高版本iOS10或更高版本Android5.0(APIlevel21)或更高版本🔗Unity集成Demo参考链接🔗UnityTapSDK功能体验APK下载链接二、集成前准备1.创建应用进入开发者后台,按照提示开始创建应用;2.开通服务在使用TDS实名认证和防沉迷服务之前,需要在上面创建的应

  4. ruby-on-rails - bundle 安装尝试使用缓存文件 - 2

    当我尝试进行bundle安装时,我的gem_path和gem_home指向/usr/local/rvm/gems/我没有写入权限,并且由于权限无效而失败。因此,我已将两个路径都更改为我具有写入权限的本地目录。这样做时,我进行了bundle安装,我得到:bruno@test6:~$bundleinstallFetchinggemmetadatafromhttps://rubygems.org/.........Fetchinggemmetadatafromhttps://rubygems.org/..Bundler::GemspecError:Couldnotreadgemat/afs/

  5. ruby-on-rails - 应用程序显示错误的小时和分钟 - 2

    起初:那不是错误区域的问题。在irb和数据库中,一切都很好。当我想在我的View中显示日期(created_at、updated_at和所有由我自己在每个模型中定义的日期)时,就会出现问题。我试图在application.rb中设置时区并从初始化程序中删除时间格式,但这并没有解决我的问题。Annotategem生成的架构信息:#created_at:datetime#updated_at:datetime#publish_at:datetime来自irb:1.9.2-p290:004>Time.zone=>(GMT+00:00)UTC1.9.2-p290:005>Time.zone.n

  6. ruby-on-rails - Heroku Action 缓存似乎不起作用 - 2

    我一直在Heroku上尝试不同的缓存策略,并添加了他们的memcached附加组件,目的是为我的应用程序添加Action缓存。但是,当我在我当前的应用程序上查看Rails.cache.stats时(安装了memcached并使用dalligem),在执行应该缓存的操作后,我得到current和total_items为0。在Controller的顶部,我想缓存我有的Action:caches_action:show此外,我修改了我的环境配置(对于在Heroku上运行的配置)config.cache_store=:dalli_store我是否可以查看其他一些统计数据,看看它是否有效或我做错

  7. ruby-on-rails - rails expire_page 没有删除缓存的文件 - 2

    我有一个具有页面缓存的ControllerAction,我制作了一个清扫程序,它使用Controller和指定的Action调用expire_page...Controller操作呈现一个js.erb模板,所以我试图确保expire_page删除public/javascripts中的.js文件,但它没有这样做。classJavascriptsController"javascripts",:action=>"lol",:format=>'js')endend...所以,我访问javascripts/lol.js并呈现我的模板。我验证了public/javascripts/lol.js

  8. ruby-on-rails - rails 3 缓存 : expire action for named route - 2

    我的Controller有这个:caches_action:render_ticker_for_channel,:expires_in=>30.seconds在我的路由文件中我有这个:match'/render_c_t/:channel_id'=>'render#render_ticker_for_channel',:as=>:render_channel_ticker在日志文件中我看到了这个:Writefragmentviews/mcr3.dev/render_c_t/63(11.6ms)我如何手动使它过期?我需要从与渲染Controller不同的Controller使它过期,但即使

  9. ruby - 更新 gem 时 Docker 包安装缓存问题 - 2

    我在开发和生产中都使用docker,真正困扰我的一件事是docker缓存的简单性。我的ruby​​应用程序需要bundleinstall来安装依赖项,因此我从以下Dockerfile开始:添加GemfileGemfile添加Gemfile.lockGemfile.lock运行bundleinstall--path/root/bundle所有依赖项都被缓存,并且在我添加新gem之前效果很好。即使我添加的gem只有0.5MB,从头开始安装所有应用程序gem仍然需要10-15分钟。由于依赖项文件夹的大小(大约300MB),然后再花10分钟来部署它。我在node_modules和npm上遇到了

  10. ruby - 如何让 Ruby 每 10 分钟运行一次任务? - 2

    我想每10分钟执行一次cron作业,但我的系统只执行1小时。所以我正在寻找一种方法来做到这一点。我看过Timer和sleep但我不确定如何执行此操作,甚至不知道如何实现此操作。 最佳答案 看看http://rufus.rubyforge.org/rufus-scheduler/rufus-scheduler是一个用于调度代码片段(作业)的Rubygem。它了解在特定时间、在特定时间、每x次或仅通过CRON语句运行作业。rufus-scheduler不能替代cron/at,因为它在Ruby内部运行。

随机推荐