Ehcache synchronization principle, ehcache Synchronization
A problem found during a recent study on ehcache synchronization:
Currently, server A and server B synchronize information from server A to server B and use RMI for manual synchronization.
The configuration information is as follows:
<?xml version="1.0" encoding="UTF-8"?><ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="false" monitoring="autodetect" dynamicConfig="true"> <cacheManagerPeerListenerFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory" properties="hostName = 127.0.0.1, port = 50001, socketTimeoutMillis=10000" /> <cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory" properties="peerDiscovery=manual, rmiUrls=//127.0.0.1:40001/clusterCache"/> <cache name="clusterCache" maxEntriesLocalHeap="999999999" eternal="false" timeToIdleSeconds="1800" timeToLiveSeconds="1800" overflowToDisk="false"> <cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"/> </cache></ehcache>
Core code for synchronization:
String key = StringUtils.leftPad(Thread.currentThread().getName() + a, 20, "a");Element element = new Element(key, value);CacheInstance.cache.put(element);
All values reference the same static variable static final byte [] bytes = new byte [1024*100];
Test found a problem: Assume that a single byte [1024*100] is synchronized with 16000 data records, the size of the synchronized data is about GB. However, during the synchronization process, the network adapter of server B is monitored, no such big data is found on the NIC.
After analysis, we know that:
The RMI protocol is composed of java serialization and HTTP protocol. During synchronization, all the synchronized data is serialized, and the value put into the Element is actually a reference to the static variable value, by default, 1000 elements are synchronized during ehcache synchronization. Therefore, the data of these 1000 elements passing through the NIC is only one byte [1024*100.
Ehcache synchronization source code:
private void writeReplicationQueue() { List<EventMessage> eventMessages = extractEventMessages(maximumBatchSize); if (!eventMessages.isEmpty()) { for (CachePeer cachePeer : listRemoteCachePeers(eventMessages.get(0).getEhcache())) { try { cachePeer.send(eventMessages); } catch (UnmarshalException e) { String message = e.getMessage(); if (message.contains("Read time out") || message.contains("Read timed out")) { LOG.warn("Unable to send message to remote peer due to socket read timeout. Consider increasing" + " the socketTimeoutMillis setting in the cacheManagerPeerListenerFactory. " + "Message was: " + message); } else { LOG.debug("Unable to send message to remote peer. Message was: " + message); } } catch (Throwable t) { LOG.warn("Unable to send message to remote peer. Message was: " + t.getMessage(), t); } } } }
MaximumBatchSize indicates the number of elements to be synchronized. The value can be customized in the following Configuration:
<cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" properties = "asynchronousReplicationMaximumBatchSize=1"/>
AsynchronousReplicationMaximumBatchSize = 1 indicates that an Element is synchronized at a time. In this case, the traffic passing through the NIC is actually normal.