对于大型的互联网业务来说,消息系统是必不可少的基础服务。 子柳 在《淘宝技术这十年》中为大家展示了阿里消息系统架构的概貌,作为集团业务使用的核心基础服务,目前消息系统现在可以承受每天几百亿规模的请求,并在历年的双十一、双十二大促中承受住抗住了更加严峻的考验,消息系统背后的中间件团队还陆续开源了诸如MetaQ、RocketMQ等项目。近期,InfoQ 采访了阿里消息中间件团队消息和分布式数据层负责人王晶昱(花名:沈询),话题涉及案例中间件系统的选型、系统扩容与数据一致性、团队文化等内容。
InfoQ:对于阿里的消息中间件系统,大家所广泛了解的是@子柳 在《淘宝技术这十年》中介绍的 Notify ,但是从最近的阿里的开源计划中,我们经常看到 MetaQ/RocketMQ ,在阿里内部 Notify 和 MetaQ 是怎样的关系?我看到早期的MetaQ是采用的Kafaka的设计思路,那么可能大家就比较好奇“问什么要重复造轮子”,能不能介绍这个方面的考虑以及所做的工作?
沈询:要讲明白这个问题,就需要从产品的实际需求角度入手开始做个介绍了。Notify作为一个已经存在了5年多的消息产品,被广泛的应用在整个阿里巴巴集团的大部分消息通信领域。它的核心特性是: 提供事务支持、不保证消息顺序、消息可能会重复、推模型。
因为淘宝是个交易类网站,所以事务支持的特性能够非常方便的让用户可以快速的依托于Notify完成他们自己的业务逻辑。
然而,一个产品不可能满足所有的场景,在当时我们就经常收到一些需要保证消息有序的发送和接收的需求,而这样的场景对于上来就定位于无序消息投递的 Notify 来说无异于釜底抽薪。
而正在我们讨论这类需求应该如何被满足的时候,正好赶上 LinkedIn 的 KafKa 队列开源,简单的文件队列,拉模型,保证顺序的特性一下就吸引了我们的目光,在对他的做了整体架构上的Review以后,我们认为这是个非常优雅的模型,因为他足够简单,简单就是最好的~!
然而里面也有一些特性不是我们所需要的,比如我们主要是面向内部用户,因此定期轮询去拉的方式就不适合我们的实际场景需求,并且因为 KafKa 的开发语言是 Scala ,不大利于我们的后续的维护,因此我们借鉴了 Kafka 的核心思路,对其进行了重写并开源,当然我们还是向 LinkedIn 的 KafKa 做了致敬的,MetaQ 其实是 Metamorphosis 的意思,是Kafka的名作。
从上面的发展历程其实也就能够比较清晰的找到两个消息队列产品的不同定位了:
- RocketQ(MetaQ) 主要面向消息有序的场景,能够提供更大的消息堆积能力
- Notify,主要面向需要更加安全可靠地交易类场景,无序,推模式。
InfoQ:您个人在分布式方面有比较多的经验,而消息系统中一个重要的考虑因素就是分布式的扩展能力,尤其是对于阿里、淘宝的业务,能不能介绍下目前中间件团队在分布式是如何做的?跨域、跨机房方面?
沈询:其实所谓分布式运算,核心的思路就是系统架构无单点, 让整个系统可扩展。
如果要介绍分布式场景的实际经验,那么我就需要先引入一个概念:“有状态存储节点和无状态运算节点”。
无状态运算节点主要是部署 Web 应用、 HSF 服务,消息队列等的机器有状态的存储节点主要是指部署数据库、缓存、配置服务器、 NoSQL 等的机器。
那么针对无状态节点,因为不存储数据,请求分发可以采取很简单的随机算法或者是轮询的算法就可以了,如果需要增加机器,那只需要把对应的运算代码部署到一些机器上,然后启动起来,引导流量到那些机器上就可以实现动态的扩展了,所以一般来说在无状态的节点的扩展是相对的容易的,唯一需要做的事情就是在某个机器承担了某种角色以后,能够快速的广播给需要这个角色提供服务的人说:“我目前可以做这个活儿啦,你们有需要我做事儿的人,可以来找我。”
而针对有状态节点,扩容的难度就相对的大一些,因为每台 Server 中都有数据,所以请求分发的算法不能够用随机或者是轮询了,一般来说常见算法就是哈希或者是使用 Tree 来做一层映射,而如果需要增加机器,那么需要一个比较复杂的数据迁移的过程,而迁移数据本身所需要的成本是非常高的,这也就直接导致有状态节点的扩容难度比无状态节点更大。
针对有状态节点的难题,我们提供了一套数据自动扩容和迁移的工具来满足用户的自动扩容缩容中所产生的数据迁移类的需求。 于是,无论是有状态的数据节点的扩容,还是无状态的数据节点的自动扩容,我们都可以使用自动化工具来完成了。
在所有的节点都能够实现自动的扩容以后,整个体系就能够水平的进行扩展了。这种架构很好的支持了我们历年的双11大促,而且每年都有一些进步。然而,这套模式也不是万能药,在当下,杭州已经很难满足我们对机器的全部需求了。
为此,我们也在尝试进行异地数据中心的尝试,以期能够将一部分运算和存储能力搬运到异地机房进行。
提到异地数据中心,一般第一个会被想到的是 Google 的 Spanner,这套系统是一个跨数据中心的强一致数据库系统,然而我们在经过仔细的考量以后,认为在目前的情况下,使用这种方式并不能够解决一个大规模在线交易类网站对于高并发TPS的实际需求,因此我们选择了另外的方式来实现跨数据中心的事务模式。
其核心思想也很简单,即是将数据放置在距离用户最近的机房里面,并尽可能减少应用层的跨机房调用,以充分提高性能,降低延迟。
InfoQ:消息系统在保证数据的一致性方面做了哪些工作?
沈询:一致性这是个说复杂,挺复杂;说简单,也挺简单的领域。要理解一致性,其实关键在一个“看”字,一致性约束的是一个用户写入并提交数据之后,其他用户去读这条记录的时候,要么看到的是事务开始之前的状态,要么就是事务结束后的状态,而在这两个状态之间的事务状态则不会被其他人看到。
我们以一个例子做说明:
李雷要给韩梅梅100元,那么,要么结果是韩梅梅有100元,要么是李雷有100元,而李雷减少了100元,但韩梅梅还没加上这100块的这个中间状态则不能够被其他人看到。
做到这个一致性的一般性做法就是把数据加锁,让某个数据只能被某个进程或线程访问就行了。但这样也有个代价就是锁住数据的时间越长,系统的并发程度越低,系统的tps也就越低了。尤其在分布式场景下,维持锁的延迟在加入了网络这个因素后,变得非常巨大,以至于很难接受。
因此在互联网行业中,大家普遍使用的方式是“最终一致”,也就是,三种状态都有可能出现,但李雷减少了100元,韩梅梅却没加上100元这个状态,因为速度非常快,只有毫秒级,并且对用户没有太多的不良影响,所以就认为是允许了。
用户可见的状态,从原来的两个状态,变成了三个状态。
然而需要注意的是,最终一致并不意味着弱一致,也就是说,韩梅梅“最终”必须能够拿到这笔钱,能够拿到,就是“最终”一致,在异常状态下不能够拿到,那就是“弱”一致。
消息系统的作用,就在于能够将“弱”一致变成“最终”一致,保证多方数据的状态的最终正确性。
InfoQ: 目前消息中间件的使用规模是怎样的?目前的吞吐量、负载如何?在中间件博客中提到了双12期间中间件在彩票活动中所起的总用,是否能够详细介绍下在两次大促期间,中间件团队所做的工作?遇到的问题以及应对方案?
沈询:基本上整个阿里集团都在使用我们的中间件所提供的服务,消息规模在几百亿每天,高峰期 load 在4~5左右。
在大促过程中,消息中间件主要起到了蓄水池的作用,投递消息的往往都是核心应用,机器会优先保证,处理能力强劲,而接受消息的应用则可能存在处理不过来的情况,因此业务请求会在消息中间件中做一次削峰的操作,从而可以保证后端系统不会因为前端流量过载而导致系统不可用。
InfoQ:目前所在的团队具体负责哪些工作?团队组成是怎样的?如何分工?业务扩展方向是怎样的?
沈询:阿里中间件团队,是国内为数不多的极具技术挑战性的团队之一,依托于全球规模最大的阿里巴巴电子商务平台所带来的巨大流量和海量数据,以及对于电子商务平台固有的稳定性要求,使得团队有机会去面对一个又一个技术难题,创造一个又一个技术奇迹。在刚刚过去的“2013双十一网购狂欢节”中,350亿元销售奇迹背后的每一笔交易订单都和阿里中间件团队的技术小二们息息相关。
中间件团队致力于成为中国第一、世界一流的Java技术团队。自主研发的一系列产品始于07年底开始的淘宝架构 2.0 到 3.0 的变迁过程中,使淘宝网 从集中式的 Java 应用走向了分布式 Java 应用,涵盖了消息中间件、服务框架、数据层、应用服务器和大规模分布式稳定性平台等等。解决了淘宝网这个大型系统中的应用间以及应用到水平拆分后的数据库间的访问问题,通过消息中间件对应用进行了解耦并提供了最终一致性支持。目前广泛使用在大淘宝的各个Java应用中以及少部分的非Java应用中。而稳定性平台、性能优化平台是在淘宝系统分布式化后解决和稳定性、容量规划、降级管理、依赖告警以及性能丈量等方面的问题的利器。
中间件团队的同学是一群不安于现状且喜欢折腾的人,未必很资深但是很执着,充满热情。大家来自五湖四海,到这里一起解决技术难题,提升系统性能,完成业务突破,构建新的应用,玩儿转技术、业务、数据、无线。
如果你酷爱技术、喜欢钻研、愿意去帮助多个业务系统的发展,并且认为编程是别人不能剥夺的权利的话,欢迎加入我们,一起提升我们的技术产品,一起去支持业务更好的发展。
如果你希望在淘宝的土壤上,用我们的技术去折腾一些新应用,新玩儿法出来,也欢迎通过[email protected]或者[email protected]和我们联系
InfoQ:您个人的经历也是比较有意思,我看到在 ADC 2012 的分享中,您提到自己做过4年淘宝小二、参与淘宝所有去 O 项目、负责分布式数据库中间件团队、到现在负责消息中间件团队,能不能详细介绍下自己成长的历程?
沈询:我当年是被这团队的 Title “骗”来的,当时中间件这个团队的名字非常唬人: “淘宝平台架构组”,不能不说平台架构这个名字对于刚毕业的学生来说确实是高大上啊~
其他的事情其实更多地还是在外部环境和自己的积累上。
能够赶上这样快速发展并且需求多种多样的应用场景,不能不说是一个程序员最幸福的事情,尽管也会偶尔为了解决一个线上问题在高度紧张下在线上操作到深夜等这类问题,不过当你回头看看,会发现过程本身其实就是个积累的时刻,碰到并解决的坑越多,加上自己的一些思考与探索,自然就会有一定建树。
InfoQ:作为一个需要对阿里系的所有项目提供支撑服务的团队,在选择团队成员的时候一般都会从哪些方面考量?如何确保对的人作对的事?
沈询:首先,希望他是个技术人:毕竟这是个纯粹的技术团队,产品本身就是纯粹的技术产品,因此计算机体系内知识,编程技巧方面的要求是首要的要求。
第二,希望他是个品行端正的正人君子,能够能够准确的把握自己的实际需要,拥有自我管理的能力,并能与其他人进行合作,能够体谅其他人的难处。
第三,希望他是个能够独立解决未知问题的人、独立思考、不人云亦云、活用知识,能够解决实际问题。
在用人上面,我们比较关注每个人自己的主观能动性,毕竟兴趣是最好的老师,所以个人的需求会优先被考虑。当然,团队本身客观上会有一些不得不去做的事情,不过这种情况下也会在充分尊重个人意愿的情况下做好沟通性工作的。
沈询其实是个花名,原作里叫沈洵,是个40多岁的白衣大侠,真实的我就是个普通的程序员,平时喜欢看一些杂书,天文地理海洋气象历史政治经济都喜欢读读,在技术上主要还是关注数据库相关的业界最新进展。