论坛首页 Java企业应用论坛

令人振奋的结果:memcached 访问速度达到66000TPS

浏览 20156 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-10-29  
sdh5724 写道

uniseraph 写道sdh5724 写道
最近,我陷入一个郁闷。 就是JAVA的序列化问题。 当你向MEMCACHED直接写序列化的对象的时候, 一个对象完整的描述将会被写进memcached。 那么如果写1000W个对象给memcached, 对象描述将会被写无数次。 序列化描述大小往往远远大于对象的实际数据的, 因此, 我们的内存就被大量这些信息浪费了。 谁解决了这个问题? 我在研究berkleydb java edition的解决方案。 这个问题对于内存节约使用是非常重要的。 我现在4台memcache机器吃了我20G内存, 再涨下去, 就要买机器了。 很不划算啊。


如果你放入的对象很多,对象类型不多,干脆将其转换成byte[]再写入memcached,用IoBuffer实现很简单。




你没有理解我的意思啊, 就是byte[] 也会有ClassInfo的啊. 我是做一个把所有CACHE种类接口统一化的项目.我无法预知用户要保存什么样的对象.  今天我研究了berkely DB java edition的代码, 发现他们是按照把存入对象的顺序, 把对象类型进行编号. 并单一在数据库里写入对象格式的, 实际对象的保存里前面几个字节保存了对象编号的. 在封闭系统中, 这样做是很好的. 可是, memcached是个非封闭系统, 我无法控制不同对象的编号!
   召唤大人们给我个美丽的解决方案啊, 机器贵啊贵啊...节约一台是台.


你看一下我的代码,byte[]不会产生ClassInfo,没有用对象序列化。

0 请登录后投票
   发表时间:2008-10-29  
uniseraph 写道

dennis_zane 写道key和value的大小,网络状况也说明下嘛。纯粹的tps没有多大意义。
既然大家这么关心key/value大小,明天我给一个测试结果,今天实在没空了。


刚才试,当key长度为5,value长度为100的时候,速度和key为5,长度为5的基本一致。明天回公司,用服务器试试,应该还是能到60000。
0 请登录后投票
   发表时间:2008-10-29  
codeutil 写道

javabean实现Externalizable 接口,自己实现byte转换,就可以不依赖描述信息。
bdb无非也是用bind接口来干同样的事情而已。

sdh5724 写道最近,我陷入一个郁闷。 就是JAVA的序列化问题。
当你向MEMCACHED直接写序列化的对象的时候, 一个对象完整的描述将会被写进memcached。 那么如果写1000W个对象给memcached, 对象描述将会被写无数次。 序列化描述大小往往远远大于对象的实际数据的, 因此, 我们的内存就被大量这些信息浪费了。 谁解决了这个问题? 我在研究berkleydb java edition的解决方案。 这个问题对于内存节约使用是非常重要的。 我现在4台memcache机器吃了我20G内存, 再涨下去, 就要买机器了。 很不划算啊。



正解。
0 请登录后投票
   发表时间:2008-10-29  
sdh5724 写道
uniseraph 写道
sdh5724 写道

最近,我陷入一个郁闷。 就是JAVA的序列化问题。 当你向MEMCACHED直接写序列化的对象的时候, 一个对象完整的描述将会被写进memcached。 那么如果写1000W个对象给memcached, 对象描述将会被写无数次。 序列化描述大小往往远远大于对象的实际数据的, 因此, 我们的内存就被大量这些信息浪费了。 谁解决了这个问题? 我在研究berkleydb java edition的解决方案。 这个问题对于内存节约使用是非常重要的。 我现在4台memcache机器吃了我20G内存, 再涨下去, 就要买机器了。 很不划算啊。


如果你放入的对象很多,对象类型不多,干脆将其转换成byte[]再写入memcached,用IoBuffer实现很简单。




你没有理解我的意思啊, 就是byte[] 也会有ClassInfo的啊. 我是做一个把所有CACHE种类接口统一化的项目.我无法预知用户要保存什么样的对象.  今天我研究了berkely DB java edition的代码, 发现他们是按照把存入对象的顺序, 把对象类型进行编号. 并单一在数据库里写入对象格式的, 实际对象的保存里前面几个字节保存了对象编号的. 在封闭系统中, 这样做是很好的. 可是, memcached是个非封闭系统, 我无法控制不同对象的编号!
   召唤大人们给我个美丽的解决方案啊, 机器贵啊贵啊...节约一台是台.


我也想知道答案,楼上的研究出来后要做下贡献啊!
0 请登录后投票
   发表时间:2008-10-29  
m8x6bmxb 写道

sdh5724 写道uniseraph 写道sdh5724 写道
最近,我陷入一个郁闷。 就是JAVA的序列化问题。 当你向MEMCACHED直接写序列化的对象的时候, 一个对象完整的描述将会被写进memcached。 那么如果写1000W个对象给memcached, 对象描述将会被写无数次。 序列化描述大小往往远远大于对象的实际数据的, 因此, 我们的内存就被大量这些信息浪费了。 谁解决了这个问题? 我在研究berkleydb java edition的解决方案。 这个问题对于内存节约使用是非常重要的。 我现在4台memcache机器吃了我20G内存, 再涨下去, 就要买机器了。 很不划算啊。


如果你放入的对象很多,对象类型不多,干脆将其转换成byte[]再写入memcached,用IoBuffer实现很简单。




你没有理解我的意思啊, 就是byte[] 也会有ClassInfo的啊. 我是做一个把所有CACHE种类接口统一化的项目.我无法预知用户要保存什么样的对象.  今天我研究了berkely DB java edition的代码, 发现他们是按照把存入对象的顺序, 把对象类型进行编号. 并单一在数据库里写入对象格式的, 实际对象的保存里前面几个字节保存了对象编号的. 在封闭系统中, 这样做是很好的. 可是, memcached是个非封闭系统, 我无法控制不同对象的编号!
   召唤大人们给我个美丽的解决方案啊, 机器贵啊贵啊...节约一台是台.

我也想知道答案,楼上的研究出来后要做下贡献啊!


建议看一下代码,官方的memcached java client,set方法传入的value参数是一个object,他会默认使用serialize接口序列化这个类成,所以有上面说的class信息。

我的实现中set方法传入value的是一个byte[],要求你自己序列化,我只管结果,所以你如果用ByteBuffer/IoBuffer/Externalizable就可以把对象转化成byte[],根据自己的需求定格式,就可以没有class info。


另外我记得官方的客户端中,如果set传入的value参数是byte[],应该不会序列化,直接使用byte[],时间长了记不太清楚,楼上可以自己查一下代码。



0 请登录后投票
   发表时间:2008-10-29  
晕死, 自己做, 我当然也能想到, 问题的现实是, 我开发了个API, 给其他程序员用, 还要他们实现外部序列化方法?
    就是外部序列化,也会浪费非常多的CLASSINFO的东西, 这个你可以看ObjectOutpuStream。  无论如何, 一个byte[], 要被重新组装回对象就必须付出ClassInfo的存储的代价。
   只有通过外部保存CLASSINFO的东西, 才能做到重新组装。
0 请登录后投票
   发表时间:2008-10-29  
sdh5724 写道

晕死, 自己做, 我当然也能想到, 问题的现实是, 我开发了个API, 给其他程序员用, 还要他们实现外部序列化方法?     就是外部序列化,也会浪费非常多的CLASSINFO的东西, 这个你可以看ObjectOutpuStream。  无论如何, 一个byte[], 要被重新组装回对象就必须付出ClassInfo的存储的代价。    只有通过外部保存CLASSINFO的东西, 才能做到重新组装。


你错了。 并非所有byte[]要重新组装回对象必须付出ClassInfo存储的代价。你想想,以前c/c++时候哪有classinfo,还不是照样完成了。



前面codeutil朋友也说了“javabean实现Externalizable 接口,自己实现byte转换,就可以不依赖描述信息。bdb无非也是用bind接口来干同样的事情而已。 ” 其实就是这个意思。


框架不可能结束所有问题的,所以有些时候还是得对应用开发者有些约束,所以要求他们满足某些约束,例如实现Externalizable接口。我说的IoBuffer也是如此。



0 请登录后投票
   发表时间:2008-10-29  
    一个对象可以这么做, 我甚至可以通过反射,或者anotation把所有要序列化的数据获得。 但是对象类型多了, 反序列化要确定对象类型是很困难的事情。 BDB的做法是, 把所有要被保存的对象, 获得他的对象类型, 然后独立保存了一份独立的数据表, 反序列化的时候, 查询对象的META来重新组装。
    作为架构人员, 首先要想到的是不是可行, 而不是限制。为系统API设置诸多的限制, 会让程序员痛苦的。
0 请登录后投票
   发表时间:2008-10-29  
sdh5724 写道

一个对象可以这么做, 我甚至可以通过反射,或者anotation把所有要序列化的数据获得。 但是对象类型多了, 反序列化要确定对象类型是很困难的事情。 BDB的做法是, 把所有要被保存的对象, 获得他的对象类型, 然后独立保存了一份独立的数据表, 反序列化的时候, 查询对象的META来重新组装。
    作为架构人员, 首先要想到的是不是可行, 而不是限制。为系统API设置诸多的限制, 会让程序员痛苦的。



和你理解恰好想法,框架不应该提供无限自由度的,更多的是一种约束,让开发者遵守框架的推荐的开发方式。

就今天这个问题,其实我们的区别在于对一个send的设计,你希望是
void send1(Object obj)

我更喜欢
public interface Command {
     byte[] toBuffer();
}
void send2(Command command);

并非一定是某种更好,但是相对来说,send2的约束更强,send1的自由度高。从你现在这个场景,我觉得send2更合适,而且也简单。
0 请登录后投票
   发表时间:2008-10-29  
sdh5724 写道
召唤大人们给我个美丽的解决方案啊, 机器贵啊贵啊...节约一台是台.

为啥要多买机器呢,在原有的机器上加内存不就可以了,现在内存白菜价,400可以买2G,400还不够一个资深Java开发人员一天的工资
12000 / 22 ~= 454
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics