Hibernate Distirbuted cache
Hazelcast, Infinispan, etc.
Key Terms
Perfomance - number of operations per unit of time (requests/second)
Perfomance is not Scalability
Scalability can be Vertical and Horizontal
Happy App
more happy App?
Solution?
Cache concept
An area of local memory that holds a copy of
frequently accessed data that is otherwise
expensive to get or compute
Cache types:
-
Application cache
-
Second level (L2) cache
-
Hybrid cache
Application cache
l2 cache
Hybrid cache
key cache terms
- Cache size - defines how many elements a cache can hold;
- Cache eviction - algorithm defines what to do when the number of elements in cache exceeds the size (LRU, LFU, FIFO) & eviction percentage;
- Time-to-live - defines time after that a cache key should be remove from the cache (expired);
REPLICATED CACHE VS distributed cache
Peer-to-peer cluster
Clients and server cluster
Hybrid cluster
frameworks overview
*IMDG - In-Memory Data Grid
Scalable data grid platform
-
open-source - LGPL
-
based on some JBoss Cache code
JBoss Cache
-
clustered caching library
Infinispan has a Map-like API(JSR-107 JCACHE)
-
can be used as Key-Value No-SQL solution
-
has Hibernate4 cache region&provider implementation
POm.xml
<!--Infinispan-->
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-core</artifactId>
<version>6.0.2.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-infinispan</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.jboss.jbossts</groupId>
<artifactId>jbossjta</artifactId>
<version>4.16.4.Final</version>
</dependency>
Infinispan.xml
<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 nodeName="caching" clusterName="caching_cluster" transportClass="org.infinispan.remoting.transport.jgroups.JGroupsTransport">
<properties> <property name="configurationFile" value="tcp.xml"/>
</properties>
</transport>
</global>
<default>
<clustering mode="dist"><async/>
</clustering>
<eviction maxEntries="1000" strategy="LRU"/>
</default>
<namedCache name="productBrand.region">
<clustering mode="dist"/>
<eviction strategy="LRU" maxEntries="5000" threadPolicy="DEFAULT"/>
<expiration maxIdle="10"/>
</namedCache>
</infinispan>
datasourceContext-infinispan.xml
cached entity
@Entity
@Table(name = "PRODUCT_CATEGORY")
@Cache(region = "productCategory.region", usage = CacheConcurrencyStrategy.TRANSACTIONAL)
public class ProductCategory {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "CATEGORY_ID")
private Long id;
@Column(name = "NAME")
private String name;
@Cache(region = "productCategory.brands.region", usage = CacheConcurrencyStrategy.TRANSACTIONAL)
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinTable(name = "BRAND_CATEGORY", joinColumns = @JoinColumn(name = "CATEGORY_ID"), inverseJoinColumns = @JoinColumn(name = "BRAND_ID"))
private List<ProductBrand> brands;
...
}
application cache
Cache<Object, Object> cache = new DefaultCacheManager().getCache();
// Add a entry cache.put("key", "value"); // Remove the entry from the cache Object v = cache.remove("key"); // And replace it if missing cache.putIfAbsent("key", "newValue"); cache.clear(); //By default entries are immortal but we can override this on a per-key basis and provide lifespans. cache.put("key", "value", 5, SECONDS);
Apache license
1 solid Jar file ~3MB + HibernateProvider
Transactional & Secure
IMDG
3-way configuration: XML, Java, Spring
pom.xml
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast-hibernate4</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast-spring</artifactId>
<version>3.2.1</version>
</dependency>
Hazelcast.xml
<hazelcast>
<group name="dev" password="dev"/>
<network>
<port auto-increment="true">5701</port>
<outbound-ports><ports>0</ports></outbound-ports>
<join>
<multicast enabled="false">
<multicast-group>231.12.21.135</multicast-group>
<multicast-port>45564</multicast-port>
<multicast-timeout-seconds>2</multicast-timeout-seconds>
</multicast>
<tcp-ip enabled="true"><interface>127.0.0.1</interface></tcp-ip>
</join>
<interfaces enabled="true"><interface>127.0.0.*</interface></interfaces>
<ssl enabled="false"/>
<socket-interceptor enabled="false"/>
<symmetric-encryption enabled="false"/>
</network>
<partition-group enabled="false"/>
<executor-service name="default">
<pool-size>16</pool-size>
<queue-capacity>0</queue-capacity>
</executor-service>
HAZELCAST.XML
<map name="default"/>
<map name="productCategory.brands.region">
<in-memory-format>OBJECT</in-memory-format>
<backup-count>2</backup-count>
<async-backup-count>0</async-backup-count>
<time-to-live-seconds>90</time-to-live-seconds>
<max-idle-seconds>0</max-idle-seconds>
<eviction-policy>LRU</eviction-policy>
<max-size policy="PER_NODE">5000</max-size>
<eviction-percentage>30</eviction-percentage>
<merge-policy>com.hazelcast.map.merge.PassThroughMergePolicy</merge-policy>
<read-backup-data>true</read-backup-data>
</map>
</hazelcast>
DATASOURCECONTEXT-hazelcast.XML
<!-- SessionFactory bean with Hazelcast Hibernate properties -->
<prop key="hibernate.cache.region.factory_class">com.hazelcast.hibernate.HazelcastCacheRegionFactory</prop>
<prop key="hibernate.cache.hazelcast.configuration_file_path">hazelcast.xml</prop>
<prop key="hibernate.cache.hazelcast.use_lite_member">true</prop>
<prop key="hibernate.cache.hazelcast.shutdown_on_session_factory_close">false</prop>
Cached Entity
@Entity
@Table(name = "PRODUCT_CATEGORY")
@Cache(region = "productCategory.region", usage = CacheConcurrencyStrategy.READ_WRITE)
public class ProductCategory {
...
@Cache(region = "productCategory.brands.region", usage = CacheConcurrencyStrategy.READ_WRITE)
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinTable(name = "BRAND_CATEGORY", joinColumns = @JoinColumn(name = "CATEGORY_ID"), inverseJoinColumns = @JoinColumn(name = "BRAND_ID"))
private List<ProductBrand> brands;
...
}
Application cache
Config cfg = new Config();
HazelcastInstance instance = Hazelcast.newHazelcastInstance(cfg);
Map<Integer, String> mapCustomers = instance.getMap("customers");
mapCustomers.put(1, "Joe");
mapCustomers.put(2, "Ali");
mapCustomers.put(3, "Avi");
conclusion
Hazelcast wins!
REferences
-
http://docs.oracle.com/cd/E18686_01/coh.37/e18677/cache_intro.htm
-
http://coherence.oracle.com/display/COH31UG/Read-Through,+Write- Through,+Refresh-Ahead+and+Write-Behind+Caching
-
http://blog.tekmindsolutions.com/oracle-coherence-diffrence-between- replicated-cache-vs-partitioneddistributed-cache/
-
http://www.slideshare.net/MaxAlexejev/from-distributed-caches-to- inmemory-data-grids
-
http://www.slideshare.net/jaxlondon2012/clustering-your-application- with-hazelcast
-
http://www.gridgain.com/blog/fyi/cache-data-grid-database/
-
http://gridgaintech.wordpress.com/2013/10/19/distributed-caching-is- dead-long-live/
-
http://www.hazelcast.com/resources/the-book-of-hazelcast/
- https://labs.consol.de/java-caches/part-3-3-peer-to-peer-with-hazelcast/
hibernate-dist-cache
By Yegor Bondar
hibernate-dist-cache
- 1,603