先来看一下缓存穿透,是指业务请求穿过了缓存层,落到持久化存储上。在大多数场景下,我们应用缓存是为了承载前端业务请求,缓存被击穿以后,如果请求量比较大,则会导致数据库出现风险。
以双十一为例,由于各类促销活动的叠加,整体网站的访问量、商品曝光量会是平时的千倍甚至万倍。巨大的流量暴涨,单靠数据库是不能承载的,如果缓存不能很好的工作,可能会影响数据库的稳定性,继而直接影响整体服务。
不合理的缓存失效策略
缓存失效策略如果设置不合理,比如设置了大量缓存在同一时间点失效,那么将导致大量缓存数据在同一时刻发生缓存穿透,业务请求直接打到持久化存储层。
外部用户的恶意攻击
外部恶意用户利用不存在的 Key,来构造大批量不存在的数据请求我们的服务,由于缓存中并不存在这些数据,因此海量请求全部穿过缓存,落在数据库中,将导致数据库崩溃。
首先是设置合理的缓存失效策略,避免缓存数据在同一时间失效。
缓存穿透还可以通过缓存空数据的方式避免。缓存空数据非常好理解,就是针对数据库不存在的数据,在查询为空时,添加一个对应 null 的值到缓存中,这样在下次请求时,可以通过缓存的结果判断数据库中是否存在,避免反复的请求数据库。不过这种方式,需要考虑空数据的 Key 在新增后的处理。
缓存击穿也是缓存应用常见的问题场景,其是一个非常形象的表达。具体表现:前端请求大量的访问某个热点 Key,而这个热点 Key 在某个时刻恰好失效,导致请求全部落到数据库上。
另外一个方案是使用布隆过滤器。布隆过滤器是应用非常广泛的一种数据结构,我们熟悉的 Bitmap,可以看作是一种特殊的布隆过滤器。使用布隆过滤器,可在缓存前添加一层过滤,布隆过滤器映射到缓存,在缓存中不存在的数据,会在布隆过滤器这一层拦截,从而保护缓存和数据库的安全。
在任何一组东西中,最重要的只占其中一小部分,约 20%,其余 80% 尽管是多数,却是次要的,因此又称二八定律。
二八定律在缓存应用中也不能避免,往往是 20% 的缓存数据,承担了 80% 或者更高的请求,剩下 80% 的缓存数据,仅仅承担了 20% 的访问流量。
由于二八定律的存在,缓存击穿虽然可能只是一小部分数据失效,但这部分数据如果恰好是热点数据,还是会对系统造成非常大的危险。
缓存击穿和缓存穿透都是降低了整体的缓存命中率,不过在表现上比较类似。缓存击穿可以认为是缓存穿透的一种特殊场景,所以在解决方案上也可以应用上面提到的那几种手段。
其是缓存穿透和缓存击穿升级的一种问题场景。
缓存雪崩的表现有两种,一种是大量的缓存数据在同一时刻失效,请求全部转发到数据库,将导致数据库压力过大,服务宕机;另外一种是缓存服务不稳定,比如负责缓存的 Redis 集群宕机。
在业务开发中,出现缓存雪崩非常危险,可能会直接导致大规模服务不可用,因为缓存失效时导致的雪崩,一方面是整体的数据存储链路,另一方面是服务调用链路,最终导致微服务整体的对外服务出现问题。
我们知道,微服务本身就存在雪崩效应,在电商场景中,如果商品服务不可用,最终可能会导致依赖的订单服务、购物车服务、用户浏览等级联出现故障。
你考虑一下,如果商品服务出现缓存雪崩,继而商品服务不可用,关联的周边服务都会受影响。
首先是明确缓存集群的容量峰值,通过合理的限流和降级,防止大量请求直接拖垮缓存;其次是做好缓存集群的高可用,以 Redis 为例,可以通过部署 RedisCluster、Proxy 等不同的缓存集群,来实现缓存集群高可用。
首先明确应用缓存的目的,大部分缓存都是内存数据库,并且可以支持非常高的 QPS,所以缓存应用,可以防止海量业务请求击垮数据库,保护正常的服务运行。
其次,在考虑缓存的稳定性时,要从两个方面展开,第一个是缓存的数据,第二个是缓存容器也就是缓存服务本身的稳定性。
从缓存数据的层面,有一个缓存命中率的概念,是指落到缓存上的请求占整体请求总量的占比。缓存命中率在电商大促等场景中是一个非常关键的指标,我们要尽可能地提高缓存数据的命中率,一般要求达到 90% 以上,如果是大促等场景,会要求 99% 以上的命中率。
从缓存服务的层面,缓存集群本身也是一个服务,也会有集群部署,服务可用率,服务的最大容量等。在应用缓存时,要对缓存服务进行压测,明确缓存的最大水位,如果当前系统容量超过缓存阈值,就要通过其他的高可用手段来进行调整,比如服务限流,请求降级,使用消息队列等不同的方式。
所以我们在使用缓存的时候,要把这几个场景都考虑到,做到在使用缓存的时候,保持稳定状态。
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/
我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为
我有一大串格式化数据(例如JSON),我想使用Psychinruby同时保留格式转储到YAML。基本上,我希望JSON使用literalstyle出现在YAML中:---json:|{"page":1,"results":["item","another"],"total_pages":0}但是,当我使用YAML.dump时,它不使用文字样式。我得到这样的东西:---json:!"{\n\"page\":1,\n\"results\":[\n\"item\",\"another\"\n],\n\"total_pages\":0\n}\n"我如何告诉Psych以想要的样式转储标量?解