庄周梦蝶

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

初识Kestrel

Posted on 2009-09-15 11:34 dennis 阅读(15360) 评论(9)  编辑  收藏 所属分类: java源码解读
    Kestrel是一个scala写的twitter开源的消息中间件,特点是高性能、小巧(2K行代码)、持久存储(记录日志到journal)并且可靠(支持可靠获取)。Kestrel的前身是Ruby写的Starling项目,后来twitter的开发人员尝试用scala重新实现。它的代码非常简洁并且优雅,推荐一读。

    Kestrel采用的协议是memcached的文本协议,但是并不完全支持所有memcached协议,也不是完全兼容现有协议。标准的协议它仅支持GET、SET、FLUSH_ALL、STATS,扩展的协议有:
           
              SHUTDOWN       关闭kestrel server     
              RELOAD         动态重新加载配置文件
              DUMP_CONFIG    dump配置文件
              FLUSH queueName   flush某个队列

    每个key对应都是一个队列。标准memcached文本协议的支持上也没有完全兼容,SET不支持flag,因此现有大多数基于flag做序列化的memcached client都无法存储任意java类型到kestrel;FLUSH_ALL返回"Flushed all queues.\r\n"而不是"OK\r\n"。

    GET协议支持阻塞获取和可靠获取,都是在key上作文章,例如你要获取queue1的消息,并且在没有消息的时候等待一秒钟,如果有消息马上返回,超时时间后还没有就返回空,kestrel允许你通过发送
                     "GET queue1/t=1000\r\n"

来阻塞获取。本来的key应该queue1,这里变成了"queue1/t=1000",因此如果你使用的client有对返回的key和发送的key做校验,那么可能就认为kestrel返回错误。
    什么是可靠获取呢?默认的GET是从队列中获取消息后,server端就将该消息从队列中移除,客户端需要自己保证不把这个消息丢失掉,也就是说这里是类似JMS规范中的自动应答(auto-acknowledge),如果客户端在处理这个消息的时候异常崩溃或者在接收消息数据的时候连接断开,那么可能导致这个消息永久丢失。Kestrel的可靠获取就是类似JMS规范中的CLIENT_ACK mode,客户端获取消息后,server将这个消息从队列移除并正常发送给客户端,如果这时候客户端崩溃或者连接断开,那么server将不会确认该消息被消费并且"un-get"这个消息,重新放到队列头部,那么当client重新连接上来的时候还可以获取这个消息;只有当server收到客户端的明确确认消息成功的时候,才将消息移除。这个功能也是通过key做手脚,

"GET queue1/open\r\n"   开始一次可靠获取
"GET queue1/close\r\n"  确认消费成功


你要关闭前一次可靠获取开启新的一次,还可以这样调用
"GET queue1/close/open\r\n"


    要注意的是每个连接的client只能有一个正在执行的可靠获取,关闭一个没有开启的reliable fetch或者在执行一次reliable fetch再次open一个新的获取都将直接返回空。

    从kestrel的协议方面,我们可以学习到的一点就是在做一份协议的时候,如果有多种不同语言的client的话,应该尽量用通用协议,通用协议通常都已经有很多成熟的client可以使用,避免了为私有协议开发不同语言的client;并且我们可以在通用协议上作扩展,例如kestrel在key上面做的花样,通过给key附加不同的属性即可实现一些特殊功能

    XMemcachedClient默认是无法支持kestrel对memcached的协议的扩展,也就是说无法支持阻塞获取、可靠获取和flush_all,这是因为xmemcached会对返回的key和发送的key做校验,如果不相等就认为解码错误;并且由于kestrel不支持flag,因此无法存储java序列化类型;另外一个问题是,xmemcached(spymemcached)都会将连续的GET协议合并成一个bulk get协议,而kestrel也并不支持bulk get,所以需要关闭这个优化,这个可以通过下列代码关闭:
memcachedClient.setOptimizeGet(false);

Spymemcached似乎不提供这个选项。为了解决序列化问题,我添加了一个新的KestrelCommandFactory,使用这个CommandFactory后,将默认关闭get优化,并且不对GET返回的key做校验从而支持阻塞获取和可靠获取,并且将在存储的数据之前加上4个字节的flag(整型),因此可以支持存储任意可序列化类型。但是有一些应用只需要存储字符串类型和原生类型,这是为了在不同语言的client之间保持可移植(如存储json数据),那么就不希望在数据之前加上这个flag,关闭这个功能可以通过
memcachedClient.setPrimitiveAsString(true);

方法来设置,所有的原生类型都将调用toString转成字符串来存储,字符串前不再自动附加flag。

    KestrelCommandFactory已经提交到svn trunk,预计在xmemcached 1.2.0-RC2的时候发布。

    使用KestrelCommandFactory对kestrel做的性能测试,server和client都跑在linux上,jdk6,单线程单client连续push消息

               消息个数       消息长度       是否启用journal   时间       TPS(/s)
                500000          256             否              123.0s     4065
                500000          1024            否              126.3s     3959
                500000          4096            否              120.6s     4145
                500000          4096            是              122.1s     4095
                500000          8192            是              121.2s     4125

从数据上来看比官方数据好很多,可能机器配置不同。是否启用journal带来的影响似乎很小,写文件都是append,还是比较高效的。

kestrel的项目主页  http://github.com/robey/kestrel
kestrel的wiki页    http://wiki.github.com/robey/kestrel
xmemcached项目主页  http://code.google.com/p/xmemcached/



评论

# re: 初识Kestrel[未登录]  回复  更多评论   

2009-09-16 12:38 by tenderuser
scala 现在已经有人在使用了? 太快了。。

# re: 初识Kestrel  回复  更多评论   

2009-09-16 13:00 by Unmi
是啊发展太快了
请问是否可以转载

# re: 初识Kestrel  回复  更多评论   

2009-09-16 14:38 by Sparkle
其实我不认同kestrel这种用memcached协议的做法,看上去兼容性强了,实际上很多暗病。而且memcached的文本协议也不见得是什么好协议

# re: 初识Kestrel  回复  更多评论   

2009-09-16 14:55 by dennis
@Sparkle
通用协议,肯定没办法做到效率的最大化,针对应用做优化,胜在可以有多种成熟的client可用,对于没有能力或者时间开发多种语言client的团队来说是有价值的。memcached的文本协议确实不怎么样,我在写xmemcached的时候就觉的解析起来不是很方便,有些拐弯抹角的地方。一开始它的协议是简单的,随着功能的附加,又要考虑兼容性,导致不得不开发二进制协议了。

# re: 初识Kestrel  回复  更多评论   

2009-09-16 14:55 by dennis
@Unmi
请注明出处即可

# re: 初识Kestrel  回复  更多评论   

2009-10-15 10:14 by Xuefeng
分析得很精到,
欢迎加入Scala中文社区邮件列表,保持Scala爱好者之间联系,加强和方便交流,分享和合作。
发送空邮件到: scalacn+subscribe@googlegroups.com 加入邮件列表

# re: 初识Kestrel  回复  更多评论   

2009-10-15 10:14 by Xuefeng
或访问http://groups.google.com/group/scalacn

# re: 初识Kestrel  回复  更多评论   

2009-10-15 10:16 by Xuefeng
http://groups.google.com/group/scalacn

# re: 初识Kestrel  回复  更多评论   

2009-10-15 13:01 by dennis
@Xuefeng
已加入,感谢

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


网站导航: