MetaQ在双十二彩票中的运用

双十二大促是淘宝集市的年终促销活动,活动当天扫描首页二维码赠送一注彩票的活动更是让大家“玩”了一把。面对瞬间的数倍于往常的峰值,如何让用户有一个良好的体验,如何保证系统的稳定运行,让我们来揭秘这一切。

归纳一下系统需要做到如下几点:

  • RT足够短

  • 压力分布均匀

  • 复杂逻辑分离,异步化


系统结构图

caipiao2-300x58.jpg

图1-系统结构图

大体分为两个部分:活动系统,彩票系统,他们之间通过消息驱动。
活动系统里面只更新一个彩票分配的状态,数据更新成功就返回给用户,逻辑足够简单能保证RT非常短。彩票系统负责真正的彩票出票和更新用户状态等一些耗时操作。

用户在首页扫描二维码发起对活动系统的请求,活动系统更新彩票分配状态,产生一条消息,立即返回并。彩票系统收到这个消息完成后续出票等一些的业务操作。整个过程是通过MetaQ提供的消息服务驱动完成。活动的时候会有大量的请求涌进活动系统,会产生大量的消息,预估qps达到24w;并且消息不可丢失,确保用户都能领到一注彩票;活动系统,彩票系统业务复杂度相差较大,处理能力也相差较大,可能会出现大量的堆积;为了让用户有个较好的体验,消息的消费也需要足够的及时。综上对MetaQ有这么一些挑战:

  • 高吞吐量

  • 数据可靠

  • 高效堆积

  • 消息投递足够低延迟


下面介绍一下MetaQ如何做到这些的。

MetaQ简介

METAQ是一款完全的队列模型消息中间件,服务器使用Java语言编写,可在多种软硬件平台上部署。客户端支持Java、C++编程语言,已于2012年3月对外开源,开源[地址](http://metaq.taobao.org/)。MetaQ的设计目标是高吞吐量,高效堆积。完全的队列模型还提供了顺序消息,消息回溯等一些特性。

metaq_overview

图2-MetaQ整体结构

基本概念

  • Topic 消息主题

  • Partition 分区,代表一个消费队列 (一个Topic可以划分为多个分区,分区数越多并行度越大,支持的Qps越高)

  • Group 消费分组,代表一个消费集群

MetaQ对外提供的是一个队列服务,内部实现也是完全的队列模型,这里的队列是持久化的磁盘队列,具有非常高的可靠性,并且充分利用了操作系统cache来提高性能。这些特性都源于存储层的设计。

MetaQ存储结构

MetaQ的存储结构是根据阿里大规模互联网应用需求,完全重新设计的一套存储结构,使用这套存储结构可以支持上万的队列模型,并且可以支持消息查询、分布式事务、定时队列等功能,如图3所示。

metaq_store_overview

图3-MetaQ存储体系


存储层可以大致分为数据文件(CommitLog)和索引文件两部分。数据文件保存了所有的消息的内容,索引文件保存了消息所在数据文件的偏移量。消息数据不区分Topic,顺序的append到CommitLog,索引文件按照Topic-Partition维度组织,不同分区的消息append到不同索引队列里面。

消息写入
客户端发送一条消息,数据首先会写到文件缓存中,同时派发一个写索引请求;异步的构建消息索引。

消息读取
客户端读取消息,根据索引的位置找到需要读取的消息的物理位置和消息长度,从CommitLog中读取数据,通过文件缓存来加速消息的读取。通常热数据都在缓存中,无需IO操作;非热数据,会触发缺页中断,数据从磁盘加载到文件缓存中,直接写到socket缓冲区,避免数据进入Java堆。

数据刷盘
刷盘后数据最终持久化到磁盘。刷盘方式分为两种方式:同步刷盘,数据写入缓存后立即刷盘,确保数据落盘后返回客户端,MetaQ在同步刷盘过程中也做了一定优化避免过多的性能损失;异步刷盘,数据批量定时的刷到磁盘。

数据清理
消息数据按照文件有效期定时做清理。

数据复制
数据可靠性要求很高的应用,可通过数据复制保证数据的可靠。MetaQ提供两种数据同步的方式:同步双写,数写入到主机后会同时写到备机,主备都写成功才返回客户端成功,主备间数据无延迟,MetaQ有一套自己的主备间高效数据复制方案;异步复制,数据写到主机后返回客户端成功,主备间异步同步,主备间存在一定的延迟。

MetaQ单机上万队列

metaq_queue

图4-MetaQ单机上万队列

MetaQ的大部分功能都是靠队列来驱动,以文件的方式存储,通过内存映射对数据进行操作。所有的消息都是顺序的写到数据文件(CommitLog),完全顺序的写入,避免随机IO;消息索引按照Topic和Partition的维度区分串行的写到索引文件。通过这种这种组织方式可以实现单机上万队列,如图4所示。

数据流图

数据流图

图5-MetaQ数据流图

消息数据首先写入到Java堆,然后在写入到文件缓存,在根据具体的刷盘策略Flush到磁盘;消费消息的时候如果是热数据则直接从系统缓存写到socket发到远端;如果非热数据则由系统产生缺页中断将数据从磁盘加载到系统缓存在写到socket,数据不进应用程序内存空间。内存的管理,页面的换入换出都是由OS来管理的。同时消息的拉取也是批量的,一次处理多条数据,尽量减少往返的时间。
MetaQ性能依赖于系统内存分配,磁盘IO的有效利用,所以我们也对操作系统内存分配,脏页会写策略,以及IO调度算法做了一些调优,让资源的分配耗时趋于平稳,堆积的时候保持较高的吞吐量。

负载均衡

发送端负载
默认发送端通过轮询的方式向broker写消息,如图6所示;也可以自行指定消息发到哪里。

图6-默认发送端负载

图6-默认发送端负载

消费端负载
默认是消费集群机器均分所有的消费队列。余下的部分由靠前的消费者消费,如图7所示。消费端负载均很也可以定制,如同机房优先等。

图7-默认消费端负载

图7-默认消费端负载

其他特性

综上MetaQ主要有以下一些特性:

  • 高吞吐量,低延迟

  • 高效堆积;亿级消息堆积能力

  • 完全分布式;客户端,服务端都是分布式的,每个结点的变化都能动态负载

  • 顺序消息;能保证消息的严格顺序

  • 实时消息订阅

  • 丰富的消息拉取模式

  • 消息过滤

  • 消息内容查询

  • 消息回溯

  • 事物消息

  • 高可用HA


上文介绍了双十二彩票系统面临的挑战,以及MetaQ如何克服这些难点。如果对其中的实现细节感兴趣;或者对其他的一些特性感兴趣可以参看MetaQ开源地址:[http://metaq.taobao.org/]。有什么疑问或者好的建议也欢迎大家给予我们反馈。



你可能感兴趣的:(metaq,双十二彩票)