写在前面当开始一个项目时,它没有过多考虑性能问题,而是专注于快速迭代。
随着业务的快速发展,系统的性能越来越慢。
这时,需要对系统进行相应的优化,最显着的效果是为系统添加了缓存。
所以,问题来了。
在向系统添加缓存时,您是否考虑过使用缓存时需要注意的事项?高速缓存命中率高速缓存命中率是从高速缓存中读取数据的次数与总读取次数之比。
命中率越高,效果越好。
高速缓存命中率=从高速缓存读取的次数/(总读取次数(从高速缓存读取的次数+从慢速设备读取的次数))。
这是非常重要的监视指标。
如果要缓存,则应监视此指示器以查看缓存是否运行良好。
缓存类型一般来说,缓存类型可以分为:堆缓存,堆外缓存,磁盘缓存和分布式缓存。
堆内存使用Java堆内存来存储对象。
使用堆缓存的优点是没有序列化/反序列化,并且它是最快的缓存。
缺点也很明显。
当高速缓存的数据量很大时,GC(垃圾收集)的暂停时间将变长,并且存储容量受堆空间大小的限制。
通常,软引用/弱引用用于存储缓存的对象。
也就是说,当堆内存不足时,可以强制恢复这部分内存以释放堆内存空间。
堆缓存通常用于存储热数据。
可以使用Guava Cache,Ehcache 3.x和MapDB来实现。
堆外内存意味着将缓存的数据存储在堆外内存中,这可以减少GC暂停时间(将堆对象移出堆,并且GC扫描并移动更少的对象),并且可以支持更多的缓存空间(仅有限)机器内存大小),不受堆空间的影响。
但是,读取数据时需要序列化/反序列化。
因此,它将比堆缓存慢得多。
可以使用Ehcache 3.x和MapDB来实现。
磁盘缓存是指将缓存的数据存储在磁盘上。
重新启动JVM时数据仍然存在,但是堆/堆外缓存数据将丢失,需要重新加载。
可以使用Ehcache 3.x和MapDB来实现。
分布式缓存分布式缓存可以使用ehcache集群(与Terracotta服务器一起)来实现Java进程间分布式缓存。
也可以使用Memcached和Redis来实现。
使用分布式高速缓存时,有以下两种模式:独立模式:将最热的数据存储在堆高速缓存中,将相对热的数据存储在堆外高速缓存中,将非热数据存储在磁盘高速缓存中。
集群模式:将最热的数据存储在堆缓存中,将相对热的数据存储在外部缓存中,并将所有数据存储在分布式缓存中。
缓存恢复策略缓存恢复策略通常包括:基于空间的恢复策略,基于容量(空间)的恢复策略,基于时间的恢复策略和基于对象引用的恢复策略。
基于空间的是指缓存设置的存储空间,例如10MB。
当达到存储空间的上限时,将根据某种策略删除数据。
基于容量的是指高速缓存设置的最大大小。
当缓存的条目超过最大大小时,将根据特定策略删除旧数据。
基于时间的TTL(生存时间):生命周期,即从开始创建缓存数据到到期的时间(无论在此时间段内是否访问缓存数据,缓存数据都会过期)。
TTI(空闲时间):空闲时间,即在未访问缓存的数据之后删除缓存的时间。
基于对象引用的软引用:如果对象是软引用,则当JVM堆内存不足时,垃圾收集器可以回收这些对象。
软引用适用于缓存,因此,当JVM堆内存不足时,可以回收这些对象以释放一些用于强引用对象的空间,从而避免了OOM。
弱引用:当垃圾收集器回收内存时,如果发现弱引用,则将立即对其进行回收。
与软引用相比,弱引用的生命周期更短。
注意:仅当没有其他强引用对象引用弱引用/软引用对象时,该引用才会在垃圾回收期间被回收。
也就是说,如果某个对象(不是弱引用/软引用对象)引用了弱引用/软引用对象,则在垃圾回收期间将不会回收弱引用/软引用对象。
回收算法基于空间和基于容量的缓存的使用将使用某些策略来删除旧数据,通常包括:FIFO algori