轉載請注明出處哈: http://carlosfu.iteye.com/blog/2237511
更多BigMemory Go可參考官方文檔:
http://www.terracotta.org/documentation/4.0/bigmemorygo一、BigMemory證書:
(1). 由于BigMemory是商業版,需要從官網上注冊、下載下傳證書(目前隻支援90天)和對應版本的jar包:
下載下傳位址:
http://terracotta.org/downloads/bigmemorygo,完成表單填寫,完成下載下傳。
(2). 可以将證書放到classpath下,或者加入啟動參數:
-Dcom.tc.productkey.path=/path/to/terracotta-license.key
(3). 證書示例:
# This software license, granted by Terracotta Inc. - a Software AG company, is valid for and may only be used
# by the licensee of this product ("Licensee").
# Descriptor version: 4
# ------------------------------------------------------------------------------------
Date of Issue: 2015-08-19
Expiration Date: 2015-11-17
License Type: Trial
License Number: 1009994
Licensee: deren zhang, it
Email: [email protected]
Product: BigMemory Go
Edition: DX
Capabilities: ehcache, TMC, ehcache offheap
Max Client Count: 0
ehcache.maxOffHeap: 32G
Signature: MC0CFHmKKAqyuq+bmly3S6GzM9yJDznNAhUAjDDruAR/GtZRFs2dkUP6WtK7MTU=
其中:
ehcache.maxOffHeap代表最大的堆外記憶體
Capabilities: ehcache, TMC, ehcache offheap:表示證書可以适用于 ehcache, TMC, ehcache offheap
Signature:證書号
二、依賴
1. BigMemory依賴
<bigmemory.version>4.0.5</bigmemory.version>
<ehcache-ee.version>2.7.5</ehcache-ee.version>
<dependency>
<groupId>org.terracotta.bigmemory</groupId>
<artifactId>bigmemory</artifactId>
<version>${bigmemory.version}</version>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-ee</artifactId>
<version>${ehcache-ee.version}</version>
</dependency>
2. 序列化工具protostuff依賴
<protostuff.version>1.0.8</protostuff.version>
<dependency>
<groupId>com.dyuproject.protostuff</groupId>
<artifactId>protostuff-runtime</artifactId>
<version>${protostuff.version}</version>
</dependency>
<dependency>
<groupId>com.dyuproject.protostuff</groupId>
<artifactId>protostuff-core</artifactId>
<version>${protostuff.version}</version>
</dependency>
3. logback依賴(logback實作了slf4j-api)
<logback.version>1.0.13</logback.version>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
4. 引入junit
<junit.version>4.11</junit.version>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
5.最終pom配置
<properties>
<bigmemory.version>4.0.5</bigmemory.version>
<ehcache-ee.version>2.7.5</ehcache-ee.version>
<protostuff.version>1.0.8</protostuff.version>
<logback.version>1.0.13</logback.version>
<junit.version>4.11</junit.version>
</properties>
<dependencies>
<dependency>
<groupId>org.terracotta.bigmemory</groupId>
<artifactId>bigmemory</artifactId>
<version>${bigmemory.version}</version>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-ee</artifactId>
<version>${ehcache-ee.version}</version>
</dependency>
<dependency>
<groupId>com.dyuproject.protostuff</groupId>
<artifactId>protostuff-runtime</artifactId>
<version>${protostuff.version}</version>
</dependency>
<dependency>
<groupId>com.dyuproject.protostuff</groupId>
<artifactId>protostuff-core</artifactId>
<version>${protostuff.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
三、BigMemory配置
BigMemory的配置一般也叫ehcache.xml, 放到classpath下:我們使用極簡配置
<?xml version="1.0" encoding="UTF-8" ?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
<cache name="firstOffHeapCache" maxBytesLocalHeap="32M" maxBytesLocalOffHeap="1024M"/>
</ehcache>
Bigmemory的配置相對于Ehcache添加了兩個屬性:
maxBytesLocalOffHeap: 最大堆外記憶體
maxBytesLocalHeap:堆外記憶體在堆内記憶體的熱點資料最大值
四、logback配置
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="5 seconds">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
五、BigMemory測試:
1. 一個實體類:
package com.sohu.tv.bigmemory.first;
import java.util.Date;
/**
* 俱樂部
*
* @author leifu
* @Date 2015年7月28日
* @Time 下午1:43:53
*/
public class Club {
/**
* 俱樂部id
*/
private int id;
/**
* 俱樂部名
*/
private String clubName;
/**
* 俱樂部描述
*/
private String clubInfo;
/**
* 建立日期
*/
private Date createDate;
/**
* 排名
*/
private int rank;
public Club(int id, String clubName, String clubInfo, Date createDate, int rank) {
super();
this.id = id;
this.clubName = clubName;
this.clubInfo = clubInfo;
this.createDate = createDate;
this.rank = rank;
}
public Club() {
super();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getClubName() {
return clubName;
}
public void setClubName(String clubName) {
this.clubName = clubName;
}
public String getClubInfo() {
return clubInfo;
}
public void setClubInfo(String clubInfo) {
this.clubInfo = clubInfo;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
public int getRank() {
return rank;
}
public void setRank(int rank) {
this.rank = rank;
}
@Override
public String toString() {
return "Club [id=" + id + ", clubName=" + clubName + ", clubInfo=" + clubInfo + ", createDate=" + createDate
+ ", rank=" + rank + "]";
}
}
2. BigMemory測試(Ehcache單元測試作為測試)
(1) 單元測試:
package com.sohu.tv.bigmemory.first;
import java.util.Date;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
/**
* 第一個BigMemory測試
*
* @author leifu
* @Date 2015年8月12日
* @Time 上午10:14:13
*/
public class FirstBigmemoryTest {
private static Logger logger = LoggerFactory.getLogger(FirstBigmemoryTest.class);
private static Cache cache;
private static final String BIGMEORY_CACHE_NAME = "firstOffHeapCache";
@BeforeClass
public static void setUp() {
CacheManager cacheManager = CacheManager.create(FirstBigmemoryTest.class.getClassLoader()
.getResourceAsStream("ehcache.xml"));
// 列印cacheManager管理的cache
String[] cacheNameArr = cacheManager.getCacheNames();
for (String cacheName : cacheNameArr) {
logger.info("cacheName: {}", cacheName);
}
cache = cacheManager.getCache(BIGMEORY_CACHE_NAME);
}
@Test
public void testCRUD() {
logger.info("At start, bigmemory object size: {}", cache.getSize());
// 唯一key
String key = "football:club:1";
Club club = new Club(1, "AC", "AC米蘭", new Date(), 1);
// 增
Element element = new Element(key, club);
cache.put(element);
logger.info("after add bigmemory object size: {}", cache.getSize());
// 查
Element elementResult = cache.get(key);
Club clubResult = (Club) elementResult.getObjectValue();
logger.info("get key {} value is {}", key, clubResult.toString());
// 修改
club.setRank(8888);
cache.put(element);
logger.info("after set bigmemory object size: {}", cache.getSize());
// 再查
Element elementResultAgain = cache.get(key);
Club clubResultAgain = (Club) elementResultAgain.getObjectValue();
logger.info("get key {} again value is {}", key, clubResultAgain.toString());
// 删
boolean removeResult = cache.remove(key);
logger.info("remove result is {}, after remove bigmemory object size: {}", removeResult, cache.getSize());
// 增加一條,觀察下次啟動
cache.put(element);
logger.info("At final, bigmemory object size: " + cache.getSize());
// 生産環境不要使用,影響性能
logger.info("At final, bigmemory memory size: " + cache.calculateInMemorySize());
}
}
(2) 輸出報錯:Club必須序列化
net.sf.ehcache.CacheException: The element '[ key = football:club:1, value=Club [id=1, clubName=AC, clubInfo=AC米蘭, createDate=Sat Aug 22 09:40:29 CST 2015, rank=1], version=1, hitCount=0, CreationTime = 1440207629814, LastAccessTime = 1440207629814 ]' is not serializable and cannot be put into the offheap cache firstOffHeapCache
at net.sf.ehcache.store.offheap.OffHeapStore.handleNotSerializableException(OffHeapStore.java:384)
at net.sf.ehcache.store.offheap.OffHeapStore.putFaulted(OffHeapStore.java:419)
at net.sf.ehcache.store.CacheStore$2.call(CacheStore.java:127)
at net.sf.ehcache.store.CacheStore$2.call(CacheStore.java:121)
at net.sf.ehcache.store.cachingtier.OnHeapCachingTier$Fault.get(OnHeapCachingTier.java:327)
at net.sf.ehcache.store.cachingtier.OnHeapCachingTier$Fault.access$200(OnHeapCachingTier.java:304)
at net.sf.ehcache.store.cachingtier.OnHeapCachingTier.get(OnHeapCachingTier.java:174)
at net.sf.ehcache.store.CacheStore.put(CacheStore.java:121)
at net.sf.ehcache.Cache.putInternal(Cache.java:1501)
at net.sf.ehcache.Cache.put(Cache.java:1427)
at net.sf.ehcache.Cache.put(Cache.java:1392)
at com.sohu.tv.bigmemory.first.FirstBigmemoryTest.testCRUD(FirstBigmemoryTest.java:41)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
(3) 修複:Club實作序列化接口
public class Club implements Serializable
(4) 輸出結果正常:
輸出資訊包含證書的驗證、BigMemory堆外記憶體的配置設定
11:04:00.965 [main] INFO o.t.license.ehcache.LicenseManager - Terracotta license loaded from resource /terracotta-license.key
11:04:01.287 [main] INFO n.s.e.p.s.f.AnnotationSizeOfFilter - Using regular expression provided through VM argument net.sf.ehcache.pool.sizeof.ignore.pattern for IgnoreSizeOf annotation : ^.*cache\..*IgnoreSizeOf$
11:04:01.296 [main] INFO n.sf.ehcache.pool.sizeof.AgentLoader - Located valid 'tools.jar' at 'C:\Program Files\Java\jdk1.7.0_60\jre\..\lib\tools.jar'
11:04:01.358 [main] INFO n.s.e.pool.sizeof.JvmInformation - Detected JVM data model settings of: 64-Bit HotSpot JVM with Compressed OOPs
11:04:01.430 [main] INFO n.sf.ehcache.pool.sizeof.AgentLoader - Extracted agent jar to temporary file C:\Users\leifu\AppData\Local\Temp\ehcache-sizeof-agent1571240522467793322.jar
11:04:01.430 [main] INFO n.sf.ehcache.pool.sizeof.AgentLoader - Trying to load agent @ C:\Users\leifu\AppData\Local\Temp\ehcache-sizeof-agent1571240522467793322.jar
11:04:01.438 [main] INFO n.s.e.pool.impl.DefaultSizeOfEngine - using Agent sizeof engine
11:04:01.510 [main] INFO n.s.e.s.offheap.OffHeapStoreFactory - Creating Off-Heap Area Using Config
Heuristic Configuration: firstOffHeapCache
Maximum Size (specified) : 2GB
Minimum Chunk Size : 128MB
Maximum Chunk Size : 1GB
Concurrency : 64
Initial Segment Table Size : 1K slots
Segment Data Page Size : 1MB
11:04:01.515 [main] INFO c.t.o.p.UpfrontAllocatingPageSource - Allocating 2GB in chunks
11:04:02.215 [main] INFO c.t.o.p.UpfrontAllocatingPageSource - Allocated 2GB in 1GB chunks.
11:04:02.215 [main] INFO c.t.o.p.UpfrontAllocatingPageSource - Took 699 ms to create CacheManager off-heap storage of 2GB.
11:04:02.304 [main] INFO c.s.t.b.first.FirstBigmemoryTest - cacheName: firstOffHeapCache
11:04:02.307 [main] INFO c.s.t.b.first.FirstBigmemoryTest - At start, bigmemory object size: 0
11:04:02.343 [main] INFO c.s.t.b.first.FirstBigmemoryTest - after add bigmemory object size: 1
11:04:02.346 [main] INFO c.s.t.b.first.FirstBigmemoryTest - get key football:club:1 value is Club [id=1, clubName=AC, clubInfo=AC米蘭, createDate=Sat Aug 22 11:04:02 CST 2015, rank=1]
11:04:02.396 [main] INFO c.s.t.b.first.FirstBigmemoryTest - after set bigmemory object size: 1
11:04:02.396 [main] INFO c.s.t.b.first.FirstBigmemoryTest - get key football:club:1 again value is Club [id=1, clubName=AC, clubInfo=AC米蘭, createDate=Sat Aug 22 11:04:02 CST 2015, rank=8888]
11:04:02.397 [main] INFO c.s.t.b.first.FirstBigmemoryTest - remove result is true, after remove bigmemory object size: 0
11:04:02.398 [main] INFO c.s.t.b.first.FirstBigmemoryTest - At final, bigmemory object size: 1
11:04:02.398 [main] INFO c.s.t.b.first.FirstBigmemoryTest - At final, bigmemory memory size: 784
3. BigMemory測試結論:
(1) 堆外記憶體存儲的資料需要序列化。
(2) BigMemory使用Ehcache ee可以自動完成序列化,如果使用BigMemory存儲java對象,就會存在SizeOf問題(簡單對象除外),是以可以使用預序列化方式序列化要存的資料。
具體參考:
BigMemory關于sizeOf引擎的測試.(3) BigMemory啟動時候,會尋找BigMemory證書。
(4) 以下是bigMemory啟動時列印的DirectMemory分區概述,
根據日志,可以猜測出BigMemory預先将資料空間劃分為一系列Chunk,目的為了防止記憶體碎片化,與Memcache記憶體配置設定政策很像.
六、BigMemory堆外記憶體,JVM啟動參數:
-XX:MaxDirectMemorySize=4G
七、BigMemory更多使用示例:
http://www.terracotta.org/documentation/4.0/bigmemorygo/code-samples八、使用ProtoStuff序列化:
1. ProtoStuff序列化工具:
package com.sohu.tv.serializer;
import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtostuffIOUtil;
import com.dyuproject.protostuff.Schema;
import com.dyuproject.protostuff.runtime.RuntimeSchema;
import java.util.concurrent.ConcurrentHashMap;
/**
* protostuff序列化工具
*
* @author leifu
* @Date 2015-8-22
* @Time 上午10:05:20
*/
public class ProtostuffSerializer {
private static ConcurrentHashMap<Class<?>, Schema<?>> cachedSchema = new ConcurrentHashMap<Class<?>, Schema<?>>();
public <T> byte[] serialize(final T source) {
VO<T> vo = new VO<T>(source);
final LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
try {
final Schema<VO> schema = getSchema(VO.class);
return serializeInternal(vo, schema, buffer);
} catch (final Exception e) {
throw new IllegalStateException(e.getMessage(), e);
} finally {
buffer.clear();
}
}
public <T> T deserialize(final byte[] bytes) {
try {
Schema<VO> schema = getSchema(VO.class);
VO vo = deserializeInternal(bytes, schema.newMessage(), schema);
if (vo != null && vo.getValue() != null) {
return (T) vo.getValue();
}
} catch (final Exception e) {
throw new IllegalStateException(e.getMessage(), e);
}
return null;
}
private <T> byte[] serializeInternal(final T source, final Schema<T> schema, final LinkedBuffer buffer) {
return ProtostuffIOUtil.toByteArray(source, schema, buffer);
}
private <T> T deserializeInternal(final byte[] bytes, final T result, final Schema<T> schema) {
ProtostuffIOUtil.mergeFrom(bytes, result, schema);
return result;
}
private static <T> Schema<T> getSchema(Class<T> clazz) {
@SuppressWarnings("unchecked")
Schema<T> schema = (Schema<T>) cachedSchema.get(clazz);
if (schema == null) {
schema = RuntimeSchema.createFrom(clazz);
cachedSchema.put(clazz, schema);
}
return schema;
}
}
package com.sohu.tv.serializer;
import java.io.Serializable;
/**
* @author leifu
* @Date 2015-8-22
* @Time 上午10:05:44
* @param <T>
*/
public class VO<T> implements Serializable {
private T value;
public VO(T value) {
this.value = value;
}
public VO() {
}
public T getValue() {
return value;
}
@Override
public String toString() {
return "VO{" +
"value=" + value +
'}';
}
}
2. ProtoStuff + BigMemory單元測試:
@Test
public void testBigMemoryWithSerializable() {
ProtostuffSerializer protostuffSerializer = new ProtostuffSerializer();
// 唯一key
String key = "football:club:1";
byte[] clubBytes = protostuffSerializer.serialize(new Club(1, "AC", "AC米蘭", new Date(), 1));
// 增
Element element = new Element(key, clubBytes);
cache.put(element);
// 查
Element elementResult = cache.get(key);
byte[] clubBytesResult = (byte[]) elementResult.getObjectValue();
Club clubResult = protostuffSerializer.deserialize(clubBytesResult);
logger.info("get key {} value is {}", key, clubResult.toString());
}
輸出:
12:49:31.276 [main] INFO o.t.license.ehcache.LicenseManager - Terracotta license loaded from resource /terracotta-license.key
12:49:31.627 [main] INFO n.s.e.p.s.f.AnnotationSizeOfFilter - Using regular expression provided through VM argument net.sf.ehcache.pool.sizeof.ignore.pattern for IgnoreSizeOf annotation : ^.*cache\..*IgnoreSizeOf$
12:49:31.634 [main] INFO n.sf.ehcache.pool.sizeof.AgentLoader - Located valid 'tools.jar' at 'C:\Program Files\Java\jdk1.7.0_60\jre\..\lib\tools.jar'
12:49:31.694 [main] INFO n.s.e.pool.sizeof.JvmInformation - Detected JVM data model settings of: 64-Bit HotSpot JVM with Compressed OOPs
12:49:31.771 [main] INFO n.sf.ehcache.pool.sizeof.AgentLoader - Extracted agent jar to temporary file C:\Users\leifu\AppData\Local\Temp\ehcache-sizeof-agent7979572902856961639.jar
12:49:31.771 [main] INFO n.sf.ehcache.pool.sizeof.AgentLoader - Trying to load agent @ C:\Users\leifu\AppData\Local\Temp\ehcache-sizeof-agent7979572902856961639.jar
12:49:31.783 [main] INFO n.s.e.pool.impl.DefaultSizeOfEngine - using Agent sizeof engine
12:49:31.839 [main] INFO n.s.e.s.offheap.OffHeapStoreFactory - Creating Off-Heap Area Using Config
12:49:31.847 [main] INFO c.t.o.p.UpfrontAllocatingPageSource - Allocating 2GB in chunks
12:49:32.682 [main] INFO c.t.o.p.UpfrontAllocatingPageSource - Allocated 2GB in 1GB chunks.
12:49:32.682 [main] INFO c.t.o.p.UpfrontAllocatingPageSource - Took 835 ms to create CacheManager off-heap storage of 2GB.
12:49:32.801 [main] INFO c.s.t.b.first.FirstBigmemoryTest - cacheName: firstOffHeapCache
12:49:32.952 [main] INFO c.s.t.b.first.FirstBigmemoryTest - get key football:club:1 value is Club [id=1, clubName=AC, clubInfo=AC米蘭, createDate=Sat Aug 22 12:49:32 CST 2015, rank=1]