2018美团技术—后端系列

can发布于2019/02/22

注脚

展开查看详情

1.

2. 序 春节已近,年味渐浓。 又到了我们献上技术年货的时候。 不久前,我们已经给大家分享了技术沙龙大套餐,汇集了过去一年我们线上线下技术沙龙 99位讲师,85 个演讲,70+小时 分享。  今天出场的,同样重磅——技术博客全年大合集。 2018年,是美团技术团队官方博客第5个年头, 博客网站 全年独立访问用户累计超过300万,微信公众  号(meituantech)的关注数也超过了15万。 由衷地感谢大家一直以来对我们的鼓励和陪伴! 在2019年春节到来之际,我们再次精选了114篇技术干货,制作成一本厚达1200多页的电子书呈送给大 家。 这本电子书主要包括前端、后台、系统、算法、测试、运维、工程师成长等7个板块。疑义相与析,大家 在阅读中如果发现Bug、问题,欢迎扫描文末二维码,通过微信公众号与我们交流。 也欢迎大家转给有相同兴趣的同事、朋友,一起切磋,共同成长。 最后祝大家,新春快乐,阖家幸福。

3. 目录 - 后台篇 APPKIT打造稳定、灵活、高效的运营配置平台 ...................................................................... 4 CAT 3.0 开源发布,支持多语言客户端及多项性能提升 ...................................................................... 17 LruCache在美团DSP系统中的应用演进 ...................................................................... 22 Netty堆外内存泄露排查盛宴 ...................................................................... 32 Oceanus:美团HTTP流量定制化路由的实践 ...................................................................... 47 UAS-点评侧用户行为检索系统 ...................................................................... 57 美团DB数据同步到数据仓库的架构与实践 ...................................................................... 66 不可不说的Java“锁”事 ...................................................................... 74 境外业务性能优化实践 ...................................................................... 91 美团广告实时索引的设计与实现 ...................................................................... 106 大众点评账号业务高可用进阶之路 ...................................................................... 123 美团容器平台架构及容器技术实践 ...................................................................... 135 美团即时物流的分布式系统架构设计 ...................................................................... 147 美团点评运营数据产品化应用与实践 ...................................................................... 154 美团服务体验平台对接业务数据的最佳实践-海盗中间件 ...................................................................... 167 美团点评智能支付核心交易系统的可用性实践 ...................................................................... 176 卫星系统——酒店后端全链路日志收集工具介绍 ...................................................................... 192 深入浅出排序学习:写给程序员的算法系统开发实践 ...................................................................... 200 每天数百亿用户行为数据,美团点评怎么实现秒级转化分 ...................................................................... 220 析?

4. APPKIT打造稳定、灵活、高效的运营配置平台 - 美团技术团队 APPKIT打造稳定、灵活、高效的运营配置平台 作者: 国宝 小龙 一、背景 美团App、大众点评App都是重运营的应用。对于App里运营资源、基础配置,需要根据城市、版本、平 台、渠道等不同的维度进行运营管理。如何在版本快速迭代过程中,保持运营资源能够被高效、稳定和灵 活地配置,是我们团队面临的重大考验。在这种背景下,大众点评移动开发组必须要打造一个稳定、灵 活、高效的运营配置平台。本文主要分享我们在建设高效的运营配置平台过程中,积累的一些经验,以及 面临的挑战和思考。 运营资源 简单而言,运营资源可以理解为App中经常变动的一些广告、运营活动等等,譬如下图中电影首页顶部的 Banner位,就是一个典型的运营资源。对于这类运营资源,它们有如下明显特征: 1. 时效性,只在一定时间范围内显示在C端固定位置。 2. 城市强相关,这类运营资源往往是基于LBS类服务,每个活动、广告都只会出现在固定的某些城市(或区域)。 基础配置 基础配置,常见的有入口资源的配置、网络的配置等。相对运营资源来说,其变更的频繁度相对较低,与 时间、城市的关系也没那么强。譬如下面大众点评App-我的页面里的入口。这类配置有如下几个特征: 1. 多维度:需要针对不同的版本、平台、渠道,做不同的配置。 2. 长期有效:这种类型的配置一般长期存在,不会存在过期问题。

5. APPKIT打造稳定、灵活、高效的运营配置平台 - 美团技术团队 二、遇到的问题 在从0到1打造运营配置平台的过程,我们遇到了很多“坑”。特别是在早期“刀耕火种”的时代,对于入口 的配置,往往是通过“hardcode(硬编码)”的方式写死在代码中。所以必然会遇到很大的问题,这主要 体现为以下两方面: 运营效率低 对于新的运营配置需求,研发同学需要开发对应的配置页面,然后转给运营同学进行配置的管理,最后运 营人员对资源进行配置上线,其流程如下: 对于每个运营配置需求都要经过需求评审、页面开发、配置管理、上线的流程。同时,对于配置页面的开 发,少则需要1到2天的开发工时,研发成本高。问题总结如下: 1. 研发成本高,每个需求要开发新的配置管理页面。 2. 研发周期长,运营效率低,从需求的提出到运营上线周期长。 3. 灵活性差,对不同的运营维度(城市、版本、时间等)都需要事先确定好,无法动态调整。 上线流程“粗糙” 在早期,运营配置上线流程需要研发同学参与。产品提出运营配置需求,研发同学通过修改代码对配置进 行变更,然后通过代码上线进行发布。整体流程如下: 这种上线机制存在以下几个问题: 1. 配置上线过多依赖于代码的发布。 2. 整体上线过程无审核机制,无法对配置资源进行合规审核。 3. 配置容易出错,上线前不能提前预览上线后的效果,只有“事后”(上线后)才能验证效果。

6. APPKIT打造稳定、灵活、高效的运营配置平台 - 美团技术团队 三、我们的思考 针对以上问题,我们希望通过设计一个通用的解决方案,去解决上文阐述的各种运营资源管理的问题。我 们把这个整体的项目称之为APPKIT,寓意是App的运营配置工具(Kit)。通过不断的实践和总结,我们 希望能从三个维度解决上述问题: 数据JSON化 随着业务的不断迭代,无论采用怎样的数据字段组成,都无法满足业务变化的字段(这里是指像标题、副 标题、图片、跳转链接等)要求。对底层数据进行JSON化,其对应的数据字段完全可动态扩展,从而满 足业务不断迭代的需求。JSON化随之也会带来运营位字段管理的问题,我们通过字段管理的工具来解决 这个问题。 运营流程化 设计一套整体的流程管理机制,解决运营的投放、审核、发布和回滚的问题。通过流程化的机制,我们实 现了“事前”、“事中”、“事后”的三级管理。 首先,在运营配置上线前,通过测试用户的预览功能,可以预览上线后的实时效果。同时,通过穿越功能 可查看将来时段显示的效果。防止出现上线后链接出错、视觉效果达不到预期等问题。 其次,在流程阶段,引入审核机制,通过视觉和内容两方面的审核,保证投放数据的准确性。 最后,在运营配置上线后,如果发现问题,可以通过快速回滚,最大限度地实现“止损”。 接口SDK化 对于运营数据,无论是通过数据库的落地方案、还是通过分布式缓存的方案,都无法彻底解决服务中心化 和服务抖动的问题。通过接入的SDK化,可以做到数据的本地缓存更新机制,解除对中心化服务的依赖, 大大提升服务的稳定性和性能。同时整个APPKIT服务变成可水平扩展,在扩展过程中也不会影响中心服 务的稳定性。 四、APPKIT架构 APPKIT运营配置系统整体框架如下(数据流向如箭头所示)。从功能角度,大体上分为四层:数据层、 服务层、接入层和监控层。

7. APPKIT打造稳定、灵活、高效的运营配置平台 - 美团技术团队 4.1 数据层 数据层作为最底层的数据存储,其保存了最基本的运营后台数据、流程数据和线上数据。对持久化的数 据,我们采用MySQL进行存储;对于缓存数据,我们采用了Redis的解决方案。这样数据层形成基本的两 级存储结构:MySQL保证了数据的持久性,Redis保证了数据获取的速度。 这里我们对底层数据划分为三个不同域:后台数据,相当于草稿数据,运营人员所有的操作都记录在这 里;流程数据,运营人员操作完成后,提供发布流程,预览及审核都在流程数据里进行;线上数据,审核 通过后,数据同步到线上数据,最终C端用户获取到的数据都是来源于线上数据。 谈到数据层,这里我们遇到了存储上的一个小问题。按城市运营的每条数据,都需要存储具体的城市ID列 表,其在数据库里的存储为 “1,2,3,4…… ”这样字符串。而这种数据存储在业务请求和条件过滤过程中, 存在着如下两个问题: a. 大数据存储对内存的消耗 美团、大众点评运营的城市成千上万,如果每条运营的投放数据都包含大量的城市列表信息,对机器内存 势必产生一定消耗。 b. 过滤性能问题 城市的过滤逻辑大体是这样:用户所在城市与从数据库获取到的城市列表(“1,2,3,4…… ”)进行匹配, 在每次匹配过程中都需要做字符串“split”的切割操作。这种操作的特点是流量越大,对机器CPU的消耗 越大。 解决方案:基于以上两点考虑,再结合Java语言提供的BitSet机制。我们从数据库里取出城市列表数据后 只做一次“split”切割操作,将数据转化为BitSet类型。这样在实际过滤过程中只需要通过BitSet的get机

8. APPKIT打造稳定、灵活、高效的运营配置平台 - 美团技术团队 制就可以判断运营投放的城市是否包含了用户所在的城市。通过BitSet机制,我们既解决了大数据存储对 内存的消耗问题,又解决了城市过滤的性能问题。 4.2 服务层 服务层向下对底层数据进行操作;向上为接入层获取数据提供接入能力。其提供四个服务能力:运营后 台、开放平台、数据服务、APPKIT-SDK,如下表所列: 服务层 4.3 接入层 接入层主要为运营人员、业务研发提供接入能力。通过运营流程化为事前、事中、事后提供保障。一个运 营资源从制作到最后在C端展示,需要经过运营人员的投放、测试预览、审核及发布的中间流程。这里对 于一些敏感的运营资源,需要通过安全部门的审查。安全审查主要涉及到敏感词的处理、敏感图片的检测 等。对运营配置平台来说,它完全是一个“黑盒模型”。这里主要涉及到两种情况: 1. 资源上线时 2. 资源上线后

9. APPKIT打造稳定、灵活、高效的运营配置平台 - 美团技术团队 4.4 监控层 APPKIT-SDK运行在业务机器上,这里就涉及到多台机器的数据一致性问题。同时,随着业务接入运营 数据的增多,SDK对机器内存势必有一定消耗。基于服务的稳定性考虑,我们对SDK运行时的投放内容进 行监控,其主要监控两个指标:运营位数及每个运营位的配置总数。这样做可以带来以下几个好处: 1. 对接入的业务数及机器数进行统计。 2. 通过SDK的配置总数监控,防止数量超过最大限制。 同时,对于非SDK的其他性能指标,我们采用统一的监控平台– CAT 进行监控,其中包括:APPKIT中  心服务的调用QPS,机器的性能,网络流量等通用指标。 五、底层模型–灵活性设计 5.1 从一个例子切入 数据模型往往与业务相关。业务越复杂,设计需要越简单,这样方能满足复杂业务的各种变化。因为数据 模型太过于抽象,如果直接进行述说会有些乏味,我们可以先从一个具体的业务实例入手。下面是大众点 评App顶部金刚位的截图,对于这部分数据,如何做到运营可配? 首先,我们对运营数据做需求拆解。对于这块数据,每个 “节点”(对应每个位置:如美食,技术上我们 称之为 “节点”),其基本的运营诉求如下: 1. 节点内容信息:标题、图片、跳转链接、排序。 2. 节点的过滤维度信息:城市、版本、平台、渠道等。 3. 节点其他信息:角标,如外卖节点,其有一个下午茶这样的角标。值得注意的是,像下午茶这样的角标,除去文案、 文案颜色这些基本信息之外,我们也可以按城市、平台、进行过滤(不周的城市对应的文案可能不一样,如上海 为“下午茶”,北京因为嘉年华活动可以改成“嘉年华”)。 上面这个运营场景算是非常经典、复杂的一个运营场景了,如果这个问题解决了,其他问题自然就会迎刃 而解。 5.2 技术分析 我们做一下进一步的技术分析:

10. APPKIT打造稳定、灵活、高效的运营配置平台 - 美团技术团队 首先,这里有节点,每个节点(Node)有其相应的内容(Content),节点与内容是“一对多”的关系。 这里的内容,我们指的是如标题、图片、跳转链接等信息,虽然是“一对多”的关系,但最后在同一个城 市、同一个版本下(可选择)只显示一条内容。为什么有这样的需求?举一个简单的业务场景实例,以外 卖为例,在新版本10.0的时候做了一个全新的外卖频道页面,其链接信息与老版本的完全不同,这里我们 就需要按版本的不同配置两条不同的内容信息。 其次,节点与节点之间有两层关系,其一为“平级关系”,如美食与外卖的关系,这种关系就是一种简单 的列表关系;其二为树关系(Tree),如外卖与下午茶之间的关系。这里我们将角标(下午茶)视为一 个节点,因为角标也需要按不同维度进行过滤,因此下午茶成了外卖的子节点。其实这里有一些特殊的地 方,如果角标不需要按城市、版本等维度进行运营,那很简单它就是一个内容信息(类似标题)。 最后,我们谈一谈排序问题,对于这么多品类,如何排序,他们的优先级是什么?我们需要定一个基本的 基调,每个节点都有一个基本的排序值(优先级)。但深入业务分析,对于不同的人(群),每个人关注 的点不一样,需要一个“千人千面”的算法,来决定每个人所看到的内容是其真正关心的内容。所以,这 种应用场景下的排序应该通过机器学习算法而得到。 5.3 数据建模 针对上面的技术分析,我们提出了一种节点(Node)-内容(Content)-树(Tree)模型,简称为N- C-T模型。如下图所示:左边为抽象的数据模型,右边为以上实例的实现。 N-C-T数据模型设计的非常简单,其中C和T部分都是可选择的,这样使得其灵活性比较强,可以应对业 务变化的大部分需求。注意,这里我们只是对业务需求的宏观表现形式进行建模,对于具体Node和 Content里的有哪些字段(标题、副标题、图片、跳转链接),这些都是JSON化的存储格式,可以满足 任意字段的扩展。 5.4 模型的应用与小结 通过以上经典实例,我们可以很容易通过我们的数据模型解决这个问题。我们再回到文章最开头的背景章 节的运营场景,Banner位,如下:

11. APPKIT打造稳定、灵活、高效的运营配置平台 - 美团技术团队 这种Banner位,套用我们上的数据模型,它其实是一种只有一个Node节点、多个Content节点的模型。 这也是一种典型的应用场景,为此我们总结了两种应用场景。 其实,大部运营场景都可以套用以上两种经典的运营组合。 六、运营流程化 将运营资源的管理进行流程化,具有以下几个好处: 1. 资源上线前可进行严格的审核。 2. 出问题时可快速回滚。 3. 记录用户的(上线)操作历史。 4. 上线前可提前预览线上效果。 数据域 对于流程化的实现,我们是将数据域切分成三个不同的部分:后台数据、流程数据和线上数据,如下图所 示:

12. APPKIT打造稳定、灵活、高效的运营配置平台 - 美团技术团队 后台数据:我们可以简单理解为草稿数据,这里的数据多用户可同时进行操作,也不会对线上数据有影 响。 流程数据:当用户后台数据编辑完成后,对数据提交一个发布流程,数据进入流程数据区域;这时可对数 据进行测试预览、审核等操作。 线上数据:这块数据是C端用户真正获取到的数据,当流程数据审核通过后,数据会自动同步到线上数据 域,完成上线操作。 上线流程 整个上线流程如下: 1. 运营同学对后台数据进行修改,提交发布流程,同时进行预览测试。 2. 审核同学对提交的发布流程进行审核。 3. 审核通过,自动发布到线上(对审核不通过的流程,数据回退到后台进行再次编辑)。 为了能平稳上线,我们设计了一个测试预览功能。当数据处于流程中时,用户可以通过扫描二维码加入到 测试用户名单,可对处于审核流程中的数据进行预览,用美团、大众点评App查看上线后实时效果,其实 现的数据流如下: 七、稳定性的演进 稳定性是一个运营配置平台最重要的能力,没有稳定性,其他任何功能都会失去实际意义。运营系统的稳 定性经历了不同的迭代时期,总结起来,可概括为以下三个阶段: 7.1 经典方案 这是APPKIT最早期的经典方案,它的实现也非常简单,如下图所示:

13. APPKIT打造稳定、灵活、高效的运营配置平台 - 美团技术团队 C端用户通过业务接入层获取数据,业务接入层通过服务调用获取配置后台数据(APPKIT服务),配置 后台数据服务读取缓存数据。如果缓存数据不存在,则从数据库中读取数据,同时将数据库数据同步到 Redis缓存中。这是经典的数据获取模型,但它有以下几个缺点: 1. 数据调用有网络时延。 2. Redis缓存抖动(网络抖动)会对服务的稳定性产生影响。 3. 缓存的单Key存储的容量限制。 7.2 缓存方案 针对以上经典方案的缺点,我们做了进一步的改进,对配置后台数据服务做了一层本地内存缓存,如下图 所示: 样做可以解决数据调用的部分网络时延问题,同时Redis缓存的抖动也不会影响整体服务的性能。不过, 这个方案也有其自身的缺陷。 1. APPKIT服务成了中心节点,业务方对中心节点强依赖,随着业务接入越来越多,中心服务的压力会等比例增加。 2. 业务接入层与配置后台数据服务间调用的网络时延问题仍然存在。 3. 单机的Web缓存容量有限,随着业务接入越多,APPKIT服务器本地缓存的数据量越大。 7.3 SDK方案

14. APPKIT打造稳定、灵活、高效的运营配置平台 - 美团技术团队 为彻底解决缓存方案的问题,尤其是服务中心化带来的流量、容量等问题,我们将运营数据的获取、 Web缓存的管理集成进SDK。如下图所示: 这样的话,无论接入再多的业务,也不会对中心服务产生过大的流量压力和容量压力。SDK同时也解决了 服务间调用的网络时延问题。所有同步数据的网络调用都是通过后台线程异步完成,不会影响业务线程的 正常处理逻辑。 不过,SDK方案也引进了如下的新问题: 1. 数据时效性和一致性如何保证? 2. SDK本地缓存如何监控?过期数据如何删除? 3. SDK版本如何升级? 为了解决数据的时效性和一致性问题,我们引入了监听更新机制,如下图所示: 运营人员在运营后台操作完成后,提交上线流程,流程发布后通过ZooKeeper的变化监控发送一个变化 事件;SDK通过监听变化事件,拉取变化后的运营数据更新到本地。这里,为了防止这种监听机制失效, 我们也做了一个兜底策略:每分钟定期进行一次数据同步。这样保证数据最迟一分钟内就能实现同步。对 于SDK本地缓存,我们设计了监控上报机制,如下图所示:

15. APPKIT打造稳定、灵活、高效的运营配置平台 - 美团技术团队 这里有两条线路,其一为SDK在请求数据时,带上数据的accessTime时间戳,APPKIT服务会根据 accessTime时间戳判断SDK本地数据是否过期。当accessTime时间超过24小时,说明这个运营位在一 天内都没有使用,可以从本地内存中进行删除。其二为SDK定期进行监控上报,上报SDK本地缓存的数 目,这样可以对SDK本地缓存进行监控和告警。对SDK版本升级问题,现有的解决方案,是通过CI构建时 对SDK版本升级进行提示(必要时进行强制),不过大部分运营位使用的都是基础功能,在很大程度上不 需要进行频繁地升级。 效果对比 缓存方案与SDK方案的效果对比如下: 注: SDK方案的平均线为0.0是因为统计时舍入引起的,真实值其实非常小。 八、总结与展望 本文通过美团点评移动运营平台的实践,详细介绍了我们在打造稳定、灵活、高效的运营配置平台过程中 遇到的问题和挑战,同时本文也提供我们的解决思路:通过数据JSON化,运营流程化,接口SDK化分别 解决了运营平台的灵活性、高效性和稳定性。APPKIT帮助产品、运营和研发提升C端的开发和运营效 率,加速产品的迭代进程。

16. APPKIT打造稳定、灵活、高效的运营配置平台 - 美团技术团队 目前基于APPKIT的平台化特性,对App的模块化配置、 Picasso 的JS的管理、ABTest、个人中心入口  管理、鲁班(面向C端的Key/Value配置系统)等业务提供了底层的数据存储和数据获取的支持,为移动 端业务提供了运营配置的基础保障。 同时,为了进一步提升运营效率,我们基于Picasso的多端(Android、iOS、H5、微信小程序)能力, 正在构建移动化的运营能力。这样保障用户无论在什么办公环境都能进行运营配置的管理。 作者简介 国宝,美团点评移动运营平台负责人,Java后端架构师,APPKIT项目发起人,负责APPKIT项目的架构设计。专注于 高性能、高稳定、大并发系统的设计与应用。 小龙,目前为APPKIT项目负责人,主要负责APPKIT项目开发、技术对接和实施、开放平台等。专注于前后端全栈技 术开发,喜欢挑战新的技术和业务问题。

17. CAT 3.0 开源发布,支持多语言客户端及多项性能提升 - 美团技术团队 CAT 3.0 开源发布,支持多语言客户端及多项性能提升 作者: 尤勇 项目背景 CAT(Central Application Tracking),是美团点评基于 Java 开发的一套开源的分布式实时监控系统。 美团点评基础架构部希望在基础存储、高性能通信、大规模在线访问、服务治理、实时监控、容器化及集 群智能调度等领域提供业界领先的、统一的解决方案,CAT 目前在美团点评的产品定位是应用层的统一 监控组件,在中间件(RPC、数据库、缓存、MQ 等)框架中得到广泛应用,为各业务线提供系统的性能 指标、健康状况、实时告警等服务。 本文会对 CAT 的客户端、性能等做详细深入的介绍,前不久我们也发过一篇 CAT 相关的文章,里面详 细介绍了 CAT 客户端和服务端的设计思路,欲知更多细节,欢迎阅读 《深度剖析开源分布式监控 CAT》 产品价值 减少故障发现时间。 降低故障定位成本。 辅助应用程序优化。 技术优势 实时处理:信息的价值会随时间锐减,尤其是在事故处理过程中。 全量数据:全量采集指标数据,便于深度分析故障案例。 高可用:故障的还原与问题定位,需要高可用监控来支撑。 故障容忍:故障不影响业务正常运转、对业务透明。 高吞吐:海量监控数据的收集,需要高吞吐能力做保证。

18. CAT 3.0 开源发布,支持多语言客户端及多项性能提升 - 美团技术团队 可扩展:支持分布式、跨 IDC 部署,横向扩展的监控系统。 使用现状 目前,CAT 已经覆盖了美团点评的外卖、酒旅、出行、金融等核心业务线,几乎已经接入美团点评的所 有核心应用,并在生产环境中大规模地得到使用。 2016 年初至今,CAT 接入的应用增加了400%,机器数增加了 900%,每天处理的消息总量高达 3200 亿,存储消息量近 400TB,高峰期集群 QPS 达 650万/秒。 面对流量的成倍增长,CAT 在通信、计算、存储方面都遇到了前所未有的挑战。整个系统架构也经历了 一系列的升级和改造,包括消息采样聚合、消息存储、业务多维度指标监控、统一告警等等,项目最终稳 定落地。为公司未来几年内业务流量的稳定增长,打下了坚定的基石。 经过 7 年的持续建设,CAT 也在不断发展,我们也希望更好的回馈社区,将 CAT 提供的服务惠及更多 的外部公司。我们今年将对开源版本进行较大的迭代与更新,未来也会持续把公司内部一些比较好的实践 推广出去,欢迎大家跟我们一起共建这个开源社区。 新版特性 CAT 3.0.0 Release Notes  多语言客户端 随着业务的不断发展,很多产品和应用需要使用不同的语言,CAT 多语言客户端需求日益增多,除 Java 客户端外,目前提供了 C/C++、Python、Node.js、Golang 客户端,基本覆盖了主流的开发语言。对于 多语言客户端,核心设计目标是利用 C 客户端提供核心 API 接口作为底层基石,封装其他语言 SDK。 目前支持的主流语言使用指南: Java C/C++  Python  Node.js  Golang 

19. CAT 3.0 开源发布,支持多语言客户端及多项性能提升 - 美团技术团队 性能提升 消息采样聚合 消息采样聚合在客户端应对大流量时起到了至关重要的作用,当采样命中或者内存队列已满时都会经 过采样聚合上报。采样聚合是对消息树拆分归类,利用本地内存做分类统计,将聚合之后的数据进行 上报,减少客户端的消息量以及降低网络开销。 通信协议优化 CAT 客户端与服务端通信协议由自定义文本协议升级为自定义二进制协议,在大规模数据实时处理场 景下性能提升显著。目前服务端同时支持两种版本的通信协议,向下兼容旧版客户端。 测试环境:CentOS 6.5,4C8G 虚拟机 测试结果:新版相比旧版,序列化耗时降低约 3 倍 消息文件存储 新版消息文件存储进行了重新设计,解决旧版本的文件存储索引、数据文件节点过多以及随机 IO 恶化的 问题。 新版消息文件存储为了同时兼顾读写性能,引入了二级索引存储方案,对同一个应用的 IP 节点进行合 并,并且保证一定的顺序存储。下图是索引结构的最小单元,每个索引文件由若干个最小单元组成。每个

20. CAT 3.0 开源发布,支持多语言客户端及多项性能提升 - 美团技术团队 单元分为 4×1024 个桶,第一个桶作为我们的一级索引 Header,存储 IP、消息序列号与分桶的映射信 息。剩余 4×1024 - 1 个桶作为二级索引,存储消息的地址。 新版消息文件存储文件节点数与应用数量成正比,有效减少随机 IO,消息实时存储的性能提升显著。以 下为美团点评内部 CAT 线上环境单机消息存储的数据对比: 未来规划 技术栈升级 拥抱主流技术栈,降低学习和开发成本,使用开源社区主流技术工具(Spring、Mybatis等),建设 下一代开源产品。 产品体验 对产品、交互进行全新设计,提升用户体验。 开源社区建设 产品官网建设、组织技术交流。 更多语言 SDK 关于开源 https://github.com/dianping/cat  自2014年开源以来,Github 收获 7700+ Star,2800+ Forks,被 100+ 公司企业使用,其中不乏携程、 陆金所、猎聘网、平安等业内知 名公司。在每年全球 QCon 大会、全球架构与运维技术峰会等都有持续 的技术输出,受到行业内认可,越来越多的企业伙伴加入了 CAT 的开 源建设工作,为 CAT 的成长贡献 了巨大的力量。

21. CAT 3.0 开源发布,支持多语言客户端及多项性能提升 - 美团技术团队 美团点评基础架构部负责人黄斌强表示,在过去四年中,美团点评在架构中间件领域有比较多的积累沉 淀,很多系统服务都经历过大规模线上业务实际运营的检验。我们在使用业界较多开源产品的同时,也希 望能把积累的技术开源出去,一方面是回馈社区,贡献给整个行业生态;另一方面,让更多感兴趣的开发 工程师也能参与进来,共同加速系统软件的升级与创新。所以,像 CAT 这样的优秀项目,我们将陆续开 源输出并长期持续运营,保证开源软件本身的成熟度、支撑度与社区的活跃度,也欢迎大家给我们提出更 多的宝贵意见和建议。 结语 这是一场没有终点的长跑,我们整个 CAT 项目组将长期有耐心地不断前行。愿同行的朋友积极参与我 们,关注我们,共同打造一款企业级高可用、高可靠的分布式监控中间件产品,共同描绘 CAT 的新未 来! 这次开源仅仅是一个新的起点,如果你对 CAT 新版本有一些看法以及建议,欢迎联系我们: cat@dianping.com or Github issues  招聘信息 美团点评基础架构团队诚招 Java 高级、资深技术专家,Base北京、上海。我们是集团致力于研发公司 级、业界领先基础架构组件的核心团队,涵盖分布式监控、服务治理、高性能通信、消息中间件、基础存 储、容器化、集群调度等技术领域。欢迎有兴趣的同学投送简历到 yong.you@dianping.com。

22. LruCache在美团DSP系统中的应用演进 - 美团技术团队 LruCache在美团DSP系统中的应用演进 作者: 王粲 崔涛 霜霜 背景 DSP系统是互联网广告需求方平台,用于承接媒体流量,投放广告。业务特点是并发度高,平均响应低 (百毫秒)。 为了能够有效提高DSP系统的性能,美团平台引入了一种带有清退机制的缓存结构LruCache(Least Recently Used Cache),在目前的DSP系统中,使用LruCache + 键值存储数据库的机制将远端数据变为 本地缓存数据,不仅能够降低平均获取信息的耗时,而且通过一定的清退机制,也可以维持服务内存占用 在安全区间。 本文将会结合实际应用场景,阐述引入LruCache的原因,并会在高QPS下的挑战与解决方案等方面做详 细深入的介绍,希望能对DSP感兴趣的同学有所启发。 LruCache简介 LruCache采用的缓存算法为LRU(Least Recently Used),即最近最少使用算法。这一算法的核心思想是 当缓存数据达到预设上限后,会优先淘汰近期最少使用的缓存对象。 LruCache内部维护一个双向链表和一个映射表。链表按照使用顺序存储缓存数据,越早使用的数据越靠 近链表尾部,越晚使用的数据越靠近链表头部;映射表通过Key-Value结构,提供高效的查找操作,通过 键值可以判断某一数据是否缓存,如果缓存直接获取缓存数据所属的链表节点,进一步获取缓存数据。 LruCache结构图如下所示,上半部分是双向链表,下半部分是映射表(不一定有序)。双向链表中 value_1所处位置为链表头部,value_N所处位置为链表尾部。 LruCache 初始结构 LruCache读操作,通过键值在映射表中查找缓存数据是否存在。如果数据存在,则将缓存数据所处节点 从链表中当前位置取出,移动到链表头部;如果不存在,则返回查找失败,等待新数据写入。下图为通过 LruCache查找key_2后LruCache结构的变化。

23. LruCache在美团DSP系统中的应用演进 - 美团技术团队 LruCache 查找 LruCache没有达到预设上限情况下的写操作,直接将缓存数据加入到链表头部,同时将缓存数据键值与 缓存数据所处的双链表节点作为键值对插入到映射表中。下图是LruCache预设上限大于N时,将数据M写 入后的数据结构。 LruCache 未达预设上限,添加数据 LruCache达到预设上限情况下的写操作,首先将链表尾部的缓存数据在映射表中的键值对删除,并删除 链表尾部数据,再将新的数据正常写入到缓存中。下图是LruCache预设上限为N时,将数据M写入后的数 据结构。 LruCache 达预设上限,添加数据 线程安全的LruCache在读写操作中,全部使用锁做临界区保护,确保缓存使用是线程安全的。 LruCache在美团DSP系统的应用场景 在美团DSP系统中广泛应用键值存储数据库,例如使用Redis存储广告信息,服务可以通过广告ID获取广 告信息。每次请求都从远端的键值存储数据库中获取广告信息,请求耗时非常长。随着业务发展,QPS呈 现巨大的增长趋势,在这种高并发的应用场景下,将广告信息从远端键值存储数据库中迁移到本地以减少

24. LruCache在美团DSP系统中的应用演进 - 美团技术团队 查询耗时是常见解决方案。另外服务本身的内存占用要稳定在一个安全的区间内。面对持续增长的广告信 息,引入LruCache + 键值存储数据库的机制来达到提高系统性能,维持内存占用安全、稳定的目标。 LruCache + Redis机制的应用演进 在实际应用中,LruCache + Redis机制实践分别经历了引入LruCache、LruCache增加时效清退机制、 HashLruCache满足高QPS应用场景以及零拷贝机制四个阶段。各阶段的测试机器是16核16G机器。 演进一:引入LruCache提高美团DSP系统性能 在较低QPS环境下,直接请求Redis获取广告信息,可以满足场景需求。但是随着单机QPS的增加,直接 请求Redis获取广告信息,耗时也会增加,无法满足业务场景的需求。 引入LruCache,将远端存放于Redis的信息本地化存储。LruCache可以预设缓存上限,这个上限可以根 据服务所在机器内存与服务本身内存占用来确定,确保增加LruCache后,服务本身内存占用在安全范围 内;同时可以根据查询操作统计缓存数据在实际使用中的命中率。 下图是增加LruCache结构前后,且增加LruCache后命中率高于95%的情况下,针对持续增长的QPS得 出的数据获取平均耗时(ms)对比图: 引入LruCache前后平均耗时 根据平均耗时图显示可以得出结论: 1. QPS高于250后,直接请求Redis获取数据的平均耗时达到10ms以上,完全无法满足使用的需求。 2. 增加LruCache结构后,耗时下降一个量级。从平均耗时角度看,QPS不高于500的情况下,耗时低于2ms。 下图是增加LruCache结构前后,且增加LruCache后命中率高于95%的情况下,针对持续增长的QPS得 出的数据获取Top999耗时(ms)对比图:

25. LruCache在美团DSP系统中的应用演进 - 美团技术团队 引入LruCache前后TP999耗时 根据Top999耗时图可以得出以下结论: 1. 增加LruCache结构后,Top999耗时比平均耗时增长一个数量级。 2. 即使是较低的QPS下,使用LruCache结构的Top999耗时也是比较高的。 引入LruCache结构,在实际使用中,在一定的QPS范围内,确实可以有效减少数据获取的耗时。但是 QPS超出一定范围后,平均耗时和Top999耗时都很高。所以LruCache在更高的QPS下性能还需要进一 步优化。 演进二:LruCache增加时效清退机制 在业务场景中,Redis中的广告数据有可能做修改。服务本身作为数据的使用方,无法感知到数据源的变 化。当缓存的命中率较高或者部分数据在较长时间内多次命中,可能出现数据失效的情况。即数据源发生 了变化,但服务无法及时更新数据。针对这一业务场景,增加了时效清退机制。 时效清退机制的组成部分有三点:设置缓存数据过期时间,缓存数据单元增加时间戳以及查询中的时效性 判断。缓存数据单元将数据进入LruCache的时间戳与数据一起缓存下来。缓存过期时间表示缓存单元缓 存的时间上限。查询中的时效性判断表示查询时的时间戳与缓存时间戳的差值超过缓存过期时间,则强制 将此数据清空,重新请求Redis获取数据做缓存。 在查询中做时效性判断可以最低程度的减少时效判断对服务的中断。当LruCache预设上限较低时,定期 做全量数据清理对于服务本身影响较小。但如果LruCache的预设上限非常高,则一次全量数据清理耗时 可能达到秒级甚至分钟级,将严重阻断服务本身的运行。所以将时效性判断加入到查询中,只对单一的缓 存单元做时效性判断,在服务性能和数据有效性之间做了折中,满足业务需求。 演进三:高QPS下HashLruCache的应用 LruCache引入美团DSP系统后,在一段时间内较好地支持了业务的发展。随着业务的迭代,单机QPS持 续上升。在更高QPS下,LruCache的查询耗时有了明显的提高,逐渐无法适应低平响的业务场景。在这 种情况下,引入了HashLruCache机制以解决这个问题。 LruCache在高QPS下的耗时增加原因分析:

26. LruCache在美团DSP系统中的应用演进 - 美团技术团队 线程安全的LruCache中有锁的存在。每次读写操作之前都有加锁操作,完成读写操作之后还有解锁操 作。在低QPS下,锁竞争的耗时基本可以忽略;但是在高QPS下,大量的时间消耗在了等待锁的操作 上,导致耗时增长。 HashLruCache适应高QPS场景: 针对大量的同步等待操作导致耗时增加的情况,解决方案就是尽量减小临界区。引入Hash机制,对全量 数据做分片处理,在原有LruCache的基础上形成HashLruCache,以降低查询耗时。 HashLruCache引入某种哈希算法,将缓存数据分散到N个LruCache上。最简单的哈希算法即使用取模算 法,将广告信息按照其ID取模,分散到N个LruCache上。查询时也按照相同的哈希算法,先获取数据可 能存在的分片,然后再去对应的分片上查询数据。这样可以增加LruCache的读写操作的并行度,减小同 步等待的耗时。 下图是使用16分片的HashLruCache结构前后,且命中率高于95%的情况下,针对持续增长的QPS得出的 数据获取平均耗时(ms)对比图: 引入HashLruCache前后平均耗时 根据平均耗时图可以得出以下结论: 1. 使用HashLruCache后,平均耗时减少将近一半,效果比较明显。 2. 对比不使用HashLruCache的平均耗时可以发现,使用HashLruCache的平均耗时对QPS的增长不敏感,没有明显增 长。 下图是使用16分片的HashLruCache结构前后,且命中率高于95%的情况下,针对持续增长的QPS得出的 数据获取Top999耗时(ms)对比图:

27. LruCache在美团DSP系统中的应用演进 - 美团技术团队 引入HashLruCache前后TP999耗时 根据Top999耗时图可以得出以下结论: 1. 使用HashLruCache后,Top999耗时减少为未使用时的三分之一左右,效果非常明显。 2. 使用HashLruCache的Top999耗时随QPS增长明显比不使用的情况慢,相对来说对QPS的增长敏感度更低。 引入HashLruCache结构后,在实际使用中,平均耗时和Top999耗时都有非常明显的下降,效果非常显 著。 HashLruCache分片数量确定: 根据以上分析,进一步提高HashLruCache性能的一个方法是确定最合理的分片数量,增加足够的并行 度,减少同步等待消耗。所以分片数量可以与CPU数量一致。由于超线程技术的使用,可以将分片数量 进一步提高,增加并行性。 下图是使用HashLruCache机制后,命中率高于95%,不同分片数量在不同QPS下得出的数据获取平均耗 时(ms)对比图: HashLruCache分片数量耗时 平均耗时图显示,在较高的QPS下,平均耗时并没有随着分片数量的增加而有明显的减少,基本维持稳定 的状态。

28. LruCache在美团DSP系统中的应用演进 - 美团技术团队 下图是使用HashLruCache机制后,命中率高于95%,不同分片数量在不同QPS下得出的数据获取 Top999耗时(ms)对比图: HashLruCache分片TP99耗时 Top999耗时图显示,QPS为750时,分片数量从8增长到16再增长到24时,Top999耗时有一定的下降, 并不显著;QPS为1000时,分片数量从8增长到16有明显下降,但是从16增长到24时,基本维持了稳定状 态。明显与实际使用的机器CPU数量有较强的相关性。 HashLruCache机制在实际使用中,可以根据机器性能并结合实际场景的QPS来调节分片数量,以达到最 好的性能。 演进四:零拷贝机制 线程安全的LruCache内部维护一套数据。对外提供数据时,将对应的数据完整拷贝一份提供给调用方使 用。如果存放结构简单的数据,拷贝操作的代价非常小,这一机制不会成为性能瓶颈。但是美团DSP系统 的应用场景中,LruCache中存放的数据结构非常复杂,单次的拷贝操作代价很大,导致这一机制变成了 性能瓶颈。 理想的情况是LruCache对外仅仅提供数据地址,即数据指针。使用方在业务需要使用的地方通过数据指 针获取数据。这样可以将复杂的数据拷贝操作变为简单的地址拷贝,大量减少拷贝操作的性能消耗,即数 据的零拷贝机制。直接的零拷贝机制存在安全隐患,即由于LruCache中的时效清退机制,可能会出现某 一数据已经过期被删除,但是使用方仍然通过持有失效的数据指针来获取该数据。 进一步分析可以确定,以上问题的核心是存放于LruCache的数据生命周期对于使用方不透明。解决这一 问题的方案是为LruCache中存放的数据添加原子变量的引用计数。使用原子变量不仅确保了引用计数的 线程安全,使得各个线程读取的引用计数一致,同时保证了并发状态最小的同步性能开销。不论是 LruCache中还是使用方,每次获取数据指针时,即将引用计数加1;同理,不再持有数据指针时,引用计 数减1。当引用计数为0时,说明数据没有被任何使用方使用,且数据已经过期从LruCache中被删除。这 时删除数据的操作是安全的。 下图是使零拷贝机制后,命中率高于95%,不同QPS下得出的数据获取平均耗时(ms)对比图:

29. LruCache在美团DSP系统中的应用演进 - 美团技术团队 HashLruCache分片数量耗时 平均耗时图显示,使用零拷贝机制后,平均耗时下降幅度超过60%,效果非常显著。 下图是使零拷贝机制后,命中率高于95%,不同QPS下得出的数据获取Top999耗时(ms)对比图: HashLruCache分片数量耗时 根据Top999耗时图可以得出以下结论: 1. 使用零拷贝后,Top999耗时降幅将近50%,效果非常明显。 2. 在高QPS下,使用零拷贝机制的Top999耗时随QPS增长明显比不使用的情况慢,相对来说对QPS的增长敏感度更 低。 引入零拷贝机制后,通过拷贝指针替换拷贝数据,大量降低了获取复杂业务数据的耗时,同时将临界区减 小到最小。线程安全的原子变量自增与自减操作,目前在多个基础库中都有实现,例如C++11就提供了内 置的整型原子变量,实现线程安全的自增与自减操作。 在HashLruCache中引入零拷贝机制,可以进一步有效降低平均耗时和Top999耗时,且在高QPS下对于 稳定Top999耗时有非常好的效果。 总结 下图是一系列优化措施前后,命中率高于95%,不同QPS下得出的数据获取平均耗时(ms)对比图: