庄周梦蝶

生活、程序、未来
   :: 首页 ::  ::  :: 聚合  :: 管理

fqueue初步分析

Posted on 2011-09-16 20:10 dennis 阅读(9197) 评论(7)  编辑  收藏 所属分类: java源码解读

    fqueue是国产的一个类似memcacheq,kestrel这样的支持memcached协议的轻量级开源MQ。它的项目主页:
http://code.google.com/p/fqueue/downloads/list,介绍和特点都可以看主页,我就不废话了。

    今天老大提到, co了源码看了下,写个初步分析报告。

    首先是它的存储层,主要是一个FQueue这么一个抽象队列,内部实现是FSQueue,也就是基于文件的FIFO队列。这个队列是多个文件组成的。每个文件默认大小在150M,超过即切换一个新文件来写。读的时候如果读到尾部,则查找下一个文件进行读取。数据文件名以idb为后缀,并且从编号1开始递增,除了数据文件外,每个队列还有个db为后缀的索引文件,记录当前写和读的数据文件编号和偏移量。目录结构大概是这样:
    --fqueue
        --fqueuedata_1.idb
        --fqueuedata_2.idb
        --……
        --icqueue.db

    文件的存储比较有特色,采用MappedByteBuffer做文件读写,MappedByteBuffer是java nio引入的文件内存映射方案,读写性能极高,但是也有一定的问题,比如说内存占用,以及数据刷入设备的不确定性和关闭问题。在fqueue中,每隔10毫秒会强制force一次buffer,将修改过的数据刷入设备。对于关闭问题,则采用那个技巧,示例代码:
/**
     * 关闭索引文件
     
*/
    
public void close() {
        
try {
            mappedByteBuffer.force();
            AccessController.doPrivileged(
new PrivilegedAction<Object>() {
                
public Object run() {
                    
try {
                        Method getCleanerMethod 
= mappedByteBuffer.getClass().getMethod("cleaner"new Class[0]);
                        getCleanerMethod.setAccessible(
true);
                        sun.misc.Cleaner cleaner 
= (sun.misc.Cleaner) getCleanerMethod.invoke(mappedByteBuffer,
                                
new Object[0]);
                        cleaner.clean();
                    } 
catch (Exception e) {
                        log.error(
"close logindexy file error:", e);
                    }
                    
return null;
                }
            });
            fc.close();
            dbRandFile.close();
            mappedByteBuffer 
= null;
            fc 
= null;
            dbRandFile 
= null;
        } 
catch (IOException e) {
            log.error(
"close logindex file error:", e);
        }
    }

    利用反射,并且使用了sun特有的类,不具有可移植性。MappedByteBuffer还有一个问题是map的代价比较高,可能在切换文件的时候fqueue会有一定程度的阻塞现象。

    存储的性能,我在我的机器测试了下,似乎没有作者宣称的那么高,我的机器是5400转的普通SATA盘,写入1K数据的平均QPS在8000左右。我估计fqueue的性能跟磁盘有很大关系,如果使用15000转的SAS盘应该能有很大改观。

    网络层直接使用了jmemcached的实现,jmemcached是一个java实现的memcached,通常用于单元测试之类。看情况fqueue也支持memcached的二进制协议了。网络框架使用了netty3,这些就不多说了。自己看都明白。额外提一下,作者做的单元测试使用了xmemcached,咔咔,广而告之。

    总体来说fqueue是一个整体上很清爽和轻量级的MQ实现,适合一些特定的场景,至于性能,我们下周准备做个压测,到时候再谈吧。

评论

# re: fqueue初步分析  回复  更多评论   

2011-09-16 21:01 by fuyou001
请问下 getCleanerMethod.setAccessible(true);
sun.misc.Cleaner cleaner = (sun.misc.Cleaner) getCleanerMethod.invoke(mappedByteBuffer,
new Object[0]);

这个技巧,在哪有相关文档,看的似懂非懂的?
在java api里MappedByteBuffer 类里没有cleaner方法,其父类也没有

# re: fqueue初步分析[未登录]  回复  更多评论   

2011-09-16 21:17 by dennis
@fuyou001
看 sun.nio.ch.DirectBuffer

MappedByteBuffer是direct buffer的一种。

# re: fqueue初步分析  回复  更多评论   

2011-09-17 01:07 by 孙立
我是Fqueue的作者。很高兴看到你的分析。
你提到的:可能在切换文件的时候fqueue会有一定程度的阻塞现象。
这个起始有考虑,每次打开,会提前预分配下一个文件避免阻塞。sun.nio.ch.DirectBuffer这个东西的使用,是当时在windows下面出现无法删除的问题,但是在linux下面似乎没有这个问题。
单个文件的大小,推荐设置为40M左右。
Fqueue的存储层性能直接取决于磁盘性能。我前两天刚测试在服务器上sas上,1K的qps有19万。

# re: fqueue初步分析  回复  更多评论   

2011-09-17 08:55 by tb
学习了

# re: fqueue初步分析  回复  更多评论   

2011-09-17 12:59 by dennis
@孙立
感谢作者的回复,呵呵,我初步看了下,还不够仔细。下周做个压测再向你请教。

# re: fqueue初步分析  回复  更多评论   

2011-09-18 16:00 by vbg
jmemcached 是memcached 的一个java实现。
jmemcached 和 fqueue 有啥关系呀?

它们是怎么配合的?

# re: fqueue初步分析  回复  更多评论   

2011-09-18 16:10 by vbg
看了CacheStorage<String, LocalCacheElement> storage = new FSStorage();知道FSStorage是memcached实现的缓存存储。

只有注册用户登录后才能发表评论。


网站导航: