本文作者:IMWeb daihuimi 原文出处:IMWeb社区 未经同意,禁止转载 学习整理了web缓存的一些策略,如有不正确的地方,欢迎指正。 在HTTP请求和响应的消息报头中,常见的与缓存有关的消息报头有: Web缓存的作用 减少网络带宽消耗 降低服务器压力 减少网络延迟,加快页面打开速度 HTTP缓存机制 缓存行为主要由缓存策略决定,而缓存策略由内容拥有者设置 这些策略主要通过特定的HTTP头部来清晰地表达。 3.客户端展现该页面,并将页面连同Last-Modified/ETag一起缓存。 4.客户再次请求页面A,并将上次请求时服务器返回的Last-Modified/ETag一起传递给服务器。 CDN缓存策略 CDN边缘节点缓存策略因服务商不同而不同,但一般都会遵循http标准协议,通过http响应头中的Cache-control: max-age的字段来设置CDN边缘节点数据缓存时间。
Web缓存的作用 减少网络带宽消耗 降低服务器压力 减少网络延迟,加快页面打开速度 HTTP缓存机制 缓存行为主要由缓存策略决定,而缓存策略由内容拥有者设置。 这些策略主要通过特定的HTTP头部来清晰地表达。 3.客户端展现该页面,并将页面连同Last-Modified/ETag一起缓存。 4.客户再次请求页面A,并将上次请求时服务器返回的Last-Modified/ETag一起传递给服务器。 CDN缓存策略 CDN边缘节点缓存策略因服务商不同而不同,但一般都会遵循http标准协议,通过http响应头中的Cache-control: max-age的字段来设置CDN边缘节点数据缓存时间。 前端工程与性能优化 参考: Web开发基本准则-55实录-缓存策略 【Web缓存机制系列】2 – Web浏览器的缓存机制 HTTP协议详解 CDN缓存那些事 浅谈HTTP缓存机制
策略 Cache-Aside 可能是最常用的缓存策略。 使用 Cache Aside 策略的系统可以在一定程度上抵抗缓存故障。如果缓存服务发生故障,系统仍然可以通过直接访问数据库进行操作。 然而,这种策略并不能保证数据存储和缓存之间的一致性,需要配合使用其它策略来更新或使缓存无效。另外,首次请求数据时,总是会导致缓存未命中,这种情况下需要额外的时间来将数据加载到缓存中。 Read-Through 策略 在上面的 Cache-Aside 策略中,应用程序需要与缓存和数据源“打交道”,而在 Read-Through 策略下,应用程序无需管理数据源和缓存,只需要将数据源的同步委托给缓存提供程序 Write-Through 策略 Write-Through 策略下,当发生数据更新(Write)时,缓存提供程序 Cache Provider 负责更新底层数据源和缓存。
viewholder的快速重用 mChangedScrap ArrayList<ViewHolder> mCachedViews ArrayList<ViewHolder> 移除屏幕外的viewholder缓存集合 ,移动到recyclerpool,并将移出屏幕外的viewholder,加入到cachedview集合里面 mViewCacheExtension ViewCacheExtension 用户自己实现的缓存类 缓存viewholder的对象,当mCachedViews长度大于2,就会把mCachedViews超出的内容放到mRecyclerPool,然后给viewholder复用。
而解决上述问题需要一个优秀的缓存策略。除此之外,web缓存的优点还有很多,例如:减轻服务器压力 ,加快了客户端加载速度,节省网络带宽等。 web缓存按缓存位置,缓存机制可大致分为三类。 当然这需要一系列策略进行约定。 2.1 强缓存策略 所谓强缓存策略即在静态资源有效期内,使用该资源时直接使用本地资源,不请求服务器。 4 过期时直接返回200并在body中放入更新内容。 5 如果未过期则直接返回304状态码。 下面进行实例验证 // 协商缓存 // 方式一 last-modified & if-Modified-Since 通过协商修改时间为基础的策略 // 首先需要禁用强缓存 res.setHeader 4 过期时直接返回200并在body中放入更新内容。 5 如果未过期则直接返回304状态码。
首先,SDWebImage 的图片缓存采用的是 Memory(内存) 和 Disk(硬盘) 双重 Cache 机制,SDImageCache 中有一个叫做 memCache 的属性,它是一个 NSCache 对象,用于实现我们对图片的 `Memory Cache,其实就是接受系统的内存警告通知,然后清除掉自身的图片缓存。 Disk Cache,也就是文件缓存,SDWebImage` 会将图片存放到 NSCachesDirectory 目录中,然后为每一个缓存文件生成一个 md5 文件名, 存放到文件中。 Disk(硬盘)缓存清理策略:SDWebImage 会在每次 APP 结束的时候执行清理任务。 清理缓存的规则分两步进行。 第一步先清除掉过期的缓存文件。 如果清除掉过期的缓存之后,空间还不够。 那么就继续按文件时间从早到晚排序,先清除最早的缓存文件,直到剩余空间达到要求。
缓存介绍 这里是列表文本在高并发多用户的系统中常常会使用缓存来提升读写性能 这里是列表文本常见的如memcached, redis, 内存缓存等 现象 这里是列表文本某产品上线后不久 0x0000000725dc66d8, 0x0000000732c2df18, 0x00000007232425a0, 0x0000000723242648, 0x0000000732c31da0, 0x0000000731a4fd78 , 0x0000000731a4fe20, 0x0000000738139a10, 0x0000000725cda198, 0x0000000725cda240, 0x0000000738066638, com.xxxx.xxxx.web.controller.login.LoginController.login(LoginController.java:119) 分析 仔细分析对应代码逻辑,可发现有如下的缓存策略 每一个线程都会去执行getFromDb()这个方法,每个请求都会穿透到db上 当用户请求较大时,对数据库的压力会非常大【上面的stack仅为多台应用web中的一台】 解决 当数据库中无数据时,可以在缓存中放一个无效的对象表明
CPU缓存策略原理 缓存概述 CPU为了提升执行效率,减少CPU与内存的交互(交互影响CPU效率),一般在CPU上集成了多级缓存架构 cpu缓存策略图 cpu读取数据时, 会先从自己的寄存器当中读取. 如果没有再从Cache当中读取数据.如果Cache当中也没能.再从内存当中获取.然后再依次缓存 多核CPU结构图 三级缓存 L1 Cache 分为数据缓存和指令缓存,逻辑核独占 CPU所有操作的数据全部在寄存器当中完成 1ns` L1 cache (一级缓存) `约1ns` L2 cache(二级缓存) `约3ns` L3cache(三级缓存) `约15ns` 主内存(最终存储地址) `约80ns` 缓存行Cache Line概念 1. 缓存是由最小的存储区块缓存行Cache Line组成 2.
Redis 缓存淘汰策略 如何估算缓存容量大小 「二八定律」:百分之八十的访问会落到百分之二十的热点数据上 内存容量建议设置在总数据量的 15%~30% Redis 设置最大缓存容量: config set maxmemory 4gb Redis 缓存淘汰策略 8 中淘汰策略: 1 种不进行淘汰策略: noeviction 7 种进行淘汰策略,按照是否设置过期时间,进行数据集淘汰进行分类 有设置过期时间 一般不使用这个配置策略。 配置项 maxmemory-samples 用于配置候选集 N 的数据个数: config set maxmemory-samples 100 Redis 缓存淘汰策略最佳实践 数据访问频率差异大(冷热数据区分明显 )优先使用 allkeys-lru 策略 数据访问频率差异不大时(无明显冷热数据区分)推荐使用 allkeys-random 策略 业务有置顶需求(置顶新闻、视频)使用 volatile-lru 策略,
数据缓存 JuiceFS 对数据也提供多种缓存机制来提高性能,包括内核中的页缓存和客户端所在节点的本地缓存。 内核数据缓存 注意:此特性需要使用 0.15.0 及以上版本的 JuiceFS。 客户端读缓存 JuiceFS 客户端会根据读取模式自动预读数据放入缓存,从而提高顺序读的性能。默认情况下,会在读取数据时并发预读 1 个 block 缓存在本地。 JuiceFS 目前是通过累加所有被缓存对象的大小并附加固定的开销(4KiB)来估算得到的,这与 du 命令得到的数值并不完全一致。 为防止缓存盘被写满,当缓存目录所在文件系统空间不足时,客户端会尽量减少缓存用量。 通过上述介绍,我们对 JuiceFS 的缓存机制的原理有了进一步了解。 JuiceFS 本身作为底层文件系统,提供了包括元数据缓存、数据读写缓存等多种缓存机制,最大限度的保证了数据的一致性。希望大家通过本文的了解能更好的应用 JuiceFS。
Redis是一个流行的内存缓存系统,由于内存有限,缓存系统必须遵循一些淘汰策略来删除一些不再需要的键,以便为新键腾出空间。 在Redis中,缓存淘汰策略是由maxmemory和maxmemory-policy两个配置参数控制的。本文将详细介绍Redis的缓存淘汰策略,并给出一些示例。 缓存淘汰策略当Redis的内存达到maxmemory配置的值时,Redis会尝试删除一些键,以便为新键腾出空间。 Redis支持以下五种缓存淘汰策略:noeviction: 当Redis的内存达到maxmemory时,不执行任何操作,而是返回错误。volatile-lru: 在过期的键中使用LRU算法进行淘汰。 示例以下是一些Redis缓存淘汰策略的示例:noeviction策略示例maxmemory 10mbmaxmemory-policy noeviction在此示例中,当Redis的内存使用达到10MB时
对于 Redis 来说,一旦确定了缓存最大容量,比如 4GB,你就可以使用下面这个命令来设定缓存的大小了: CONFIG SET maxmemory 4gb Redis设置了缓存的容量大小,那么缓存被写满是不可避免的 Redis有哪些淘汰策略 Redis共提供了8中缓存淘汰策略,其中volatile-lfu和allkeys-lfu是Redis 4.0版本新增的。 Redis 用作缓存时,实际的数据集通常都是大于缓存容量的,总会有新的数据要写入缓存,这个策略本身不淘汰数据,也就不会腾出新的缓存空间,我们不把它用在 Redis 缓存中。 allkeys-lfu 策略,使用 LFU 算法在所有数据中进行筛选。 通常情况下推荐优先使用 allkeys-lru 策略。 这样,可以充分利用 LRU 这一经典缓存算法的优势,把最近最常访问的数据留在缓存中,提升应用的访问性能。如果你的业务数据中有明显的冷热数据区分,我建议你使用 allkeys-lru 策略。
问题:项目中,Redis用了缓存热点数据,持久化数据在MySQL DB中;那么Redis缓存数据什么时候更新呢? 方法A: 步骤:1. 删除缓存,2.更新DB , 3.下一次读操作没有命中缓存时,更新缓存; 存在的问题:如果另外一个读任务发生在"更新DB"之前,那么缓存就"更新DB"之前的“脏数据”; 方法B: 删除缓存; 3. 下一次读操作没有命中缓存时,更新缓存; 存在的问题:如果在步骤1“更新DB”之前,有一个并发读任务没有命中缓存,从DB读取到“老数据”,在步骤2之后才把“老数据”更新到缓存,那么缓存中就是 “脏数据”; 思考:方法C采取的策略,在实际场景中发送的概率比前两种方法小很多;但是怎么完全杜绝这种问题呢?
所以设计一个简单的缓存更新策略就很必要了。 以资源为出发点 以上面的例子为示例: 以uid(用户)为资源的考量对象。引入版本的概念。 在缓存的对象中,加入version的概念。 cache:{ 'data': xxx, 'version': timestamp } 取缓存时,同时取ut:1的值。 如果cache['version']小于 ut:1,说明缓存落后于数据库。此时,刷新缓存。并更新cache['version']为最新timestamp。 完成上面操作后,实作中,把所有和user task表相关的缓存都绑定到ut:{uid}这个key上。只要在更新表时更新这个key。就能引发所有的缓存惰性更新。 wraps(f) async def run(request, *args, **kwargs): key = prefix # 绑定的过期策略键
Glide的缓存策略 前言 众所周知,图片加载框架的基本模式就是三层缓存。内存、文件和网络。 但Glide在缓存策略上,花费了很多心思,从而使得其在加载图片过程中,对内存的使用量非常小。 本文将分享Glide在缓存策略上使用的技巧。 在加载图片之后,内存缓存填满,我们可以将Bitmap从内存缓存中移出。但是,Bitmap还是存在于Java堆中,此时我们将失去对这个Bitmap的任何控制。 内存缓存的策略 既然要区分Bitmap是否正在显示。Glide的策略是从源头上,区分正在显示和没有显示的Bitmap。Glide将内存分为两块儿:ActiveCache和MemoryCache。 综上,生命周期的监听、BitmapPool的复用、可见/不可见资源的分开缓存。是Glide缓存策略的精妙之处。 如有问题,欢迎指正。
-----------------------------------概述---------------------------------------- Memcached是一套高性能分布式内存对象缓存服务器 Linux、BSD、Solaris等操作系统上发挥其高性能 3.简单key/value存储:服务器不关心数据本身的意义及结构,只要是可序列化数据即可;存储项由“键、过期时间、可选的标志及数据”四个部分组成 4. 客户负责发送存储项至服务器端、从服务端获取数据以及无法连接至服务器时采用相应的动作;服务端负责接收、存储数据,并负责数据项的超时过期 ----------------------------------------缓存策略 比如将100字节的数据缓存到128字节的chunk中,剩余的28字节就浪费了;按照预先规定的大小,将分配的内存分割成特定长度的内存块chunk,再把尺寸相同的内存块分层组chunk集合,这些内存不会释放 存取操作均通过key进行,例如可以把后端数据库中的select操作提取出来,然后对相应的SQL进行hash计算得出key,然后以这个key在memcached中查找数据,如果数据不存在,说明其尚未被写入缓存中
【持久化存储模块/策略】,使我们可以更加精准地控制缓存,即使是在 http 缓存过期之后也可以使用。 [7f5faf365c33fdb57f308cd15d4492b4.png] 使用优测平台(http://utest.oa.com) 从报表中清晰看到测试了五轮,除了第一轮,我们缓存在本地的静态资源均没有再被请求加载 [a88b975cb6391c0a807450163e401e5c.png] 过期策略 在LocalStorage中存在一组key: _gzh_cache_webuy.qq.com/static/js 技术实现 * 支持缓存的文件类型:js|css * 根据文件MD5摘要或版本号比对缓存变化,若无变化,直接使用缓存的内容,若有变化,请求服务器,然后替换旧缓存内容 */ var PREFIX = xhr.open('GET', resolve(file.src)); xhr.onreadystatechange = function() { if (xhr.readyState === 4)
上一篇文章我写了koa-static的源码解析[1],其中用到了HTTP的缓存策略,给返回的静态文件设置了一些缓存的头,比如Cache-Control之类的。 于是我就跟朋友讨论了一下HTTP的缓存策略: 朋友说:“HTTP里面控制缓存的头(header)太多了,啥Cache-Control,ETag,Last-Modified,一大堆,乱七八糟的,而且之间逻辑关系不强 HTTP缓存策略只是为了解决客户端和服务端信息不对称的问题而存在的,客户端为了加快速度会缓存部分资源,但是下次请求时,客户端不知道这个资源有没有更新,服务端也不知道客户端缓存的是哪个版本,不知道该不该再返回资源 ,其实就是一个信息同步问题,HTTP缓存策略就是来解决这个问题的。 4.Expires的值是一个时间,表示这个时间前缓存都有效,都不需要发起请求。
场景描述 比如一条数据同时存在数据库、缓存,现在你要更新此数据,你会怎么更新? 先更新数据库?还是先更新缓存? 其实这两种方式都有问题。 (1)先更新数据库,后更新缓存 ? 这样会造成数据不一致。 A 先把数据库更新为 123,由于网络问题,更新缓存的动作慢了。 这时,B 去更新数据库了,改为了 456,紧接着把缓存也更新为 456。 现在 A 更新缓存的请求到了,把缓存更新为了 123。 Cache Aside 策略 其实,在更新数据时,我们可以不更新缓存,而是删除缓存中的数据,在读取数据时,发现缓存中没有,再从数据库中读取数据,更新到缓存中。 这就是 Cache Aside 策略(旁路缓存策略)。 读策略步骤 ? 写策略步骤 ? 写时可以不可以先删除缓存?不行! 例如这个场景: ? A 先删了缓存,还没等数据库更新完成呢,就被 B 把缓存更新为了旧值。 注意 Cache Aside 策略也是不保证数据一致性的,它的作用是大大减少不一致性。
目前常用的一种缓存算法是lru(least recently used),它的核心思想是当缓存满了,会优先淘汰近期最少使用的缓存对象。 当缓存空间不足时,可以remove头部结点释放缓存空间。 disklrucache顾名思义,实现存储设备缓存,即磁盘缓存,它通过将缓存对象写入文件系统从而实现缓存效果。 ps: 如果缓存的图片经常被使用,可以考虑使用contentprovider。 disklrucache的数据缓存与获取缓存: 数据缓存操作是借助disklrucache.editor类完成的,editor表示一个缓存对象的编辑对象。 缓存策略对比与总结 lrucache是android中已经封装好的类,disklrucache需要导入相应的包才可以使用。