用的HTTP协议成为另一个引起问题的协议。 HTTP协议可用于传输大小文件。同时,您可以使用高级功能,例如断点续传。许多FLASH浏览器使用HTTP协议进行视频播放。
如上所述,由于ISP之间的“跨网络支付”问题,某些地方(小型运营商,小区域)的服务器缓存HTTP请求。客户端:客户端http代理在服务器之间设置HTTP代理,解析HTTP请求并缓存请求的资源以存储跨网络计费。此处会出现一些问题,例如费用损失,错误的相应结果,错误的请求等。
大多数CDN供应商将服务器端日志用于计费目的。上述代理服务器可以通过减少实际请求数来减少实际流量。但是,这种类型相对较少,所以没什么大不了的。一些http代理实现中存在错误。例如,对于具有范围请求的HTTP服务器,代理将丢失范围信息,并将整个文件返回给客户端,从而导致客户端请求失败。抱怨CDN服务质量差。
还有一些HTTP代理通过组合不同的HTTP请求标头而导致服务器解析错误。例如,该请求包含多个范围信息。它支持标准的http,但不支持实际的业务层。
对于此类问题,通常可以通过向HTTP标头和URL参数添加任意信息来避免这种情况。但是,最好的选择是直接在请求的链接中包含随机路径,以使上述缓存服务器无法缓存所有信息并使用https协议。
我们在编程中经常听到的是时间,空间和空间的交换。作为可以提高程序性能的灵丹妙药,高速缓存是典型的后者(时间空间)。
随着用户数量和访问次数的增加,应用程序需要支持更多的并发性,而同时应用程序服务器和数据库服务器正在执行更多的计算。但是,通常应用程序服务器资源是有限的,并且数据库每秒可以接受的请求数也受到限制(甚至读取和写入文件)。您如何有效地利用有限的资源来提供最大的吞吐量?一种有效的方法是引入缓存。在每个链接上,请求都可以直接从缓存中获取并返回目标数据,从而减少计算量,有效提高响应速度,并为更多用户提供有限的资源。
缓存并非能治愈所有疾病
首次与缓存“ MAP”联系
我第一次遇到缓存是在我上三年级的时候。在系统中,默认情况下,所有接口都可能需要获取用户信息和某些用户配置。当时,我们的系统检查的更多而更改的更少。这也可以显着提高性能。当时的做法是保持全球化。单例地图被缓存。当时,类名是DBMirror。
大致如下:
类DBMirror {
私有静态映射小于字符串,而用户大于userCache=新的HashMap为(小于)
public static void putUser(字符串键,用户){
userCache.put(key,user);
}
公共静态用户getUser(字符串键){
返回userCache.get(key);
}
专用DBMirror(){}
}
该代码非常简单,并且基本上可以满足当时系统的要求,从而减少了许多数据库读写操作。这是我第一次意识到数据库并不是当时唯一的存储库。
但是,上面的代码有一个主要缺点,随着用户数量的增加,缺少合适的剔除算法会导致地图变大,并且在极端情况下会发生内存溢出。
一般移除策略
如上所述,如果不使用消除算法,则内存空间会越来越大且无法回收。然后,我们来讨论一般的删除策略。FIFO(先进先出)
在先进先出策略中,如果缓存空间不足以为新数据腾出空间(超过最大因子限制),则首先清除进入缓存的第一个数据。
LFU(较少使用)
最少使用的策略是确定元素的使用次数并清除较少使用的元素以释放空间。
LRU(最近最少使用)
最近使用的策略通过根据元素上次使用的时间戳擦除使用次数最多的时间戳记的元素来释放空间。
其他
为缓存元素设置一个过期时间,并清理超出其过期时间的元素。
随机清洁
优先处理大对象
简单的缓存分类
本地缓存:指应用程序的缓存组件。最大的优点是应用程序和缓存处于同一进程中。请求缓存非常快,没有过多的网络开销。单个应用程序不需要群集支持或群集。在某些情况下,在节点不需要相互通知的情况下使用本地缓存更为合适。同时,还有一个缺点,因为缓存与应用程序结合在一起,因此多个应用程序无法直接共享缓存,并且群集中的每个应用程序或每个节点必须维护自己的缓存。单独的缓存浪费了内存。
分布式缓存:是指与应用程序分离的缓存组件或服务,最大的优点是它是独立于本地应用程序的独立应用程序,并且多个应用程序可以直接共享缓存。缺点既有优点也有缺点。由于它是一个独立的应用程序,因此需要与本地节点进行通信,这会在网络上产生依赖性,并且如果缓存服务崩溃,则可能会影响所有依赖性节点。
对于某些单实例服务,或默认情况下其数据未更改的数据,可以使用本地缓存来提高性能。否则,您可以使用分布式缓存。
没有最好的技术解决方案,只有最适合您的解决方案。
缓存使用
Java集合类
以上面的简单示例为例,DBMirror可以使用Map实现简单的内存缓存,而Set和List都可以实现内存缓存的功能。您可以根据并发性选择不同的实现类:HashMap,LinkedHashMap,TreeMap,LinkedTreeMap等。ConcurrentHashMap .总会有一个能让您满意的
尽管此实现非常简单,但它也具有致命的缺点。不能回收未使用的缓存。
番石榴缓存
很多人都熟悉Guava,但这是Google提供的非常有用的Java工具包。 Guava Cache是Guava的本地缓存实现,基于LRU算法,并提供各种缓存过期策略,过期时间,容量等。它简化了高速缓存的使用,并使高速缓存的使用更加激烈。咖啡因
Caffeine是基于Java 8开发的高性能缓存库,可提供最佳命中率。
在本地缓存方面,SpringFramework5.0(SpringBoot2.0)放弃了Google的GuavaCache,而选择了“咖啡因”(Drop Guava缓存由Caffeine [SPR-13797]#18370取代)。您可以充分见证性能和可靠性的好处。
性能测试位于https://github.com/ben-manes/caffeine/wiki/Benchmarks。
高速缓存
Ehcache是一个纯Java开源缓存框架,具有简单的配置,清晰的结构,强大的功能,非常轻巧的缓存实现,并且常用的Hibernate包含了相关的缓存功能。
我在开发初期就使用过它,但是我不知道它是否仍在使用中。
记忆快取
基于高性能分布式内存的键值对象存储系统,用于存储小块任意数据(字符串,对象)
访问数据库以减少数据库的读写负担。
雷迪斯
Redis还是基于用作数据库,缓存和消息代理的内存中数据结构的高性能存储。
它支持更多数据结构,例如字符串,哈希,列表,集合,带范围查询的排序集合,位图,超日志,地理空间索引。
Redis具有内置的复制,Lua脚本,LRU删除,事务和各种级别的磁盘持久性,并通过Redis Sentinel和Redis Cluster自动分区提供了高可用性。
弹簧缓存
Spring Cache不是缓存的实现,而是缓存管理的抽象解决方案,该解决方案消除了样板方法的使用,并保护了Spring最好的缓存使用细节。