如何提高缓存命中率
命中:可以直接通过缓存获取到需要的数据。
不命中:无法直接通过缓存获取到想要的数据,需要再次查询数据库或者执行其它的操作。原因可能是由于缓存中根本不存在,或者缓存已经过期。
通常来讲,缓存的命中率越高则表示使用缓存的收益越高,应用的性能越好(响应时间越短、吞吐量越高),抗并发的能力越强。
由此可见,在高并发的互联网系统中,缓存的命中率是至关重要的指标。
如何监控缓存的命中率在memcached中,运行state命令可以查看memcached服务的状态信息,其中cmd_get表示总的get次数,get_hits表示get的总命中次数,命中率 = get_hits/cmd_get。
当然,我们也可以通过一些开源的第三方工具对整个memcached集群进行监控,显示会更直观。比较典型的包括:zabbix、MemAdmin等。
如图:MemAdmin对memcached服务的命中率情况的监控统计
同理,在redis中可以运行info命令查看redis服务的状态信息,其中keyspace_hits为总的命中中次数,keyspace_misses为总的miss次数,命中率=keyspace_hits/(keyspace_hits+keyspace_misses)。
开源工具Redis-star能以图表方式直观redis服务相关信息,同时,zabbix也提供了相关的插件对redis服务进行监控。
影响缓存命中率的几个因素之前的章节中我们提到了缓存命中率的重要性,下面分析下影响缓存命中率的几个因素。
业务场景和业务需求缓存适合“读多写少”的业务场景,反之,使用缓存的意义其实并不大,命中率会很低。
业务需求决定了对时效性的要求,直接影响到缓存的过期时间和更新策略。时效性要求越低,就越适合缓存。在相同key和相同请求数的情况下,缓存时间越长,命中率会越高。
互联网应用的大多数业务场景下都是很适合使用缓存的。
缓存的设计(粒度和策略)通常情况下,缓存的粒度越小,命中率会越高。举个实际的例子说明:
当缓存单个对象的时候(例如:单个用户信息),只有当该对象对应的数据发生变化时,我们才需要更新缓存或者让移除缓存。而当缓存一个集合的时候(例如:所有用户数据),其中任何一个对象对应的数据发生变化时,都需要更新或移除缓存。
还有另一种情况,假设其他地方也需要获取该对象对应的数据时(比如其他地方也需要获取单个用户信息),如果缓存的是单个对象,则可以直接命中缓存,反之,则无法直接命中。这样更加灵活,缓存命中率会更高。
此外,缓存的更新/过期策略也直接影响到缓存的命中率。当数据发生变化时,直接更新缓存的值会比移除缓存(或者让缓存过期)的命中率更高,当然,系统复杂度也会更高。
缓存容量和基础设施缓存的容量有限,则容易引起缓存失效和被淘汰(目前多数的缓存框架或中间件都采用了LRU算法)。同时,缓存的技术选型也是至关重要的,比如采用应用内置的本地缓存就比较容易出现单机瓶颈,而采用分布式缓存则毕竟容易扩展。所以需要做好系统容量规划,并考虑是否可扩展。此外,不同的缓存框架或中间件,其效率和稳定性也是存在差异的。
当缓存节点发生故障时,需要避免缓存失效并最大程度降低影响,这种特殊情况也是架构师需要考虑的。业内比较典型的做法就是通过一致性Hash算法,或者通过节点冗余的方式。
有些朋友可能会有这样的理解误区:既然业务需求对数据时效性要求很高,而缓存时间又会影响到缓存命中率,那么系统就别使用缓存了。其实这忽略了一个重要因素--并发。通常来讲,在相同缓存时间和key的情况下,并发越高,缓存的收益会越高,即便缓存时间很短。
提高缓存命中率的方法
从架构师的角度,需要应用尽可能的通过缓存直接获取数据,并避免缓存失效。这也是比较考验架构师能力的,需要在业务需求,缓存粒度,缓存策略,技术选型等各个方面去通盘考虑并做权衡。尽可能的聚焦在高频访问且时效性要求不高的热点业务上,通过缓存预加载(预热)、增加存储容量、调整缓存粒度、更新缓存等手段来提高命中率。
对于时效性很高(或缓存空间有限),内容跨度很大(或访问很随机),并且访问量不高的应用来说缓存命中率可能长期很低,可能预热后的缓存还没来得被访问就已经过期了。
缓存的失效和更新策略也是非常重要的,下篇继续...
CDN缓存相关问题及命中率优化 本文详细介绍旅CDN缓存命中率的概念,分析了无法命中缓存的问题原因以及命中率降低影响因素,并针对命中率降低及如何优化做了分析和介绍。
[20171109]缓存命中率神话.txt [20171109]缓存命中率神话.txt --//在oracle版本的早期,缓存命中率是一个很重要的优化指标,实际上这个根本不重要. --//一般OLTP系统即使出现严重的性能问题,这个数值也很高,实际上一个简单的情况就能说明问题, --//比如走hash join的计划,不小心走了nested loop,可能导致逻辑读上升.
丁浪 关注高并发、分布式系统架构、中间件、领域建模等。 InfoQ特约作者,CSDN博客专家。
相关文章
- 使用nginx+lua脚本读写redis缓存
- 互联网大厂都如何更新缓存的?看懂这篇缓存读写策略
- Windows7清除图标缓存
- cleanmymac x激活免费秘钥v2021.4.7.8如何清空DNS缓存教程分享
- 在ASP.NET WebAPI 中使用缓存【Redis】
- 如何保证缓存与数据库的双写一致性?
- 合理配置Mysql缓存,提高缓存命中率
- 如何避免缓存穿透、缓存击穿、缓存雪崩?
- Ehcache(03)——Ehcache中储存缓存的方式
- Nginx反向代理和缓存服务功能说明和简单实现 - 运维笔记
- 如何查看服务器的Raid缓存等配置的情况
- 七牛云刷新缓存
- nginx 缓存机制
- Springboot2.x使用redis作为缓存
- MemoryCache 如何清除全部缓存?
- 缓存学习(一)浏览器缓存(上) - 基于缓存策略三要素分解法
- SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】
- SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解、如何添加锁解决缓存击穿问题?分布式情况下如何添加分布式锁
- ServletWeb缓存解决问题
- OpenGL帧缓存对象(FBO)
- webview的缓存
- 如何用redis/memcache做Mysql缓存层?
- 使用 AsyncTask 下载图片,并用LurCache 实现图片缓存(超详细)
- 2018-8-10-如何移动-nuget-缓存文件夹
- 如何移动 nuget 缓存文件夹
- 如何移动 nuget 缓存文件夹
- http缓存总结
- Cache 和 Buffer 都是缓存,主要区别是什么?【转】
- Redis 缓存和 MySQL 如何实现数据一致性
- 多级缓存-OpenResty快速入门