缓存技术-大促场景下热点数据的读/写优化方案
Posted 大数据与微服务架构
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了缓存技术-大促场景下热点数据的读/写优化方案相关的知识,希望对你有一定的参考价值。
敢于跨出第一步,往往是成功的开始。
一、缓存技术简介
1、缓存是指将被频繁访问的热点数据存储在距离计算最近的地方,以方便系统快速做出响应。
eg:
静态资源可缓存到CDN(Content Delivery NetWork,内容分发网络,即离电信运营商最近的机房)上。
也可以缓存到反向代理服务器,与CDN不同的是,反向代理服务器属于企业内部机房,它挡在应用服务器的前端。
2、缓存分本地缓存和分布式缓存,比如:
Ehcache、MemCache及Redis
4、本地缓存:
会共享同一个JVM进程内的heap空间,从Ehcache3.x以后提供off-heap(堆外内存),堆外内存可以减少GC次数或降低暂停时间,可以扩展和使用更大的内存空间。
5、分布式缓存:
由于本地缓存的容量有限,无法实现横向扩展,因此从本地缓存架构演变到分布式缓存架构是必经之路。
常见分布式缓存有Redis、MemCache
二、实际应用场景
1、基于Redis集群多写多读方案,保障多写时的数据一致性可以借助Zookeeper
2、LocalCache结合Redis集群的多级Cache方案
三、扩展,深度了解JVM堆内内存和堆外内存(转载)
Java 虚拟机在执行Java程序的过程中会把它在主存中管理的内存部分划分成多个区域,每个区域存放不同类型的数据。
下图所示为java虚拟机运行的时候,主要的内存分区:
在这些分区中,占用内存空间最大的一部分叫做“堆(heap)”,也就是我们所说的堆内内存(on-heap memory)。
java虚拟机中的“堆”主要是存放所有对象的实例。
这一块区域在java虚拟机启动的时候被创建,被所有的线程所共享,同时也是垃圾收集器的主要工作区域,因此这一部分区域除了被叫做“堆内内存”以外,也被叫做“GC堆”(Garbage Collected Heap)。
堆内内存是java垃圾收集器的主要工作区域,为了提高垃圾回收的效率,在堆内内存的内部又划分出了新生代、老年代和永久代。
在新生代内存中又按照8:1:1的比例(java虚拟机默认分配比例为8:1:1,这个比例也可以自定义)划分出了Eden, Survivor1, Survivor2三个区域。
在执行垃圾回收算法的时候,不同的回收算法会对内存区域造成不一样的影响。
但是大部分的回收算法会造成堆内内存空间在物理上的不连续性。
下面以最基本的垃圾回收算法“标记 - 清除算法”为例:
可以看到,内存区域在经过垃圾回收之后,产生大量不连续的内存空间。
因此,java虚拟机中的堆内内存区域,只是逻辑上的连续,并不能保证物理上的连续性。
所以,操作系统并不能直接得到堆内内存区域所存储的数据在主存中的正确地址。
在一些特定的时间点,Java虚拟机会进行一次彻底的垃圾回收(full gc)。
彻底回收时,垃圾收集器会对所有分配的堆内内存进行完整的扫描,在扫描期间,绝大部分正在运行的java线程都会被暂时停止。
这意味着:
这样一次垃圾收集对Java应用造成的影响,跟堆内内存所存储的数据的多少是成正比的,过大的堆内内存会影响Java应用的性能。
2. 堆外内存(off-heap memory)
为了解决堆内内存过大带来的长时间的GC停顿的问题,以及操作系统对堆内内存不可知的问题,java虚拟机开辟出了堆外内存(off-heap memory)。
堆外内存意味着把一些对象的实例分配在Java虚拟机堆内内存以外的内存区域,这些内存直接受操作系统(而不是虚拟机)管理。
这样做的结果就是能保持一个较小的堆,以减少垃圾收集对应用的影响。
同时因为这部分区域直接受操作系统的管理,别的进程和设备(例如GPU)可以直接通过操作系统对其进行访问,减少了从虚拟机中复制内存数据的过程。
java 在NIO 包中提供了ByteBuffer类,对堆外内存进行访问。
下图为NIO包中ByteBuffer的层次继承关系
import sun.nio.ch.DirectBuffer;
import java.nio.ByteBuffer;
public class TestDirectByteBuffer {
public static void main(String[] args) throws Exception {
ByteBuffer buffer = ByteBuffer.allocateDirect(10 * 1024 * 1024);
3. 堆外内存的优缺点以及与堆内内存联系
可以很方便的自主开辟很大的内存空间,对大内存的伸缩性很好
直接受操作系统控制,可以直接被其他进程和设备访问,减少了原本从虚拟机复制的过程
堆外内存的数据结构不直观,当存储结构复杂的对象时,会浪费大量的时间对其进行串行化。
虽然堆外内存本身不受垃圾回收算法的管辖,但是因为其是由ByteBuffer所创造出来的,因此这个buffer自身作为一个实例化的对象,其自身的信息(例如堆外内存在主存中的起始地址等信息)必须存储在堆内内存中,具体情况如下图所示。
当在堆内内存中存放的buffer对象实例被垃圾回收算法回收掉的时候,这个buffer对应的堆外内存区域同时也就被释放掉了。
以上是关于缓存技术-大促场景下热点数据的读/写优化方案的主要内容,如果未能解决你的问题,请参考以下文章
分布式缓存系统热点key解决方案
Redis 开发与运维缓存设计
应用缓存预热方案设计
应用缓存预热方案设计
应用缓存预热方案设计
应用缓存预热方案设计