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

一、緩存技術簡介
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對應的堆外記憶體區域同時也就被釋放掉了。