Hazelcast.xml 配置文件说明
配置 Hazelcast的使用可以通过XML配置和编程来实现,或者是两者共同配合使用来完成其功能; 1-配置声明 如果你创建Hazelcast实例的时候,不传递参数给Hazelcast的话 (即:newHazelcastInstance(null))或者使用空的工厂方法(Hazelcast.newHazelcastInstance) 来创建,Hazelcast将会自己自动的检查两个地方来寻找Hazelcast的配置文件: § 系统属性:Hazelcast 首先会检查是否”hazelcast.config”系统属性被设置到某个配置文件下。例如: -Dhazelcast.config=C:/myhazelcast.xml § Classpath:如果配置文件配置成系统属性,Hazelcast将会继续检查classpath 来寻找hazelcast.xml文件。 如果Hazelcast 没有找到任何配置文件,它将很乐意的使用默认的配置文件(hazelcast-default.xml),它在hazelcast.jar包下。(在配置 Hazelcast之前,建议您使用默认的配置文件来看看是否Hazelcast能正常的工作。默认的配置文件对于大部分的开发者来说已经是很好的了。如 果您不想这样,那么就考虑为您的环境亲自配置一份吧)。 如果您想指定自己的配置文件来创建配置的话,Hazelcast提供了几种方式来供您选择,包括-filesystem,classpath,InputStream,URL等等: § Config cfg = new XmlConfigBuilder(xmlFileName).build(); § Config cfg = new XmlConfigBuilder(inputStream).build(); § Config cfg = new ClasspathXmlConfig(xmlFileName); § Config cfg = new FileSystemXmlConfig(configFilename); § Config cfg = new UrlXmlConfig(url); § Config cfg = new InMemoryXmlConfig(xml); 2- 可编程配置 根据您的需求,初始化Config对象设置/修改属性,完成编程式的配置Hazelcast。 Config config =new Config(); config.getNetworkConfig().setPort(5900 ); config.getNetworkConfig().setPortAutoIncrement(false ); NetworkConfig network = config.getNetworkConfig(); JoinConfig join = network.getJoin(); join.getMulticastConfig().setEnabled( false ); join.getTcpIpConfig().addMember( "10.45.67.32").addMember( "10.45.67.100" ) .setRequiredMember("192.168.10.100" ).setEnabled( true ); network.getInterfaces().setEnabled( true ).addInterface("10.45.67.*" ); MapConfig mapConfig = new MapConfig(); mapConfig.setName( "testMap" ); mapConfig.setBackupCount( 2 ); mapConfig.getMaxSizeConfig().setSize( 10000 ); mapConfig.setTimeToLiveSeconds( 300 ); MapStoreConfig mapStoreConfig = new MapStoreConfig(); mapStoreConfig.setClassName("com.hazelcast.examples.DummyStore" ) .setEnabled(true ); mapConfig.setMapStoreConfig( mapStoreConfig ); NearCacheConfig nearCacheConfig = new NearCacheConfig(); nearCacheConfig.setMaxSize( 1000 ).setMaxIdleSeconds( 120) .setTimeToLiveSeconds( 300 ); mapConfig.setNearCacheConfig( nearCacheConfig ); config.addMapConfig( mapConfig ); 然后创建Config对象,你就可以用这个对象来创建Hazelcast实例。
Config config = new Config(); config.setInstanceName( "my-instance" ); Hazelcast.newHazelcastInstance( config ); ·用它的名字来取得一个已经存在的HazelcastInstance; Hazelcast.getHazelcastInstanceByName("my-instance" ); ·用它的名字来取得所有已经存在的HazelcastInstance; Hazelcast.getAllHazelcastInstances(); 使用通配符 Hazelcast支持为所有分布式数据结构的通配符配置,它可以使用Config来配置(但除了 IatomicLong,IatomicReference)。在不同的map,queues,topics,semaphores实例等名字中使用星号(*)简单的配置。 注意,这种简单的用法,星号(*)可以放在配置中的任何位置。 比如:一个名叫‘com.hazelcast.test.mymap’的map可以使用以下的几种配置方式: <map name="com.hazelcast.test.*"> ... </map> <map name="com.hazel*"> ... </map> <map name="*.test.mymap"> ... </map> <map name="com.*test.mymap"> ... </map> 或者 一个queue ‘com.hazelcast.test.myqueue’; <queue name="*hazelcast.test.myqueue"> ... </queue> <queue name="com.hazelcast.*.myqueue"> ... </queue> 网络配置 配置TCP/IP集群 如果你的环境中多播不是首选的话,那么你可以配置Hazelcast完整集群。像下面的配置显示那样,当多播属性被设置成false时,tcp-ip就不得不设置为true。 对于一个没有多播选择的环境,所有或者主机和IP节点必须列出。注意,所有的集群节点必须列出来,但是至少有一个是活动的当有一个新的节点进来时。 <hazelcast> ... <network> <portauto-increment="true">5701</port> <join> <multicastenabled="false"> <multicast-group>224.2.2.3</multicast-group> <multicast-port>54327</multicast-port> </multicast> <tcp-ipenabled="true"> <member>machine1</member> <member>machine2</member> <member>machine3:5799</member> <member>192.168.1.0-7</member> <member>192.168.1.21</member> </tcp-ip> </join> ... </network> ... </hazelcast> 鉴于它需要被看到,IP地址和主机名可以作为节点的标签。你还可以给出一个IP范围,例如:192.168.1.0-7. 为了不一行一行的配置,你可以使用逗号作为标签,写在IP之间,如下所示: <members>192.168.1.0-7,192.168.1.21</members> 如果节点的端口不支持,Hazelcast可以自动的尝试5701,5702等端口。 Hazelcast默认情况下,会自动的绑定本网络接口的所有通信数据流。当然,这也可以通过系统属性来改变。 Hazelcast.socket.bind.any。当 这个属性值被设置为false时,Hazelcast使用接口之间的特定接口(请参考 Specifying Network Interfaces 章节)。如果没有接口提供,那它会试着解析任何一个绑定的端口,在这个节点标签上让步。 Tcp-ip标签接收一个叫connection-timeout-seconds的属性,它的默认值是 5。推荐您增加这个值,如果你有许多IP列表的话,并且当节点不能很好的创建集群的话。 还有一个标签,required-member,用来识别特定的节点,需要设置在一个集群前面。 <hazelcast> ... <network> <join> <tcp-ipenabled="true"> <required-member>192.168.1.21</required-member> <member>machine2</member> <member>machine3:5799</member> <member>192.168.1.0-7</member> </tcp-ip> </join> ... </network> ... </hazelcast> 在这个例子中,这个集群不会生效,除非节点的IP 192.168.1.21 是有效的。 指定网络接口 你可以指定Hazelcast使用哪个你指派的接口。服务 器大部分都有超过一个的网络接口,所以你需要列出有效的所有IP。可以简易的使用 ‘*’ 和 ‘-’。例如 10.3.10.*,可以替代10.3.10.0-10.3.10.255 .接口是 10.3.10.4-18(4,18也包括)。如果网络接口是配置为允许的(默认不允许),并且Hazelcast不能找到匹配的接口,那么它将会在控制 台打印出一条信息,在那个节点上不能启动。 <hazelcast> ... <network> ... <interfacesenabled="true"> <interface>10.3.16.*</interface> <interface>10.3.10.4-18</interface> <interface>192.168.1.3</interface> </interfaces> </network> ... </hazelcast> EC2(弹性计算云) 自动发现 Hazelcast 支持EC2自动发现机制,这当你不想或是不能提供可能的IP地址时,会是很有用的东西。可以你的集群配置成能够使用EC2自发发现功能,禁用加入多播和TCP / IP和启用AWS。还可以给你提供认信息(权限和秘钥)。 这需要你将hazelcast-cloud.jar添加到你的项目依赖中。注意,这个jar包被绑定到了hazelcast-all.jar包中。Hazelcast 不依赖其他任何第三方插件。 下面是一个配置样本: <join> <multicast enabled="false"> <multicast-group>224.2.2.3</multicast-group> <multicast-port>54327</multicast-port> </multicast> <tcp-ip enabled="false"> <interface>192.168.1.2</interface> </tcp-ip> <aws enabled="true"> <access-key>my-access-key</access-key> <secret-key>my-secret-key</secret-key> <!-- optional,default is us-east-1--> <region>us-west-1</region> <!—默认是ec2.amazonaws.com,如果你要设置的话,请不要覆盖此属性--> <host-header>ec2.amazonaws.com</host-header> <!-- optional --> <security-group-name>hazelcast-sg</security-group-name> <!-- optional --> <tag-key>type</tag-key> <!-- optional --> <tag-value>hz-nodes</tag-value> </aws> </join> 标签aws 的属性值是一个叫做 connection-timeout-seconds 的属性,默认是5(s)。如果你有许多IP和并且节点不能很好适应集群的话,是可以增加这个值的。 Region参数指定了哪个节点的机器是运行的。默认值是 us-east-1。如果集群在不同的地方运行,必须指定地点。否则,集群将会不稳定,因为他们不能互相发现对方。 Tag-key 和 tag-value 参数提供不同的key和value值,让你可以在同一个数据中心创建多个集群。 Securit-group-name 参数还可以用来过滤/组合节点。 注意:如果你采用了云的方式,而不是AWS,你可以使用程序化的集群配置指定一个TCP / IP。节点需要从提供方那重新获取。 AWSClient: 确保EC2已经正确创建了,这时候AWSClient就可 以使用了。它为EC2连接提供私有的IP地址。只要给它提供参数值,并在aws标签中指定即可。如下所示,你public static void main( String[] args )throws Exception{ AwsConfig config = new AwsConfig(); config.setSecretKey( ... ) ; config.setSecretKey( ... ); config.setRegion( ... ); config.setSecurityGroupName( ... ); config.setTagKey( ... ); config.setTagValue( ... ); config.setEnabled("true"); AWSClient client = new AWSClient( config ); List<String> ipAddresses = client.getPrivateIpAddresses(); System.out.println( "addressesfound:" + ipAddresses ); for ( String ip: ipAddresses ) { System.out.println( ip ); } }可以知道你的EC2是否已经建立。 调试: 在需要的时候,Hazelcast会记录下在一个域的事件日志,改变日志等级为FINEST或DEBUG查看当集群的时候,活动节点发生了什么。之后,你还可以查看是否实例被接收了或是被拒绝,导致的原因在日志文件中。注意,改变日志等级,也许会影响集群的效果。 相关信息 你可以从Hazelcast.com上 下载Hazelcast on AWS: Best Practices for Deployment 白皮书。 端口 你可以为集群中的节点之间指定通信端口。端口默认是 5701. <network> <port>5701</port> </network> 默认情况下,Hazelcast将会试着绑定100个端口,也就是说,如果你将端口设置为了5701,当有新节点进来的时候,Hazelcast会自动查找在5701-5801之间的节点。 如果在你的集群中节点过多,或是过少的话,你可以改变这种端口数参数 port-count,默认就是100. <network> <portport-count="20">5781</port> </network> 根据上面的配置,Hazelcast会寻找从5781到5801的空闲端口。正常情况下,你不要去改变这个值,当需要的时候,也很方便设置。也许还有一种情况,你只需要使用一个端口,那么你可以取消自动增加查找使用auto-increment功能。如下所示: <network> <portauto-increment="false">5701</port> </network> 当然,这种情况下,port-count参数会被忽略掉。 外部端口 默认情况下,Hazelcast允许系统在Socket操作时,打开一个临时端口。但是安全策略和防火墙也许会严格控制外部端口的访问。为了解决这个问题,你可以配置Hazelcast来配置自定义的外部端口。 <hazelcast> ... <network> <portauto-increment="true">5701</port> <outbound-ports> <!-- ports between 33000 and 35000--> <ports>33000-35000</ports> <!-- comma separated ports --> <ports>37000,37001,37002,37003</ports> <ports>38000,38500-38600</ports> </outbound-ports> ... </network> ... </hazelcast> 或者以编程的方式: ... NetworkConfig networkConfig = config.getNetworkConfig(); // ports between 35000 and 35100 networkConfig.addOutboundPortDefinition("35000-35100"); // comma separated ports networkConfig.addOutboundPortDefinition("36001,36002,36003"); networkConfig.addOutboundPort(37000); networkConfig.addOutboundPort(37001); ... 注意:你可以定义一个端口范围或是用逗号来隔开各个端口。 IPv6 支持 Hazelcast很好的支持Ipv6(默认是被关闭的)。详细请看本章节最后部分。 你所要做的就是定义IPv6地址或网络配置中的接口配置。此刻仅有的限制是,你不能在tcp - ip连接配置中定义IPv6地址通配符。接口的话,没有这个限制,你可以像在IPv4中那样定义通配符。 <hazelcast> ... <network> <portauto-increment="true">5701</port> <join> <multicastenabled="false"> <multicast-group>FF02:0:0:0:0:0:0:1</multicast-group> <multicast-port>54327</multicast-port> </multicast> <tcp-ipenabled="true"> <member>[fe80::223:6cff:fe93:7c7e]:5701</member> <interface>192.168.1.0-7</interface> <interface>192.168.1.*</interface> <interface>fe80:0:0:0:45c5:47ee:fe15:493a</interface> </tcp-ip> </join> <interfacesenabled="true"> <interface>10.3.16.*</interface> <interface>10.3.10.4-18</interface> <interface>fe80:0:0:0:45c5:47ee:fe15:*</interface> <interface>fe80::223:6cff:fe93:0-5555</interface> </interfaces> ... </network> ... </hazelcast> JVM就像inet4和inet6一样,有两个系统属性来配置IPv4 和 IPv6。在一个双协议栈中,IPv6是默认首选的。这也可以通过Java.NET.preferIPv4Stack=& lt;true|false>系统属性配置。当查询服务名的时候,JVM首选IPv4地址而不是IPv6,并且返回IPv4地址也是有可能的。这个 可以通过java.net.preferIPv6Addresses=<true|false>来改变。 请看补充细节:details on IPv6 support in Java 注意:IPv6支持默认是关闭的。因为一些平台在使用IPv6的时候出现了一些问题。其他平台像AWS根本就不支持的。想要IPv6支持生效,只要配置hazelcast.prefer.ipv4.stack 的属性为false 即可。请看详细说明:Advanced Configuration Properties. 分区分组 Hazelcast 使用一致性哈希散列算法将关键的主机分到分区中。这些分区都指派了节点。默认所有分区值是 271,通过hazelcast.map.partition.count值进行改变。详细参考Advanced Configuration Properties. 在这些分区之间,需要拷贝作为备份所有。在配置中配置 back count值,就可以设置多个备份了。比如,第一备份区,第二备份区...通常来说,一个节点不能拥有超过一份的备份(所有者 或 备份)。默认Hazelcast是随机分区和备份的,并且集群节点之间的备份是公平的,就像所有的节点都一样似得。 现在,如果某些节点共享相同的JVM或物理机器,如果你想要备份这些节点分配给其他节点,那该怎么办?如果某些节点的处理和记忆能力是不同的,并且你不希望分配相同数量的分区分配给所有节点,又该怎么办? 你可以将同在一个JVM中或在同一个架构中的节点机器组合为一组。或者,你可以组合这些节点来达到同样的功能。我们称这叫做分组。这中分组方式代替了单节点分组。备份的内容,放在其他的分组中。 当你授权分组的时候,Hazelcast给你提供了三种选择配置分组信息。
<partition-group enabled="true"group-type="HOST_AWARE" /> Config config = ...; PartitionGroupConfig partitionGroupConfig =config.getPartitionGroupConfig(); partitionGroupConfig.setEnabled( true ) .setGroupType(MemberGroupType.HOST_AWARE ); ? 第二个是通过Hazelcast接口匹配配置自定义分组。这种方式下,你可以增加多个不同的接口到你的分组中。还可以在地址接口中使用通配符。比如,用户可以通过自定义分组创建机架感知或者数据仓库在分组中。 <partition-groupenabled="true" group-type="CUSTOM"> <member-group> <interface>10.10.0.*</interface> <interface>10.10.3.*</interface> <interface>10.10.5.*</interface> </member-group> <member-group> <interface>10.10.10.10-100</interface> <interface>10.10.1.*</interface> <interface>10.10.2.*</interface> </member-group </partition-group> Config config = ...; PartitionGroupConfigpartitionGroupConfig = config.getPartitionGroupConfig(); partitionGroupConfig.setEnabled(true ) .setGroupType( MemberGroupType.CUSTOM ); MemberGroupConfigmemberGroupConfig = new MemberGroupConfig(); memberGroupConfig.addInterface("10.10.0.*" ) .addInterface("10.10.3.*" ).addInterface("10.10.5.*" ); MemberGroupConfigmemberGroupConfig2 = new MemberGroupConfig(); memberGroupConfig2.addInterface("10.10.10.10-100" ) .addInterface("10.10.1.*").addInterface( "10.10.2.*" ); partitionGroupConfig.addMemberGroupConfig(memberGroupConfig ); partitionGroupConfig.addMemberGroupConfig(memberGroupConfig2 ); ? 第三个是给每个成员它自己的分组。这意味着,每个成员是一群自己的随机分布和备份分区。这是Hazelcast集群的默认配置并且给出了最少保护数。 <partition-groupenabled="true" group-type="PER_MEMBER" /> Config config = ...; PartitionGroupConfig partitionGroupConfig= config.getPartitionGroupConfig(); partitionGroupConfig.setEnabled(true ) .setGroupType(MemberGroupType.PER_MEMBER ); 监听器配置 事件监听器可以使用HazelcastAPI从相关的对象中增加或是移除。 通过API方式来配置监听器的趋势有所下降,可能是由于创建对象和注册监听的时候丢失事件的原因。为了克服这个问题,Hazelcast提供了在配置文件中注册监听器的方式。监听器的注册可以通过声明式和编程式或是spring的配置文件方式来配置
o 声明式配置 o <listeners> o <listener>com.hazelcast.examples.MembershipListener</listener> o </listeners> o 编程式配置 o config.addListenerConfig( o new ListenerConfig("com.hazelcast.examples.MembershipListener" ) ); o Spring XMLconfiguration o <hz:listeners> o <hz:listenerclass-name="com.hazelcast.spring.DummyMembershipListener"/> o <hz:listener implementation="dummyMembershipListener"/> o </hz:listeners> ? 分布式监听器 o 声明式配置 o <listeners> o <listener>com.hazelcast.examples.DistributedObjectListener</listener> o </listeners> o 编程式配置 o config.addListenerConfig( o new ListenerConfig("com.hazelcast.examples.DistributedObjectListener" ) ); o Spring XML配置 o <hz:listeners> o <hz:listenerclass-name="com.hazelcast.spring.DummyDistributedObjectListener"/> o <hz:listenerimplementation="dummyDistributedObjectListener"/> o </hz:listeners> ? 移动式监听器 o 声明配置 o <listeners> o <listener>com.hazelcast.examples.MigrationListener</listener> o </listeners> o 编程式配置 o config.addListenerConfig( o new ListenerConfig("com.hazelcast.examples.MigrationListener" ) ); o Spring XML配置 o <hz:listeners> o <hz:listenerclass-name="com.hazelcast.spring.DummyMigrationListener"/> o <hz:listenerimplementation="dummyMigrationListener"/> o </hz:listeners> ? 周期性监听器 o 声明配置 o <listeners> o <listener>com.hazelcast.examples.LifecycleListener</listener> o </listeners> o 编程式配置 o config.addListenerConfig( o new ListenerConfig( "com.hazelcast.examples.LifecycleListener") ); o Spring XML配置 o <hz:listeners> o <hz:listenerclass-name="com.hazelcast.spring.DummyLifecycleListener"/> o <hz:listenerimplementation="dummyLifecycleListener"/> o </hz:listeners> ? Map 条目监听器 o 声明式配置 o <map name="default"> o ... o <entry-listeners> o <entry-listener include-value="true"local="false"> o com.hazelcast.examples.EntryListener o </entry-listener> o </entry-listeners> o </map> o 编程式配置 o mapConfig.addEntryListenerConfig( o newEntryListenerConfig( "com.hazelcast.examples.EntryListener", o false,false ) ); o Spring XML配置 o <hz:map name="default"> o <hz:entry-listeners> o <hz:entry-listener include-value="true" o class-name="com.hazelcast.spring.DummyEntryListener"/> o <hz:entry-listener implementation="dummyEntryListener"local="true"/> o </hz:entry-listeners> o </hz:map> ? 多种映射的条目监听器 o 声明式配置 o <multimapname="default"> o <value-collection-type>SET</value-collection-type> o <entry-listeners> o <entry-listenerinclude-value="true" local="false"> o com.hazelcast.examples.EntryListener o </entry-listener> o </entry-listeners> o </multimap> o 编程式配置 o multiMapConfig.addEntryListenerConfig( o new EntryListenerConfig("com.hazelcast.examples.EntryListener",false ) ); o Spring XML配置 o <hz:multimapname="default" value-collection-type="LIST"> o <hz:entry-listeners> o <hz:entry-listener include-value="true" o class-name="com.hazelcast.spring.DummyEntryListener"/> o <hz:entry-listener implementation="dummyEntryListener"local="true"/> o </hz:entry-listeners> o </hz:multimap> ? Queue条目监听器 o 声明式配置 o <queuename="default"> o ... o <item-listeners> o <item-listenerinclude-value="true"> o com.hazelcast.examples.ItemListener o </item-listener> o </item-listeners> o </queue> o 编程式配置 o queueConfig.addItemListenerConfig( o new ItemListenerConfig("com.hazelcast.examples.ItemListener",true ) ); o Spring XML配置 o <hz:queuename="default" > o <hz:item-listeners> o <hz:item-listenerinclude-value="true" o class-name="com.hazelcast.spring.DummyItemListener"/> o </hz:item-listeners> o </hz:queue> ? 主题信息监听器 o 声明式配置 o <topic name="default"> o <message-listeners> o <message-listener> o com.hazelcast.examples.MessageListener o </message-listener> o </message-listeners> o </topic> o 编程式配置 o topicConfig.addMessageListenerConfig( o newListenerConfig( "com.hazelcast.examples.MessageListener" ) ); o Spring XML配置 o <hz:topic name="default"> o <hz:message-listeners> o <hz:message-listener o class-name="com.hazelcast.spring.DummyMessageListener"/> o </hz:message-listeners> o </hz:topic> ? 客户端监听器 o 声明式配置 o <listeners> o <listener>com.hazelcast.examples.ClientListener</listener> o </listeners> o 编程式配置 o topicConfig.addMessageListenerConfig( o new ListenerConfig("com.hazelcast.examples.ClientListener" ) ); o Spring XML配置 o <hz:listeners> o <hz:listenerclass-name="com.hazelcast.spring.DummyClientListener"/> o <hz:listenerimplementation="dummyClientListener"/> o </hz:listeners> 日志配置 Hazelcast提供了灵活的日志配置,并且不依赖任何日志框架,仅仅依靠JDK的日志功能。它有内置的适配器来完成日志框架功能,并且提供日志接口来自定义日志功能。 想使用内置的适配器,你需要配置hazelcast.logging.type属性来使用下列预置的类型。 ? jdk: JDK logging (default) ? log4j: Log4j ? slf4j: Slf4j ? none: disable logging 你可以通过声明式,编程式或JVM系统属性来配置hazelcast.logging.type. 注意: 如果你选择log4j或是slf4j的话,一些依赖也要加载进来(classpath下)。 ? 声明式配置 <hazelcastxsi:schemaLocation="http://www.hazelcast.com/schema/config http://www.hazelcast.com/schema/config/hazelcast-config-3.0.xsd" xmlns="http://www.hazelcast.com/schema/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> .... <properties> <propertyname="hazelcast.logging.type">jdk</property> .... </properties> </hazelcast> ? 编程式配置 Configconfig = new Config() ; config.setProperty("hazelcast.logging.type","log4j" ); ? 系统属性 o 使用JVM参数:java -Dhazelcast.logging.type=slf4j o 使用系统类: System.setProperty("hazelcast.logging.type","none" ); 如果你提供了一个不是静态工厂的日志机制,你可以使用自定义日志来实现它。要使用这 个,你需要实现com.hazelcast.logging.LoggerFactory 和com.hazelcast.logging.ILogger 接口。并且设置系统属性hazelcast.logging.class作为你自定义的日志工厂类名。 -Dhazelcast.logging.class=foo.bar.MyLoggingFactory 你还可以通过注册日志监听器(LogListeners)到日志服务(LoggingService)在Hazelcast运行时来监听日志事件的过程。 LogListenerlistener = new LogListener() { public void log( LogEvent logEvent ) { // do something } } HazelcastInstanceinstance = Hazelcast.newHazelcastInstance(); LoggingServiceloggingService = instance.getLoggingService(); loggingService.addLogListener(Level.INFO,listener ); 通过这个日志服务(LoggingService),你可以得到目前使用的日志接口,也可以记录你自己的信息。 注意 :如果你不是使用的命令行来配置你的日志,你应该注意Hazelcast类,因为默认情况下有可能在最新配置的日志机制之前使用jdk日志。当日志机制被选定的话,这就不会变了。 高级属性配置 Hazelcasth还提供了一些高级的属性配置。这些属性可以通过声明式和编程式或JVM系统属性方式来设置key-value键值对进行配置。 声明配置 <hazelcastxsi:schemaLocation="http://www.hazelcast.com/schema/config http://www.hazelcast.com/schema/config/hazelcast-config-3.0.xsd" xmlns="http://www.hazelcast.com/schema/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> .... <properties> <propertyname="hazelcast.property.foo">value</property> .... </properties> </hazelcast> 声明式配置 Config config = new Config() ; config.setProperty( "hazelcast.property.foo","value" ); 系统属性
下面的两张表列出了高级属性的配置以及说明。
网络分区 想象你有10台机器的集群,由于某些原因,网络被分为两份,共4台机器,其他6台机器看不见了。结果,你只有两个集群。4台机器的和6台机器的集群。这种情况下,每个集群的机器都在想,其他的节点都死了甚至是不存在的。这种情况就叫做网络分区(a.k.a. Split-Brain Syndrome)。 然而,就像包括主机和备份机在内的一样,并不是所有的271个分区都在小集群中。因此,从每个小集群的角度来看,就像分区不存在一样,数据已经丢失了(它们在其他的分区里)。
如果使用Map存储的话,这些丢失的数据会从数据库重新加载,使得每个小集群保持完整。每个小集群的机器会重新创建丢失的主要分区,然后存储起来。也包括在其他节点的备份数据。
当主分区存在并且没有备份的话,一个关于备份版本的问题就 会出现了,紧接着备份分区就会被创建。当备份分区存在而主分区不存在的话,这个备份分区就会升级为主分区,然后重新创建个合适的版本的备份分区。这时候, 两个集群都已经修复好了,并且有271个分区和备份分区。然后在彼此没有知晓的情况下继续处理事务。想象它们都有足够的剩余内存,生产力较低。
如果使用Map存储,并且网络访问数据库可用的话,而现在 集群中的一个在进行写/更新操作,这就产生了一个潜在的问题-如果在两个集群都做修改的话,这就重写了同一个缓存记录。这种重写情况会导致潜在的数据丢 失。因此,数据库的设计应该在读的时候考虑到插入和结合问题,或者是版本问题,而不是更新数据。 如果网络访问数据库不可用,那么基于配置的和编码的事务、缓存中的条目更新都会被拒绝(保持一致性和同步性)。在缓存中的数据,更新操作的数据将会被认为是脏数据,当更新可用的时候,重写到数据库。集群成员可以在管理中心的web控制台看到脏条目数据(请参考 Map Monitoring)。 当网络不可用的时候,就没有办法避免以编程式的方式情况下 你的集群会以两个独立的集群运行。但是,我们应该可以回答下面的问题:”当网络修复好并且连接恢复了,程序又会怎样呢?这两个集群会再一次融合为一个吗? 如果是这样,那数据又是怎样解决的呢?你将Map中相同的key的值删除?” 当网络恢复了,你应该保证所有271个分区在每个集群中都是活着的,并且进行合并。一旦所有的主分区合并了,所有的备份分区将会重新写入,这时候它们的版本也就对了。也许你想通过MapMergePolicy接口写个合并策略,从数据库中将条目重建,而不是从缓存中。 从EntryView接口的观点来看,只有元数据(包括对象大小,点击次数,最后一次更新/存储数据,从0开始的随条目更新而增加的版本号)才可以起到合并的功能。你还可以创建你自己的版本控制计划,或者捕捉重建条目的时间序列。 下面例子,通过一步一步的告诉你,Hazelcast是怎么实现合并的: 1. 集群中时间最长的机器检查在网络中是否有另台带有相同组名或组密码的机器。 2. 如果发现了这样的机器,那这个探测主机将会判断它和哪个集群进行合并。 3. 进行合并的集群中每台机器将会做下面的事情: o 暂停 o 取出本地所有map条目 o 关闭所有网络连接 o 加入新的集群 o 给本地所有map条目发送合并信息请求 o 重新启动 因此合并集群中的每个机器,事实上重新加入了新的集群,然后发送合并信息请求给每个map条目。 两点重要提示:
· 每个集群在同一个map中具有相同的key值的也许也会有不同的版本。目的集群会基于合并策略(MergePolicy)为那个map决定怎么合并条目。 因为有内置的合并策略就像 PassThroughMergePolicy,PutIfAbsentMapMergePolicy,HigherHitsMapMergePolicy 和 LatestUpdateMapMergePolicy.但是,你也可以设计你自己的合并策略通过实现 com.hazelcast.map.merge.MapMergePolicy.你应该设定你的实现的完整类名到merge-policy配置。 public interface MergePolicy { /** *合并条目之后返回具有相同key值的条目的value值 *你应该考虑到条目是null的情况 * @param mapName name of the map * @param mergingEntry 条目合并到目的集群 * @param existingEntry 在集群中存在的集群 * @return final value of the entry. 如果返回null,条目会被删除 */ Object merge( String mapName,EntryViewmergingEntry,EntryView existingEntry ); } 在这里告诉你 合并策略是怎么被每个map识别的 <hazelcast> ... <map name="default"> <backup-count>1</backup-count> <eviction-policy>NONE</eviction-policy> <max-size>0</max-size> <eviction-percentage>25</eviction-percentage> <!-- 当从网络分区恢复过来的时候, 基于在这里配置的策略,小集群的map条目将会合并到大集群中。当一个条目合并到集群中时,也许会出现相同key值的条目。 具有相同的key值的条目也许value值不同. 出现冲突了,默认策略是hz.ADD_NEW_ENTRY 有内置的策略 如: com.hazelcast.map.merge.PassThroughMergePolicy; entry will be added if 这个key没有已存在的条目. com.hazelcast.map.merge.PutIfAbsentMapMergePolicy ; entry will be 如果在集群中没有这个条目,就增加这个条目. com.hazelcast.map.merge.HigherHitsMapMergePolicy ; 点击最多的条目有效. com.hazelcast.map.merge.LatestUpdateMapMergePolicy ; entry with the 最近更新的有效. --> <merge-policy>MY_MERGE_POLICY_CLASS</merge-policy> </map> ... </hazelcast> 原文地址:http://hazelcast.com (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |