<blockquote id="pww52"></blockquote>

          <div id="pww52"><tr id="pww52"><object id="pww52"></object></tr></div>
          <div id="pww52"></div>
        1. <div id="pww52"></div>
        2. 首页 > 基础设施 > 正文

          干货!教你深入理解缓存问题,使用缓存无压力!

          2019-02-13 11:48:11  来源:安胜ISEC实验室

          摘要:在高并发或大数据的场景下,面对热点数据的使用性能问题,缓存是常用的解决方式,主要作用包括将数据写入速度更快的存储设备;将数据缓存到离应用最近的位置;将数据缓存到离用户最近的位置等。
          关键词: 缓存
            在高并发或大数据的场景下,面对热点数据的使用性能问题,缓存是常用的解决方式,主要作用包括将数据写入速度更快的存储设备;将数据缓存到离应用最近的位置;将数据缓存到离用户最近的位置等。
           
          \
           
            一、缓存雪崩
           
            缓存雪崩可简单理解为,由于原有缓存失效,新缓存未到期间(例如?#20309;?#20204;设置缓存时采用了相同的过期时间,在同一时刻出现大面积的缓存过期),所?#24615;?#26412;应该访问缓存的请求都去查询数据库,对数据库CPU和内存造成巨大压力,?#29616;?#30340;会导致数据库宕机,从而形成一系列连锁反应,造成整个系统崩溃。
           
            缓存失效时的雪崩效应对底层系统的冲击很大,大多系统设计者采用加锁或队列的方式来保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量并发请求落到底层存储系统上。另外一个简单方案就是分散缓存失效时间,例如可以在原有的失效时间基础上增加一个随机值,?#28909;?-5分钟随机,这样每一个缓存过期时间的重复率就会降低,很难引发集体失效的事件。
           
            1.若一般并发量不是特别多,常用解决方案是加锁排队,可减轻数据库的压力,但不会提高系统吞吐量。假设在高并发下,缓存重建期间key是锁着的,此时1000个请求中999个在阻塞状态,同样会导致用户等待超时,这种方法治标不治本!
           
            注意:使用加锁排队的方式解决分布式环境的并发问题,可能还要解决分布式锁的问题;线程还会被阻塞,用户体验较差,因此,在真正的高并发场景下很少使用!
           
            2.另一个解决方案是,给每一个缓存数据增加相应的缓存标记,记录缓存是否失效,如果缓存标记失效,则更新数据缓存。
           
            解释说明
           
            1.缓存标记:记录缓存数据是否过期,若过期会触发通知另外的线程,则在后台更新实际key的缓存;
           
            2.缓存数据:它的过期时间比缓存标记的时间延长1倍,例:标记缓存时间30分钟,数据缓存设置为60分钟。 这样,当缓存标记key过期后,实际缓存还能将旧数据返回给调用端,直到另外的线程在后台更新完成后,才会返回新缓存。
           
            关于缓存崩溃的三种解决方案:使用锁或队列、设置过期标志更新缓存、为key设置不同的缓存失效时间,还有一种被称为“二级缓存”的解决方法,有兴趣的小伙伴可自行研究。
           
            二、缓存穿透
           
            缓存穿透是指用户无法在缓存中查询数据,需要去数据库查询,再返回空(相当于进行两次无用查询)。此时请求就绕过缓存直接查数据库,这就是经常提到的缓存命?#26032;?#38382;题。
           
            有多种方法可有效的解决缓存穿透问题,最常见的是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap?#26657;?#19968;定不存在的数据则会被bitmap拦截掉,从而避免对底层存储系统的查询压力。
           
            另外更为简单的方法是,若一个查询返回的数据为空(不管是数据不存在,还是系统故障),我们仍然将此空结果进行缓存,过期时间会很短,最长不超过五分钟。通过这个直接设置的默?#29616;?#23384;放到缓存,这样第二次到缓冲中获取就有值了,而不会继续访问数据库,这?#32844;?#27861;最为简单。
           
            将空结果进行缓存,下次同样的请求则直接返回空,即可避免当查询的值为空时引起的缓存穿透。同时也可单独设置一个缓存区域存储空值,对要查询的key进?#24615;?#20808;校验,然后再放行给后面的正常缓存处理逻辑。
           
            三、缓存预热
           
            缓存预热就是系统上线后,将相关的缓存数据直接加载到缓存系统中。这样即可避免在用户请求时,先查询数据库,再将数据缓存的问题,用户可直接查询事先被预热的缓存数据。
           
            解决思路:
           
            1.直接写一个缓存刷新页面,上线时手工操作;
           
            2.数据量不大时,可以在项?#31185;?#21160;时自动进行加载;
           
            3.定时刷新缓存。
           
            四、缓存更新
           
            除了缓存服务器?#28304;?#30340;缓存失效策略外(Redis默认的有6种策略可供选择),还可根据具体的业务需求进行自定义缓存淘汰,常见策略?#26657;?/div>
           
            1.定期清理过期缓存;
           
            2.当有用户请求时,判断缓存是否过期,过期则在底层系统得到新数据并更新缓存。
           
            两者各有优劣,第一种的缺点是维护大量缓存的key较为麻?#24120;?#31532;二种的缺点是每次用户请求都需判断缓存是否失效,逻辑相对比较复杂。具体选择哪种方案,可根据应用场景权衡。
           
            五、缓存?#23548;?/strong>
           
            当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍需保证服务可用,即使是有损服务。系统可以根据一些关键数据进行自动?#23548;叮?#20063;可配置开关实现人工?#23548;丁?/div>
           
            ?#23548;?#30340;最终目的是保证核心服务可用,即使是有损的,而且有些服务是无法?#23548;?#30340;(如加入?#20309;?#36710;、结算)。
           
            在进行?#23548;?#20043;前要对系统进行梳理,确认哪些需要保护,哪些可?#23548;??#28909;?#21487;参考日志级别设置预案:
           
            1.一般:有些服务?#32423;?#22240;网络抖动或者服务正在上线而超时,可自动?#23548;?
           
            2.警告:有些服务在一?#38382;?#38388;内成功率有波动(如在95~100%之间),可自动?#23548;?#25110;人工?#23548;叮?#24182;发送警告;
           
            3.错误:可用?#23454;?#20110;90%,或数据库连接池?#32531;?#23613;,或访问量猛增到系统能承受的最大阀值,此时可根据情况自动?#23548;?#25110;者人工?#23548;?
           
            4.?#29616;?#38169;误:因为特殊原因数据错误,此时需要紧急人工?#23548;丁?/div>
          第二十八届CIO班招生
          法国布雷斯特商学院MBA班招生
          法国布雷斯特商学院硕士班招生
          法国布雷斯特商学院DBA班招生
          责编:pingxiaoli
          湖北体彩11选5走势图

          <blockquote id="pww52"></blockquote>

                <div id="pww52"><tr id="pww52"><object id="pww52"></object></tr></div>
                <div id="pww52"></div>
              1. <div id="pww52"></div>

                <blockquote id="pww52"></blockquote>

                      <div id="pww52"><tr id="pww52"><object id="pww52"></object></tr></div>
                      <div id="pww52"></div>
                    1. <div id="pww52"></div>
                    2. 天津快乐10分基本走势图电视版 酒吧梭哈 p3试机号金码查询今天晚上 体育彩票几点开奖时间 天际六合心水论坛 双色球开奖直播是几点 江苏时时彩网 今天河南快3和直走势图 金多宝四肖中特 天津快乐十分红蓝号走势图 牛牛外掛 河南快赢481投注技巧 北京十一选五走势图手机版手机版 3d打印技术 上海快三漏