Infinispan入门教程

2022-04-14 00:00:00 查询 事务 分布式 缓存 信息

Infinispan 入门

当前版本 7 非稳定,6.x稳定版本

一、简介

1、What is it?

Infinispan是一个高度可扩展,高度可用的键/值数据存储和数据网格平台。它是100%开源的,用Java编写的。 Infinispan的目的是,以暴露该分布的数据结构,高度并行和设计地面行动作出现代的多处理器和多核心架构。它经常被用来作为一个分布式缓存,也可作为一个NoSQL的键/值存储或对象数据库。

2、为什么要使用它?

大多数人使用Infinispan的两个原因之一。首先,作为一个分布式缓存。在数据库中,基于磁盘的NoSQL存储或任何部分的系统,是一个瓶颈面前放的Infinispan可以极大地帮助提高性能。通常情况下,一个简单的缓存是不够的 - 例如,如果您的应用程序集群和缓存的一致性是非常重要的数据一致性。分布式的缓存可以极大地帮助在这里。

其他主要的用例是作为的NoSQL数据存储。除了在内存之中, Infinispan的也可以坚持的数据到一个更存储。我们称之为缓存存储。缓存存储是可插拔的,你可以随便写你自己的,而且许多已经存在供您使用。了解更多关于高速缓存存储 - 与现有的实现,您可以使用今天 - 在本网站的缓存存储部分。

3、一个不太常见的用例是增加clusterability和高可用性的框架。由于的Infinispan公开了一个分布式数据结构,框架和库,也需要集群可以通过嵌入的Infinispan和委托所有的状态管理的Infinispan轻松实现这一点。这样一来,任何框架可以很容易地通过让的Infinispan做所有繁重集群。

4、查询的Infinispan

Infinispan的支持索引和利用,以补充其主要地图的API强大的搜索API的存储网格中的Java对象的搜索。从历史上看,寻找早是在Infinispan的可通过Apache Lucene的API,但由于6.0版本的Infinispan提供了基于一个简单而传神内部DSL自己的查询API 。用新的API搜索可用于嵌入式和远程客户端,而基于Lucene的API是只适用于嵌入式客户端。远程查询功能是在热棒客户端章进一步说明。

5、使用Infinispan查询模块

此模块增加了索引和查询功能, Infinispan的。它使用Hibernate的查询和Apache Lucene来在缓存索引和搜索的对象。它可以让用户获得高速缓存中的对象,而不需要知道他们想要得到的钥匙,每个对象。您可以根据它的一些属性搜索你的对象。例如,要检索所有的红色汽车(确切的元数据匹配),或关于特定主题(全文检索和相关性得分)的所有书籍。

该查询可以表示为Lucene的查询,直接使用Lucene的查询API或内置与Hibernate搜索查询的DSL的帮助下建成。另外,您还可以使用的Infinispan自己查询的DSL其中大部分用户可能会发现更容易比一个基于Lucene在不能够访问一些强大的能力,这是特定于底层的Lucene实现的成本来使用。

二、入门个实例及基础环境

由于熟悉eclipse 环境,所以用javaEEeclipse 开发一个实例

1、 创建一个javaproject 名称为infinispan_stu

当然也可以是web project 。

2、 添加log4j 能力

习惯用log4j所以随便找个log4j.properties文件加入进来

再创建一个lib 目录将log4j-1.2.17.jar文件cp过来

点lib中的jar文件右键菜单,选择 add to build path

3、 添加TestMain.java做为运行主类

添加main方法并添加一句debug信息。测试一下log4j能力。

4、 添加相关jar包

/infinispan_stu/lib/infinispan-core-6.0.2.Final.jar

/infinispan_stu/lib/infinispan-commons-6.0.2.Final.jar

/infinispan_stu/lib/jboss-logging-3.1.2.GA.jar

/infinispan_stu/lib/jboss-marshalling-1.4.4.Final.jar

/infinispan_stu/lib/jboss-marshalling-river-1.3.15.GA.jar

/infinispan_stu/lib/jcip-annotations-1.0.jar

/infinispan_stu/lib/jgroups-3.4.1.Final.jar

5、 添加配置文件infinispan-distribution.xml(分布式)jgroups.xml(传输)

<?xml version="1.0" encoding="UTF-8"?>

<infinispan xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="urn:infinispan:config:6.0 http://www.infinispan.org/schemas/infinispan-config-6.0.xsd"

xmlns="urn:infinispan:config:6.0">

<global>

<transport>

<properties>

<property name="configurationFile" value="jgroups.xml" />

</properties>

</transport>

</global>

<default>

<clustering mode="dist"> <!-- 缓存模式。对于分布,设置模式为'dist'的。对于复制,使用'REPL'。后,为 “INV”。如果高速缓存模式设置为“本地”,所讨论的高速缓存将不支持聚类即使其高速缓存管理器一样。

distribution -->

<l1 enabled="false" />

<hash numOwners="2" />

<sync />

</clustering>

</default>

</infinispan>

6、 创建一个People对象和部门(Dept)对象。

/**

* author:刘树友

* Email :shuyouliu@126.com

* QQ :261099288

* Date :2014-5-5

*/

package cn.shuyouliu.infinispan.bean;

/**

* @author liusy

*

*/

public class People {
private Long id;

private String code;

private String name;

private String sex;

private Integer age;

private String deptcode;

private String readme;

public People(Long id, String code, String name, String sex, Integer age,

String deptcode, String readme) {
super();

this.id = id;

this.code = code;

this.name = name;

this.sex = sex;

this.age = age;

this.deptcode = deptcode;

this.readme = readme;

}

public Long getId() {
return id;

}

public void setId(Long id) {
this.id = id;

}

public String getCode() {
return code;

}

public void setCode(String code) {
this.code = code;

}

public String getName() {
return name;

}

public void setName(String name) {
this.name = name;

}

public String getSex() {
return sex;

}

public void setSex(String sex) {
this.sex = sex;

}

public Integer getAge() {
return age;

}

public void setAge(Integer age) {
this.age = age;

}

public String getDeptid() {
return deptcode;

}

public void setDeptid(String deptcode) {
this.deptcode = deptcode;

}

public String getReadme() {
return readme;

}

public void setReadme(String readme) {
this.readme = readme;

}

@Override

public String toString() {
return "{name:People,value:{id:" + id + ", code:" + code + ", name:"

+ name + ", sex:" + sex + ", age:" + age + ", deptcode:"

+ deptcode + ", readme:" + readme + "}}";

}

}

/**

* author:刘树友

* Email :shuyouliu@126.com

* QQ :261099288

* Date :2014-5-5

*/

package cn.shuyouliu.infinispan.bean;

/**

* @author liusy

*

*/

public class Dept {
private String code;

private String name;

private Integer level;

public Dept(String code, String name, Integer level) {
super();

this.code = code;

this.name = name;

this.level = level;

}

public String getCode() {
return code;

}

public void setCode(String code) {
this.code = code;

}

public String getName() {
return name;

}

public void setName(String name) {
this.name = name;

}

public Integer getLevel() {
return level;

}

public void setLevel(Integer level) {
this.level = level;

}

@Override

public String toString() {
return "{name:Dept,value:{code:" + code + ", name:" + name + ", level:"

+ level + "}}";

}

}

7、 运行TestMain()

/**

* author:刘树友

* Email :shuyouliu@126.com

* QQ :261099288

* Date :2014-5-5

*/

package cn.shuyouliu.infinispan;

import java.io.IOException;

import org.apache.log4j.Logger;

import org.infinispan.Cache;

import org.infinispan.manager.DefaultCacheManager;

import cn.shuyouliu.infinispan.bean.Dept;

import cn.shuyouliu.infinispan.bean.People;

/**

* @author liusy

*

*/

public class TestMain {

private final static Logger log = Logger.getLogger(TestMain.class);

/**

* @param args

*/

public static void main(String[] args) {
log.debug("start infinispan study");

test();

testjta();

}

/**

* 测试事务

*/

private static void testjta() {

}

private static void test() {
DefaultCacheManager dcm = loadxml("infinispan-distribution.xml");

Cache<Object, Object> cache = dcm.getCache();

cache.put("keyname","helloWorld!");

log.debug("test read data from cache :"+ cache.get("keyname"));

savedata(cache);

getPeopleById(cache,88);

getPeopleById(cache,99);

getPeopleById(cache,8);

}

private static void getPeopleById(Cache<Object, Object> cache,long id) {
People x = (People)cache.get("people:"+id);

Dept d = (Dept)cache.get("dept:"+x.getDeptid());

log.debug("编码为"+id+"的人是:"+x+" 部门信息:"+d);

}

private static void savedata(Cache<Object, Object> cache) {
for (int i = 0 ; i < 10 ; i ++){
Dept d = new Dept("20"+i, "技术"+i, i);

cache.put("dept:"+d.getCode(), d);

}

for (int i = 0 ; i < 100 ; i ++){
People p = new People((long) i, "10"+i, "张"+i, i% 2 ==1?"男":"女", i+18, "20"+((int)(Math.random()*10)), "步中一在工要"+i);

cache.put("people:"+p.getId(), p);

}

}

private static DefaultCacheManager loadxml(String name) {
log.info("BCache init start . .... ");

DefaultCacheManager dcm = null;

try {
dcm =new DefaultCacheManager(name);

} catch (IOException e) {
log.error("Infinispan init failure - ["+e.getMessage()+"]",e);

e.printStackTrace();

}

return dcm;

}

}

因为是javaProject 会提示 TransactionMananger 类找不到,可以添加一个 jotm-client.jar( 如果是jboss 等web服务器项目就不这个了。)

2014-05-05 11:10:56,375 DEBUG (CacheImpl:start) - Started cache ___defaultcache on PCB0262-843

2014-05-05 11:10:56,375 DEBUG (TestMain:test) - test read data from cache :helloWorld!

2014-05-05 11:10:56,421 DEBUG (TestMain:getPeopleById) - 编码为88的人是:{name:People,value:{id:88, code:1088, name:张88, sex:女, age:106, deptcode:208, readme:步中一在工要88}} 部门信息:{name:Dept,value:{code:208, name:技术8, level:8}}

2014-05-05 11:10:56,421 DEBUG (TestMain:getPeopleById) - 编码为99的人是:{name:People,value:{id:99, code:1099, name:张99, sex:男, age:117, deptcode:209, readme:步中一在工要99}} 部门信息:{name:Dept,value:{code:209, name:技术9, level:9}}

2014-05-05 11:10:56,421 DEBUG (TestMain:getPeopleById) - 编码为8的人是:{name:People,value:{id:8, code:108, name:张8, sex:女, age:26, deptcode:206, readme:步中一在工要8}} 部门信息:{name:Dept,value:{code:206, name:技术6, level:6}}

三、有事务的测试实例

1、 事务相关测试

事务实现不同web服务器有不同的支持。多数通过jndi来获取。

由于infinispan 6.x 对于jndi的搜索默认支持以下几项

{"java:jboss/TransactionManager", "JBoss AS 7"},

{"java:/TransactionManager", "JBoss AS 4 ~ 6, JRun4"},

{"java:comp/TransactionManager", "Resin 3.x"},

{"java:appserver/TransactionManager", "Sun Glassfish"},

{"java:pm/TransactionManager", "Borland, Sun"},

{"javax.transaction.TransactionManager", "BEA WebLogic"},

{"java:comp/UserTransaction", "Resin, Orion, JOnAS (JOTM)"}

所以我们用javaproject做测试,得自己写lookup类。

/**

* author:刘树友

* Email :shuyouliu@126.com

* QQ :261099288

* Date :2014-5-4

*/

package cn.shuyouliu.infinispan.jta;

import javax.naming.Context;

import javax.naming.InitialContext;

import javax.transaction.TransactionManager;

import javax.transaction.UserTransaction;

import org.infinispan.transaction.lookup.TransactionManagerLookup;

/**

* @author liusy

*

*/

public class MyTransactionLookup implements TransactionManagerLookup {
private UserTransaction ut = null;

@Override

public synchronized TransactionManager getTransactionManager() throws Exception {
if (ut == null){
try {
Context ictx = new InitialContext();

ut = (UserTransaction)ictx.lookup("UserTransaction");

System.out.println(ut);

} catch (Exception e) {
e.printStackTrace();

}

}

return (TransactionManager)ut;

}

}

对于tomcat来说或javaProject 一般采取JOTM 或atomikos(官方网站总是访问出错所以就没有测试)来实现JTA事务。

Tomcat 配置简略说下以后有机会再弄个实例

A、 下载JOTM

B、 Jar 复制到 tomcat lib 下

C、 配置content.xml 加入jndi信息。

2、 配置文件信息

isolationLevel缓存隔离级别

Infinispan的只支持READ_COMMITTED或隔离REPEATABLE_READ

默认为READ_COMMITTED

<locking isolationLevel="REPEATABLE_READ" />

<transaction

transactionManagerLookupClass= "cn.shuyouliu.infinispan.jta.MyTransactionLookup"

useEagerLocking="true" autoCommit="true" transactionMode="TRANSACTIONAL"

/>

useEagerLocking 默认为false ,如果为true 将忽略numOwners属性。

autoCommit 默认为true 就是自动开启事务。

transactionMode="TRANSACTIONAL”

配置缓存是否是事务性与否。如果未指定,则默认为

NON_TRANSACTIONAL除非invocationBatching被启用。

3、 事务相关代码

/**

* @param args

*/

public static void main(String[] args) {
log.debug("start infinispan study");

//test();

testjta();

}

//

static class Myrun implements Runnable {
private Cache v;

public Myrun(Cache v){
this.v = v;

}

@Override

public void run() {
long id = Thread.currentThread().getId();

log.debug("Thread :"+id);

TransactionManager tm = v.getAdvancedCache().getTransactionManager();

//for (int i = 0 ; i < 1000 ; i ++){

try {
long l = System.currentTimeMillis();

tm.begin();

v.put("xx", id * 1000 );

log.debug(id +" "+v.get("xx")+" write -->read ");

/*log.debug(id + "put:"+id * 1000 + i);

v.put("xx", id * 1000 + i);

v.put("xx2", id * 1000 + i);

log.debug(id + "putOK:"+id * 1000 + i+ " time:"+ (System.currentTimeMillis() - l ));

Thread.sleep(1000);

v.put("xx3", id * 1000 + i);

//tm.rollback();

*/

tm.commit();

log.debug( "..... time:"+ (System.currentTimeMillis() - l ));

} catch (Exception e) {
e.printStackTrace();

try{
tm.rollback();

}catch (Exception e1) {
e1.printStackTrace();

}

}

//}

}

};

static class Myshow implements Runnable {
private Cache v;

public Myshow(Cache v){
this.v = v;

}

@Override

public void run() {
long id = Thread.currentThread().getId();

log.debug("Thread :"+id);

TransactionManager tm = v.getAdvancedCache().getTransactionManager();

//for (int i = 0 ; i < 10000 ; i ++){

try {
tm.begin();

log.debug(id +"read "+v.get("xx") +" "+ v.get("xx3") + v.get("xx2"));

Thread.sleep(5000);

log.debug(id +"read "+v.get("xx") +" "+ v.get("xx3") + v.get("xx2"));

tm.commit();

log.debug(id +"read "+v.get("xx") +" "+ v.get("xx3") + v.get("xx2"));

} catch (Exception e) {
e.printStackTrace();

}

//}

}

};

/**

* 测试事务

*/

private static void testjta() {


DefaultCacheManager dcm = loadxml("infinispan-distribution-jta.xml");

Cache<Object, Object> cache = dcm.getCache();

cache.put("keyname","helloWorld!");

log.debug("test read data from cache :"+ cache.get("keyname"));

Cache xv = cache;

xv.put("xx","asdf");

Thread x1 = new Thread(new Myrun(xv));

Thread x2 = new Thread(new Myrun(xv));

//Thread x3 = new Thread(new Myrun(xv));

Thread x4 = new Thread(new Myshow(xv));

x4.start();

try {
Thread.sleep(1000);

} catch (Exception e) {
e.printStackTrace();

}

x1.start();

}

//

4、 在TestMain 调用 testjta 开始会提示错误,两个原因一个是在运行时 VM 参数加上-Djava.naming.factory.initial=org.ow2.carol.jndi.spi.MultiOrbInitialContextFactory

第二个是启动JOTM 服务器。

%JOTM_CLASSPATH=

%JOTM_HOME%/conf;%JOTM_HOME%/lib/jotm-standalone.jar;%JOTM_HOME%/lib/commons-cli.jar;%JOTM_HOME%/lib/jotm-client.jar

JOTM_HOME= E:\ow2-jotm-dist-2.2.1

java -cp %JOTM_CLASSPATH% org.objectweb.jotm.Main -uUserTransaction -m TransactionManager -s TransactionSynchronizationRegistry&

E:\ow2-jotm-dist-2.2.1>java -cp %JOTM_CLASSPATH% org.objectweb.jotm.Main -u User

Transaction -m TransactionManager -s TransactionSynchronizationRegistry &

2014-5-5 13:33:20 org.objectweb.jotm.Jotm <init>

信息: CAROL initialization

2014-5-5 13:33:20 org.ow2.carol.util.configuration.TraceCarol infoCarol

信息: Name service for jrmp is started on port 1099

2014-5-5 13:33:20 org.objectweb.jotm.Jotm <init>

信息: JOTM started with a local transaction factory

2014-5-5 13:33:21 org.objectweb.jotm.Jotm <init>

信息: TransactionFactory bound with name TMFactory

UserTransaction object bound in JNDI with name UserTransaction

TransactionManager object bound in JNDI with name TransactionManager

TransactionSynchronizationRegistry object bound in JNDI with name TransactionSyn

chronizationRegistry

JOTM is running...

运行 TestMain 特别要注意的是在运行参数中要添加

-Djava.naming.factory.initial=org.ow2.carol.jndi.spi.MultiOrbInitialContextFactory

DEBUG (CacheImpl:start) - Started cache ___defaultcache on PCB0262-10728

DEBUG (TestMain:testjta) - test read data from cache :helloWorld!

DEBUG (TestMain$Myshow:run) - Thread :40

DEBUG (TestMain$Myshow:run) - 40read asdf nullnull

DEBUG (TestMain$Myrun:run) - Thread :38

DEBUG (TestMain$Myrun:run) - 38 38000 write -->read

5 DEBUG (TestMain$Myrun:run) - ..... time:0

DEBUG (TestMain$Myshow:run) - 40read asdf nullnull

DEBUG (TestMain$Myshow:run) - 40read 38000 nullnull

实例中能够说明,在读事务过程中,信息被修改,不影响读事务重复读取的值。

四、6.x版后支持DSL 查询。正在实验中

五、分布式模式

相关文章