您的位置:首页 > 其它

阿里天池中间比赛总结,即消息队列引擎设计

2017-07-03 17:56 405 查看
阿里天池中间比赛总结,即消息队列引擎设计

题目传送门:

https://code.aliyun.com/middlewarerace2017/open-messaging-demo?spm=5176.100068.555.1.76d97540zXrIuM

这次比赛的任务就是:根据阿里的《Open-Messaging规范》实现消息队列引擎该规范也是阿里开源消息队列racketMq的接口规范。要求,多线程写入,把消息竟可能多的罗盘。杀掉消息生产者后,启动消息消费者,多线程尽可能多地消费消息。然后计算tps.

由于消息body是设定为无限大的,导致一个消息的大小是不固定的,为此我们对消息建立索引块MessageIndex,这个MessageIndex规定了一个消息的边界和位置。一个消息索引的大小是固定的。

topic和queue的功能一样的,唯一的却别是topic是多个消费者线程共享的,而且是而且消息是广播的(每个消费者有且只能消费一次)。抽象了一个队列父类bucket.

为了提高写入速度,充分利用硬盘空间和内存空间采用顺序写入。消息引擎顺序写入硬盘会导致各个队列高度离散(各个队列的数据参差在一起),使得读取数据时候耗费大量CPU资源。为了减低队列的离散程度,队列申请消息存放空间是队列块BucketBlock的形式申请的,一个块的大小可以通过一个全局参数去调优。这样一个队列就是由多个离散的BucketBlock组成,而BucketBlock内的消息都属于同一队列的连续消息,有了BucketBlock同一队列的消息离散程度变得可调节了。

为了硬盘的吞吐量,采用直接内存映射技术。这个技术利用的是虚拟内存技术,充分利用内存大大提高的文件的读写性能。

我们将一个消息顺序的写入一个文件中,直到消息文件的大小超过阀值才另起门户。同时将该消息的索引messageIndex写入该队列最新的bucketBlock中,存放bucketBlock的文件也是顺序写入的,所以存放bucketBlock的文件也是有一个阀值。

我们发现对于上亿的数据量bucketBlock的文件很多,这会给消息引起解析队列长度和bucketBlock的寻址造成很大的负担。由此我们队bucketBlock建立了索引,也就是说一个bucketBlock对应一个所以bucketBlockIndex,那么一个队列由多个bucketBlockIndex组成,一个bucketBlockIndex对象索引一个队列块,一个队列块有多个消息索引messageIndex ,一个消息索引对应一个消息message。

至此,我们设计完了队列的数据结构。

通过调优文件的阀值,和bucketBlock中存放消息索引的个数就可以实现很好的性能调优了。

读取的消息我们采用随机访问机制,通过解析队列中的索引,我们可以轻易的访问到硬盘中的消息。

比赛中还有一个比较有意思的考点:设计高效的序列化算法。由于消息的头部的数据类型只有字符串,Integer,Double,long,所以我们可以最大程度的提高数据的紧凑程度,比如一个Integer默认就是4个Byte,long用8个Byte,这样提高紧凑程度。当然还可以更高效的采用无损压缩算法,对数据进行压缩。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  阿里 设计 开源