Universal distributed caching and cluster distributed caching based on memcached for Java

Source: Internet
Author: User
Tags crc32 crc32 checksum md5 memcached static class delete cache

This article refer to for reference: http://guazi.iteye.com/blog/107164


Premise: Based on the memcached client for Java based on the two-time package, the implementation of two types of cache storage mode: Universal distributed cache and cluster distributed cache. The following is a UML diagram for the memcached client for Java two-time package.


For memcached client initialization is done in cachefactory by reading the configuration file cacheconfig.xml. Universal distributed caching, just a simple encapsulation, using the distributed support provided by memcached Client for Java, here is the realization idea of clustercache: a hash of the key value of the cached object being deposited, Find the corresponding server deposit, and then according to a certain rule to hash again, find another different server deposit, take the cache, first to take the key value of a hash, find the master server, if get failed or get the value of NULL, the key to hash again, Find it from the server, cache the results from this server (if the results are asynchronously updated to the primary server), thus forming a master-slave cluster cache. Features are: There is no absolute master node and from the node, normally all servers share the cache server, in the event of a server exception when the other server shared the increased access pressure.

The topological structure is as follows:

Source

Package Com.yx.cache;

Public interface Cache<t> {
	/**
	 * Gets the data in the cache * * 
	 @param key
	 *
	 @return
	/T Get (String key);

	/**
	 * Put data in cache if there is a value corresponding to the key, return failure
	 * * 
	 @param key
	 * @param value
	 * @return/
	Boolean Add (String key, T value);

	/**
	 * Put the data into the cache if there is a value corresponding to the key, overwrite the original value
	 * * 
	 @param key
	 * @param value *
	 @return
	* * Boolean set (String key, T value);

	/**
	 * Cache Update the
	 * 
	 * @param key
	 * @param value
	 * @return/
	Boolean is not updated if there is no cached value corresponding to the key Update (String key, T value);

	/**
	 * Delete Cache
	 * * 
	 @param key
	 * @return
	/boolean Delete (String key);


Universal Distributed Cache implementation class:

Package Com.yx.cache;

Import com.danga.MemCached.MemCachedClient;

public class Commoncache<t> implements cache<t> {
	private static memcachedclient memcachedclient = null;

	private String base = null;

	Commoncache (class<t> T, memcachedclient client) {
		memcachedclient = client;
		Base = T.getsimplename () + "-";
	}

	Public T get (String key) {return
		(T) memcachedclient.get (base + key);
	}

	public Boolean set (String key, T-value) {return
		Memcachedclient.set (base + key, value);
	}

	@Override Public
	Boolean update (String key, T value) {return
		memcachedclient.replace (base + key, value);

	@Override Public
	boolean Delete (String key) {return
		Memcachedclient.delete (base + key);
	}

	@Override Public
	Boolean Add (String key, T value) {return
		Memcachedclient.add (base + key, value);
	}


Cluster distributed Cache implementation class

Package Com.yx.cache;
Import com.danga.MemCached.MemCachedClient;
Import Com.schooner.MemCached.SchoonerSockIOPool;
Import Com.yx.cache.util.HashCodeUtil;

Import Com.yx.task.ThreadPoolManager;

	public class Clustercache<t> implements cache<t> {private static memcachedclient memcachedclient = null;

	private static Threadpoolmanager TaskManager = Threadpoolmanager. getinstance ("cache");

	Private String base = null;

	Private Schoonersockiopool pool = schoonersockiopool.getinstance ();
		Clustercache (class<t> T, memcachedclient client) {memcachedclient = client;
	Base = "I" + t.getsimplename () + "-";
		@Override public T get (String key) {T value = null;
		if (key = = null) {return null;
		Key = base + key;
		if (Pool.getservers (). length < 2) {value = (T) memcachedclient.get (key);

			else {int hashcode = Hashcodeutil.gethash (key);
			Value = (T) memcachedclient.get (key, hashcode); if (value = = null) {hashcode = This.getrehashCode (key, hashcode);
				Value = (T) memcachedclient.get (key, hashcode);
					if (value!= null) {//If the cache is fetched on another server, restore the first server Updatetask task = new Updatetask (key, value);
				Taskmanager.submit (Task);
	}} return value;
		@Override public Boolean set (String key, T value) {if (key = = null) {return false;
		Key = base + key;
		Boolean result = false;
		if (Pool.getservers (). length < 2) {result = Memcachedclient.set (key, value);

			else {int hashcode = Hashcodeutil.gethash (key);
			result = Memcachedclient.set (key, value, hashcode);
			if (result) {hashcode = Getrehashcode (key, hashcode);

			Memcachedclient.set (key, value, hashcode);
	} return result;
		private int Getrehashcode (string key, int oldhashcode) {string host = Pool.gethost (key, Oldhashcode);
		int rehashtries = 0;
		if (result) {int hashcode = Hashcodeutil.gethash (rehashtries + key); while (Host.equals (Pool.gethost (Key, Hashcode)) {rehashtries++;
		Hashcode = Hashcodeutil.gethash (rehashtries + key);
	return hashcode;
		@Override public boolean update (String key, T value) {if (key = = null) {return false;
		Key = base + key;
		Boolean result = false;
		if (Pool.getservers (). length < 2) {result = Memcachedclient.replace (key, value);

			else {int hashcode = Hashcodeutil.gethash (key);
			result = Memcachedclient.replace (key, value, hashcode);
			if (result) {hashcode = Getrehashcode (key, hashcode);

			Memcachedclient.replace (key, value, hashcode);
	} return result;
		@Override public boolean Delete (String key) {if (key = = null) {return false;
		Key = base + key;
		Boolean result = false;
		if (Pool.getservers (). length < 2) {result = Memcachedclient.delete (key);

			else {int hashcode = Hashcodeutil.gethash (key);
			result = Memcachedclient.delete (key, hashcode, NULL);

			if (result) {hashcode = This.getrehashcode (key, hashcode); MemcachEdclient.delete (key, hashcode, NULL);
	} return result;
		@Override public boolean Add (String key, T value) {if (key = = null) {return false;
		Key = base + key;
		Boolean result = false;
		if (Pool.getservers (). length < 2) {result = Memcachedclient.add (key, value);

			else {int hashcode = Hashcodeutil.gethash (key);
			result = Memcachedclient.add (key, value, hashcode);
			if (result) {hashcode = Getrehashcode (key, hashcode);

			Memcachedclient.add (key, value, hashcode);
	} return result;
		Static Class Updatetask implements Runnable {private String key;

		private Object value;
			Updatetask (String key, Object value) {this.key = key;
		This.value = value;
		@Override public void Run () {Memcachedclient.set (key, Value, Hashcodeutil.gethash (key));
 }

	}
}


Create memcached storage mode based on Factory mode (common mode or cluster mode)

Package Com.yx.cache;
Import java.util.ArrayList;
Import java.util.List;
Import Java.util.Map;

Import Java.util.concurrent.ConcurrentHashMap;
Import com.danga.MemCached.MemCachedClient;
Import Com.danga.MemCached.SockIOPool;

Import Com.yx.cache.util.ConfigUtil;

	public class Cachefactory {private static memcachedclient memcachedclient = null; @SuppressWarnings ("Rawtypes") private static final map<string, cache> Map = new concurrenthashmap<string, Cache

	> ();

		static {String Serverstr = configutil.getconfigvalue ("Servers", "");
		list<string> servers = new arraylist<string> ();
			For (String s:serverstr.split (",")) {s = S.trim (); if (! "".
			Equals (s)) {Servers.add (s); } if (Servers.size () < 1) {throw new RuntimeException ("cache initialization failed.")
		");
		} Sockiopool Pool = Sockiopool.getinstance ();
		Pool.setservers (Servers.toarray (new string[] {}));
		Pool.setfailover (Boolean.valueof (Configutil.getconfigvalue ("Failover", "true"));Pool.setinitconn (Integer.valueof (Configutil.getconfigvalue ("Initconn", "100"));
		Pool.setminconn (Integer.valueof (Configutil.getconfigvalue ("Minconn", "25"));
		Pool.setmaxconn (Integer.valueof (Configutil.getconfigvalue ("Maxconn", "250"));
		Pool.setmaintsleep (Integer.valueof (Configutil.getconfigvalue ("Maintsleep", "30")); Pool.setnagle (Boolean.valueof (Configutil.getconfigvalue ("Nagle", "false"));//Close Nagle algorithm Pool.setsocketto (
		Integer.valueof (Configutil.getconfigvalue ("Socketto", "3000"));
		Pool.setalivecheck (Boolean.valueof (Configutil.getconfigvalue ("Alivecheck", "true"));
		Pool.sethashingalg (Integer.valueof (Configutil.getconfigvalue ("Hashingalg", "0"));
		Pool.setsocketconnectto (Integer.valueof (Configutil.getconfigvalue ("Socketconnectto", "3000"));
		String wstr = configutil.getconfigvalue ("Weights", "");
		List<integer> weights = new arraylist<integer> ();
			For (String s:wstr.split (",")) {s = S.trim (); if (! "". Equals (s)) {Weights.add (integer.valueof (s));
		} if (weights.size () = = Servers.size ()) {pool.setweights (Weights.toarray (new integer[] {}));
		} pool.initialize ();

	Memcachedclient = new Memcachedclient (); public static <T> cache<t> Getcommoncache (class<t> T) {cache<t> Cache = Map.get (T.getname ()
		);
		if (cache = null) {cache = Createcommoncache (t);
	return cache; public static <T> cache<t> Getclustercache (class<t> T) {cache<t> Cache = map.get ("I" + t.g
		Etname ());
		if (cache = null) {cache = Createclustercache (t);
	return cache; private static synchronized <T> cache<t> Createcommoncache (class<t> T) {cache<t> Cache = ma
		P.get (T.getname ());
			if (cache = null) {cache = new commoncache<t> (T, memcachedclient);
		Map.put (T.getname (), cache);
	return cache; private static synchronized <T> cache<t> Createclustercache (class<
		T> t) {cache<t> Cache = Map.get (T.getname ());
			if (cache = null) {cache = new clustercache<t> (T, memcachedclient);
		Map.put (T.getname (), cache);
	return cache;
 }
}


Read the Profile tool class encapsulate and generate the hash code tool class

Configutil.java and Hashcodeutil.java

Package com.yx.cache.util;
Import java.io.IOException;
Import Java.io.InputStream;
Import Java.util.HashMap;
Import Java.util.Iterator;

Import Java.util.Map;
Import org.dom4j.Document;
Import org.dom4j.DocumentException;
Import org.dom4j.Element;

Import Org.dom4j.io.SAXReader;
	public class Configutil {private static final String Confile = "Cacheconfig.xml";

	Private static final map<string, string> Map = new hashmap<string, string> ();
		static {Saxreader Saxreader = new Saxreader ();
		InputStream ins = ConfigUtil.class.getClassLoader (). getResourceAsStream (Confile);
				try {if (INS!= null) {Document doc = saxreader.read (INS);
				Element root = Doc.getrootelement ();
				Iterator<element> iter = Root.elementiterator ();
					while (Iter.hasnext ()) {Element E = Iter.next ();
				Map.put (E.getname (), E.gettexttrim ());
			(Documentexception e) {//TODO auto-generated catch block E.printstacktrace (); throw new RuntimeexCeption ("config file not found:" + confile);
				Finally {try {if (INS!= null) {ins.close ();
				else {throw new runtimeexception ("config file not found:" + confile);
			The catch (IOException e) {//TODO auto-generated catch block E.printstacktrace ();
		}} public static string Getconfigvalue (string key, String defaultvalue) {string tmp = Map.get (key); Return IsEmpty (TMP)?
	defaultvalue:tmp;
	public static void Main (string[] args) {System.out.println (map); private static Boolean IsEmpty (String str) {if (str = NULL | |
		". Equals (str)) {return true;
	return false;
 }
}


Package com.yx.cache.util;
Import Java.security.MessageDigest;
Import java.security.NoSuchAlgorithmException;

Import java.util.zip.CRC32;

Import Com.schooner.MemCached.SchoonerSockIOPool;
	public class Hashcodeutil {public static final int native_hash = 0;//NATIVE String.hashcode (); public static final int old_compat_hash = 1; Original compatibility public static final int new_compat_hash = 2; New CRC32 based public static final int consistent_hash = 3;

	MD5 Based--Stops private static int hashingalg = Schoonersockiopool.getinstance (). Gethashingalg ();
	 /** * Returns a bucket to check for a given key. * @param key * String key cache is stored under * @return int bucket */public static final int get
		Hash (String key) {switch (HASHINGALG) {case Native_hash:return key.hashcode ();
		Case Old_compat_hash:return Origcompathashingalg (key);
		Case New_compat_hash:return Newcompathashingalg (key); Case Consistent_hash:rEturn Md5hashingalg (key);
			Default://Use the native hash as a default hashingalg = Native_hash;
		return Key.hashcode ();
		} private static int origcompathashingalg (String key) {int hash = 0;

		char[] CArr = Key.tochararray ();
		for (int i = 0; i < carr.length ++i) {hash = (hash *) + carr[i];
	return hash;
		private static int newcompathashingalg (String key) {CRC32 checksum = new CRC32 ();
		Checksum.update (Key.getbytes ());
		int CRC = (int) checksum.getvalue ();
	Return (CRC >>) & 0x7FFF;
		private static int md5hashingalg (String key) {messagedigest MD5 = Md5.get ();
		Md5.reset ();
		Md5.update (Key.getbytes ());
		byte[] Bkey = Md5.digest (); int res = ((bkey[3] & 0xFF) << 24) | ((Bkey[2] & 0xFF) << 16) | ((Bkey[1] & 0xFF) << 8) |
		(Bkey[0] & 0xFF);
	return res;  private static threadlocal<messagedigest> MD5 = new threadlocal<messagedigest> () {@Override protected Final MessageDigest InitialValue () {try {return messagedigest.getinstance ("MD5");
			catch (NoSuchAlgorithmException e) {throw new IllegalStateException ("No MD5 algorythm found");

}
		}
	};
 }


There is a lack of a tool class for cluster distributed caching Threadpoolmanage.java

Package com.yx.task;

Import Java.util.HashMap;
Import Java.util.Map;
Import java.util.concurrent.Executors;
Import Java.util.concurrent.ThreadPoolExecutor;

/**
 * @author liuyuxiao
 * @Date 2011-5-30 PM 04:34:16 * * Public
class Threadpoolmanager {

	private Static final map<string, threadpoolmanager> Map = new hashmap<string, threadpoolmanager> ();

	Final int core_size = 5;

	Private Threadpoolexecutor executor = (threadpoolexecutor) executors
			. Newfixedthreadpool (core_size);

	public void Submit (Runnable Task) {
		Executor.submit (Task);
	}

	public Boolean finished () {return
		executor.getcompletedtaskcount () = = Executor.gettaskcount ();
	}

	Private Threadpoolmanager () {

	} public

	static synchronized Threadpoolmanager getinstance (String key) {
		Threadpoolmanager t = map.get (key);
		if (t = = null) {
			t = new Threadpoolmanager ();
			Map.put (key, T);
		return t;
	}
}

For cluster cache mode and common cache mode tests:

Package com.yx.cache.test;

Import Com.yx.cache.Cache;
Import com.yx.cache.CacheFactory;

public class Testcommoncache {

	/**
	 * @param args
	 *
	/public static void main (string[] args) {

		cache& Lt string> cache = Cachefactory.getcommoncache (string.class);
		int count = 0;
		for (int i = 0; i < i++) {

			//Cache.set ("" + I, "hello!" + i);

			String result = Cache.get ("" + i);
			System.out.println (String.Format ("Set (%d):%s", I, success));
			if (result = = null) {
				count++
			}
			System.out.println (String.Format ("Get (%d):%s", I, result));
		}

		System.out.println (count);
		for (int i = 0; i < i++) {
		//memtask task = new Memtask ();
		Thread t = new thread (Task);
		T.start ();
		// }

	}
}

Package com.yx.cache.test;

Import Com.yx.cache.Cache;
Import com.yx.cache.CacheFactory;

public class Testclustercache {public

	static void Main (string[] args) {
		cache<string> Cache = cachefactory . Getclustercache (String.class);
		int count = 0;
		for (int i = 0; i < i++) {

			//Cache.set ("" + I, "hello!" + i);

			String result = Cache.get ("" + i);
			System.out.println (String.Format ("Set (%d):%s", I, success));
			if (result = = null) {
				count++
			}
			System.out.println (String.Format ("Get (%d):%s", I, result);}
		}






Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.