前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >缓存技术-大促场景下热点数据的读/写优化方案

缓存技术-大促场景下热点数据的读/写优化方案

作者头像
凹谷
发布2020-04-11 11:05:14
1.7K0
发布2020-04-11 11:05:14
举报

敢于跨出第一步,往往是成功的开始。

一、缓存技术简介

1、缓存是指将被频繁访问的热点数据存储在距离计算最近的地方,以方便系统快速做出响应。

eg:静态资源可缓存到CDN(Content Delivery NetWork,内容分发网络,即离电信运营商最近的机房)上。也可以缓存到反向代理服务器,与CDN不同的是,反向代理服务器属于企业内部机房,它挡在应用服务器的前端。

2、缓存分本地缓存和分布式缓存,比如:Ehcache、MemCache及Redis

3、缓存主要解决以下问题:

缓解应用系统或关系型数据库的负载压力

提升系统的吞吐量

4、本地缓存:会共享同一个JVM进程内的heap空间,从Ehcache3.x以后提供off-heap(堆外内存),堆外内存可以减少GC次数或降低暂停时间,可以扩展和使用更大的内存空间。

5、分布式缓存:由于本地缓存的容量有限,无法实现横向扩展,因此从本地缓存架构演变到分布式缓存架构是必经之路。常见分布式缓存有Redis、MemCache

二、实际应用场景

1、基于Redis集群多写多读方案,保障多写时的数据一致性可以借助Zookeeper

2、LocalCache结合Redis集群的多级Cache方案

三、扩展,深度了解JVM堆内内存和堆外内存(转载)

1、什么是堆内内存

Java 虚拟机在执行Java程序的过程中会把它在主存中管理的内存部分划分成多个区域,每个区域存放不同类型的数据。下图所示为java虚拟机运行的时候,主要的内存分区:

在这些分区中,占用内存空间最大的一部分叫做“堆(heap)”,也就是我们所说的堆内内存(on-heap memory)。java虚拟机中的“堆”主要是存放所有对象的实例。这一块区域在java虚拟机启动的时候被创建,被所有的线程所共享,同时也是垃圾收集器的主要工作区域,因此这一部分区域除了被叫做“堆内内存”以外,也被叫做“GC堆”(Garbage Collected Heap)。

1.1 堆内内存的垃圾回收

堆内内存是java垃圾收集器的主要工作区域,为了提高垃圾回收的效率,在堆内内存的内部又划分出了新生代、老年代和永久代。在新生代内存中又按照8:1:1的比例(java虚拟机默认分配比例为8:1:1,这个比例也可以自定义)划分出了Eden, Survivor1, Survivor2三个区域。

在执行垃圾回收算法的时候,不同的回收算法会对内存区域造成不一样的影响。但是大部分的回收算法会造成堆内内存空间在物理上的不连续性。下面以最基本的垃圾回收算法“标记 - 清除算法”为例:

可以看到,内存区域在经过垃圾回收之后,产生大量不连续的内存空间。因此,java虚拟机中的堆内内存区域,只是逻辑上的连续,并不能保证物理上的连续性。 所以,操作系统并不能直接得到堆内内存区域所存储的数据在主存中的正确地址。在一些特定的时间点,Java虚拟机会进行一次彻底的垃圾回收(full gc)。彻底回收时,垃圾收集器会对所有分配的堆内内存进行完整的扫描,在扫描期间,绝大部分正在运行的java线程都会被暂时停止。这意味着:这样一次垃圾收集对Java应用造成的影响,跟堆内内存所存储的数据的多少是成正比的,过大的堆内内存会影响Java应用的性能。

2. 堆外内存(off-heap memory)

2.1 堆外内存的产生

为了解决堆内内存过大带来的长时间的GC停顿的问题,以及操作系统对堆内内存不可知的问题,java虚拟机开辟出了堆外内存(off-heap memory)。堆外内存意味着把一些对象的实例分配在Java虚拟机堆内内存以外的内存区域,这些内存直接受操作系统(而不是虚拟机)管理。这样做的结果就是能保持一个较小的堆,以减少垃圾收集对应用的影响。同时因为这部分区域直接受操作系统的管理,别的进程和设备(例如GPU)可以直接通过操作系统对其进行访问,减少了从虚拟机中复制内存数据的过程。

2.2 堆外内存的分配

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 {

while (true) {

ByteBuffer buffer = ByteBuffer.allocateDirect(10 * 1024 * 1024);

}

}

}

这样我们就开辟出了一块大小为10M的堆外内存。

3. 堆外内存的优缺点以及与堆内内存联系

3.1堆外内存的优缺点:

优点 :

可以很方便的自主开辟很大的内存空间,对大内存的伸缩性很好

减少垃圾回收带来的系统停顿时间

直接受操作系统控制,可以直接被其他进程和设备访问,减少了原本从虚拟机复制的过程

特别适合那些分配次数少,读写操作很频繁的场景

缺点 :

容易出现内存泄漏,并且很难排查

堆外内存的数据结构不直观,当存储结构复杂的对象时,会浪费大量的时间对其进行串行化。

3.2 堆内内存与堆外内存的联系:

虽然堆外内存本身不受垃圾回收算法的管辖,但是因为其是由ByteBuffer所创造出来的,因此这个buffer自身作为一个实例化的对象,其自身的信息(例如堆外内存在主存中的起始地址等信息)必须存储在堆内内存中,具体情况如下图所示。

当在堆内内存中存放的buffer对象实例被垃圾回收算法回收掉的时候,这个buffer对应的堆外内存区域同时也就被释放掉了。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-10-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 大数据与微服务架构 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档