`
xerobuffer
  • 浏览: 3963 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

使用Memcached java client时的对象系列化

阅读更多
    最近实施的一个WEB项目中,需要处理较高的并发访问,如果使用数据库查询,恐怕难以满足要求,考虑到数据绝大数情况下只做select,不做update,还有少量insert,使用memcache应该是减少直接访问DB的有效方式。
    memcached中只是简单的存储key/value,对于memcached来说,不认为value具有任何业务上的意义。将java中的对象存储到memcached中的时候,需要将对象作适当的变换,比如变换成字符串形式,或者二进制形式。当从memcached中取出来时需要做相应的逆变换。
    默认情况下,memcached java client会使用java的默认系列化机制。一般说来效率都很低。在项目进行中,最先尝试了JSONReader和JSONWriter这两个工具类,高并发的测试条件下表现一般(应该是因为,在反系列化的时候,是一个字符一个字符处理的)。
    考虑到项目中需要存放到memcahed中的对象数量较少,而且对象属性基本上是原始类型,最后选择了自己实现系列化和反系列化。
    1)在已知对象属性类型和数量的情况下,直接将对象属性变化为String形式,然后属性之间使用分隔符(为了避免这样的分隔符在对象属性中本来就可能出现,可是使用比较复杂的分隔符,比如[$])。
    2)为了存储List类型的对象或者对象数组,可以定义对象间的分隔符,然后每个对象使用1)中描述的方法系列化后,做字符串拼接。
    3)反系列化的时候,将字符串分割为字符串数组,然后逐一赋值给对应的对象属性。

    这里,比较费时间的应该是反系列化操作过程中的字符串分割,在网上看到一种相对高效的方法,暂且称之为双扫描法,实测发现,性能确实优于String.split。
public static String[] split(String s, String delimiter) {
	if (s == null) {
		return null;
	}
	int delimiterLength;
	int stringLength = s.length();
	if (delimiter == null || (delimiterLength = delimiter.length()) == 0) {
		return new String[] { s };
	}

	// a two pass solution is used because a one pass solution would
	// require the possible resizing and copying of memory structures
	// In the worst case it would have to be resized n times with each
	// resize having a O(n) copy leading to an O(n^2) algorithm.

	int count;
	int start;
	int end;

	// Scan s and count the tokens.
	count = 0;
	start = 0;
	while ((end = s.indexOf(delimiter, start)) != -1) {
		count++;
		start = end + delimiterLength;
	}
	count++;

	// allocate an array to return the tokens,
	// we now know how big it should be
	String[] result = new String[count];

	// Scan s again, but this time pick out the tokens
	count = 0;
	start = 0;
	while ((end = s.indexOf(delimiter, start)) != -1) {
		result[count] = (s.substring(start, end));
		count++;
		start = end + delimiterLength;
	}
	end = stringLength;
	result[count] = s.substring(start, end);

	return (result);
}


使用以上方法实现后,对比测试,比JSONReader和JSONWriter方法系列化和反系列化约快5倍。

    虽说,速度是提高了,测试发现,对象的系列化和反系列化仍然占用了大量的系统处理时间。曾有一种说法,memcached不适于java,一个重要的原因应该就是java系列化效率不高吧。
    针对这个问题,后来使用了二级cache的方式,将一部分结果作为java对象存储在HashMap类似的结构中,主要目的也是为了减少直接访问memcached,减少系列化,尤其是反系列化操作。
    虽说使用HashMap或者ConcurrentHashMap实现一个cache并不需要太多的工作量,但是如果要具备命中率查询、cache占用内存控制、自动失效等功能却也不是那么简单。网上找到一个双链表方式实现的高速缓存(org.jivesoftware.util下的Cache相关的几个工具类)的描述,据说性能不错,因此也就拿来试试了。其中有对对象Size的计算,使用中可能需要自己做部分调整。由于这些代码内部是用的是普通的HashMap,get和set方法都是用了synchronize保证线程安全。并发测试中,很快发现这些get方法成为性能瓶颈。于是借鉴ConcurrentHashMap类似的方式,对jivesofteware中的这个Cache实现进行简单封装,基本思路就是:在内部使用多个(比如32个)jivesoftware这样的Cache,不同key的对象分布在不同的内部cache中(比如使用简单的求模方式决定某个Key的对象应该在哪个cache中)。这样,理论上可以同时处理32个并发请求。
分享到:
评论
1 楼 峡谷追风 2012-08-09  
java中不是自己有序列化和反序列化么
java.io.Serializable这个类的效率非常低噶?

相关推荐

    JAVA上百实例源码以及开源项目

    得到RSA密钥对,产生Signature对象,对用私钥对信息(info)签名,用指定算法产生签名对象,用私钥初始化签名对象,将待签名的数据传送给签名对象(须在初始化之后),用公钥验证签名结果,使用公钥初始化签名对象,用于...

    java开源包1

    GiftedMotion是一个很小的,免费而且易于使用图像互换格式动画是能够设计一个有趣的动画了一系列的数字图像。使用简便和直截了当,用户只需要加载的图片和调整帧您想要的,如位置,时间显示和处理方法前帧。 Java的...

    JAVA上百实例源码以及开源项目源代码

    得到RSA密钥对,产生Signature对象,对用私钥对信息(info)签名,用指定算法产生签名对象,用私钥初始化签名对象,将待签名的数据传送给签名对象(须在初始化之后),用公钥验证签名结果,使用公钥初始化签名对象,用于...

    java开源包8

    GiftedMotion是一个很小的,免费而且易于使用图像互换格式动画是能够设计一个有趣的动画了一系列的数字图像。使用简便和直截了当,用户只需要加载的图片和调整帧您想要的,如位置,时间显示和处理方法前帧。 Java的...

    java开源包4

    GiftedMotion是一个很小的,免费而且易于使用图像互换格式动画是能够设计一个有趣的动画了一系列的数字图像。使用简便和直截了当,用户只需要加载的图片和调整帧您想要的,如位置,时间显示和处理方法前帧。 Java的...

    java开源包11

    GiftedMotion是一个很小的,免费而且易于使用图像互换格式动画是能够设计一个有趣的动画了一系列的数字图像。使用简便和直截了当,用户只需要加载的图片和调整帧您想要的,如位置,时间显示和处理方法前帧。 Java的...

    java开源包101

    GiftedMotion是一个很小的,免费而且易于使用图像互换格式动画是能够设计一个有趣的动画了一系列的数字图像。使用简便和直截了当,用户只需要加载的图片和调整帧您想要的,如位置,时间显示和处理方法前帧。 Java的...

    java开源包6

    GiftedMotion是一个很小的,免费而且易于使用图像互换格式动画是能够设计一个有趣的动画了一系列的数字图像。使用简便和直截了当,用户只需要加载的图片和调整帧您想要的,如位置,时间显示和处理方法前帧。 Java的...

    java开源包9

    GiftedMotion是一个很小的,免费而且易于使用图像互换格式动画是能够设计一个有趣的动画了一系列的数字图像。使用简便和直截了当,用户只需要加载的图片和调整帧您想要的,如位置,时间显示和处理方法前帧。 Java的...

    java开源包5

    GiftedMotion是一个很小的,免费而且易于使用图像互换格式动画是能够设计一个有趣的动画了一系列的数字图像。使用简便和直截了当,用户只需要加载的图片和调整帧您想要的,如位置,时间显示和处理方法前帧。 Java的...

    java开源包10

    GiftedMotion是一个很小的,免费而且易于使用图像互换格式动画是能够设计一个有趣的动画了一系列的数字图像。使用简便和直截了当,用户只需要加载的图片和调整帧您想要的,如位置,时间显示和处理方法前帧。 Java的...

    java开源包3

    GiftedMotion是一个很小的,免费而且易于使用图像互换格式动画是能够设计一个有趣的动画了一系列的数字图像。使用简便和直截了当,用户只需要加载的图片和调整帧您想要的,如位置,时间显示和处理方法前帧。 Java的...

    java开源包2

    GiftedMotion是一个很小的,免费而且易于使用图像互换格式动画是能够设计一个有趣的动画了一系列的数字图像。使用简便和直截了当,用户只需要加载的图片和调整帧您想要的,如位置,时间显示和处理方法前帧。 Java的...

    java开源包7

    GiftedMotion是一个很小的,免费而且易于使用图像互换格式动画是能够设计一个有趣的动画了一系列的数字图像。使用简便和直截了当,用户只需要加载的图片和调整帧您想要的,如位置,时间显示和处理方法前帧。 Java的...

    Java资源包01

    GiftedMotion是一个很小的,免费而且易于使用图像互换格式动画是能够设计一个有趣的动画了一系列的数字图像。使用简便和直截了当,用户只需要加载的图片和调整帧您想要的,如位置,时间显示和处理方法前帧。 Java的...

Global site tag (gtag.js) - Google Analytics