大众点评账号业务高可用进阶之路

引言

在任何一家互联网公司,不管其主营业务是什么,都会有一套自己的账号体系。账号既是公司所有业务发展留下的最宝贵资产,它可以用来衡量业务指标,例如日活、月活、留存等,同时也给不同业务线提供了大量潜在用户,业务可以基于账号来做用户画像,制定各自的发展路径。因此,账号服务的重要性不言而喻,同时美团业务飞速发展,对账号业务的可用性要求也越来越高。本文将分享一些我们在高可用探索中的实践。

衡量一个系统的可用性有两个指标:

  1. MTBF (Mean Time Between Failure) 即平均多长时间不出故障;
  2. MTTR (Mean Time To Recovery) 即出故障后的平均恢复时间。通过这两个指标可以计算出可用性,也就是我们大家比较熟悉的“几个9”。

可用性公式

因此提升系统的可用性,就得从这两个指标入手,要么降低故障恢复的时间,要么延长不出故障的时间。

1. 业务监控

要降低故障恢复的时间,首先得尽早的发现故障,然后才能解决故障,这些故障包括系统内和系统外的,这就需要依赖业务监控系统。

业务监控不同于其他监控系统,业务监控关注的是各个业务指标是否正常,比如账号的登录曲线。大众点评登录入口有很多,从终端上分有App、PC、M站,从登录类型上分有密码登录、快捷登录、第三方登录(微信/QQ/微博)、小程序登录等。需要监控的维度有登录总数、成功数、失败分类、用户地区、App版本号、浏览器类型、登录来源Referer、服务所在机房等等。业务监控最能从直观上告诉我们系统的运行状况。

由于业务监控的维度很多很杂,有时还要增加新的监控维度,并且告警分析需要频繁聚合不同维度的数据,因此我们采用ElasticSearch作为日志存储。整体架构如下图:

每条监控都会根据过去的业务曲线计算出一条基线(见下图),用来跟当前数据做对比,超出设定的阈值后就会触发告警。

监控曲线图

每次收到告警,我们都要去找出背后的原因,如果是流量涨了,是有活动了还是被刷了?如果流量跌了,是日志延时了还是服务出问题了?另外值得重视的是告警的频次,如果告警太多就会稀释大家的警惕性。我们曾经踩过一次坑,因为告警太多就把告警关了,结果就在关告警的这段时间业务出问题了,我们没有及时发现。为了提高每条告警的定位速度,我们在每条告警后面加上维度分析。如下图(非真实数据),告警里直接给出分析结果。

监控告警分析图

其实业务监控也从侧面反映出一个系统的可用性,所谓服务未动,监控先行。

2. 柔性可用

柔性可用的目的是延长不出故障的时间,当业务依赖的下游服务出故障时不影响自身的核心功能或服务。账号对上层业务提供的鉴权和查询服务即核心服务,这些服务的QPS非常高,业务方对它们的可用性要求也很高,别说是服务故障,就连任何一点抖动都是不能接受的。对此我们先从整体架构上把服务拆分,其次在服务内对下游依赖做资源隔离,都尽可能的缩小故障发生时的影响范围。

另外对非关键路径上的服务故障做了降级。例如账号的一个查询服务依赖Redis,当Redis抖动的时候服务的可用性也随之降低,我们通过公司内部另外一套缓存中间件Cellar来做Redis的备用存储,当检测到Redis已经非常不可用时就切到Cellar上。通过开源组件Hystrix或者我们公司自研的中间件Rhino就能非常方便地解决这类问题,其原理是根据最近一个时间窗口内的失败率来预测下一个请求需不需要快速失败,从而自动降级,这些步骤都能在毫秒级完成,相比人工干预的情况提升几个数量级,因此系统的可用性也会大幅提高。下图是优化前后的对比图,可以非常明显的看到,系统的容错能力提升了,TP999也能控制在合理范围内。

性能对比图前

性能对比图后

对于关键路径上的服务故障我们可以减少其影响的用户数。比如手机快捷登录流程里的某个关键服务挂了,我们可以在返回的失败文案上做优化,并且在登录入口挂小黄条提示,让用户主动去其他登录途径,这样对于那些设置过密码或者绑定了第三方的用户还有其他选择。

具体的做法是我们在每个登录入口都关联了一个计数器,一旦其中的关键节点不可用,就会在受影响的计数器上加1,如果节点恢复,则会减1,每个计数器还分别对应一个标志位,当计数器大于0时,标志位为1,否则标志位为0。我们可以根据当前标志位的值得知登录入口的可用情况,从而在登录页展示不同的提示文案,这些提示文案一共有2^5=32种。

登录降级流程图

下图是我们在做故障模拟时的降级提示文案:

3. 异地多活

除了柔性可用,还有一种思路可以来延长不出故障的时间,那就是做冗余,冗余的越多,系统的故障率就越低,并且是呈指数级降低。不管是机房故障,还是存储故障,甚至是网络故障,都能依赖冗余去解决,比如数据库可以通过增加从库的方式做冗余,服务层可以通过分布式架构做冗余,但是冗余也会带来新的问题,比如成本翻倍,复杂性增加,这就要衡量投入产出比。

目前美团的数据中心机房主要在北京上海,各个业务都直接或间接的依赖账号服务,尽管公司内已有北上专线,但因为专线故障或抖动引发的账号服务不可用,间接导致的业务损失也不容忽视,我们就开始考虑做跨城的异地冗余,即异地多活。

3.1 方案设计

首先我们调研了业界比较成熟的做法,主流思路是分set化,优点是非常利于扩展,缺点是只能按一个维度划分。比如按用户ID取模划分set,其他的像手机号和邮箱的维度就要做出妥协,尤其是这些维度还有唯一性要求,这就使得数据同步或者修改都增加了复杂度,而且极易出错,给后续维护带来困难。考虑到账号读多写少的特性(读写比是350:1),我们采用了一主多从的数据库部署方案,优先解决读多活的问题。

Redis如果也用一主多从的模式可行吗?答案是不行,因为Redis主从同步机制会优先尝试增量同步,当增量同步不成功时,再去尝试全量同步,一旦专线发生抖动就会把主库拖垮,并进一步阻塞专线,形成“雪崩效应”。因此两地的Redis只能是双主模式,但是这种架构有一个问题,就是我们得自己去解决数据同步的问题,除了保证数据不丢,还要保证数据一致。

另外从用户进来的每一层路由都要是就近的,因此DNS需要开启智能解析,SLB要开启同城策略,RPC已默认就近访问。

总体上账号的异地多活遵循以下三个原则:

  1. 北上任何一地故障,另一地都可提供完整服务。
  2. 北上两地同时对外提供服务,确保服务随时可用。
  3. 两地服务都遵循BASE原则,确保数据最终一致。

最终设计方案如下:

异地多活架构图

3.2 数据同步

首先要保证数据在传输的过程中不能丢,因此需要一个可靠接收数据的地方,于是我们采用了公司内部的MQ平台Mafka(类Kafka)做数据中转站。可是消息在经过Mafka传递之后可能是乱序的,这导致对同一个key的一串操作序列可能导致不一致的结果,这是不可忍受的。但Mafka只是不保证全局有序,在单个partition内却是有序的,于是我们只要对每个key做一遍一致性散列算法对应一个partitionId,这样就能保证每个key的操作是有序的。

但仅仅有序还不够,两地的并发写仍然会造成数据的不一致。这里涉及到分布式数据的一致性问题,业界有两种普遍的认知,一种是Paxos协议,一种是Raft协议,我们吸取了对实现更为友好的Raft协议,它主张有一个主节点,其余是从节点,并且在主节点不可用时,从节点可晋升为主节点。简单来说就是把这些节点排个序,当写入有冲突时,以排在最前面的那个节点为准,其余节点都去follow那个主节点的值。在技术实现上,我们设计出一个版本号(见下图),实际上是一个long型整数,其中数据源大小即表示节点的顺序,把版本号存入value里面,当两个写入发生冲突的时候只要比较这个版本号的大小即可,版本号大的覆盖小的,这样能保证写冲突时的数据一致性。

写并发时数据同步过程如下图:

这种同步方式的好处显而易见,可以适用于所有的Redis操作且能保证数据的最终一致性。但这也有一些弊端,由于多存了版本号导致Redis存储会增加,另外在该机制下两地的数据其实是全量同步的,这对于那些仅用做缓存的存储来说是非常浪费资源的,因为缓存有数据库可以回源。而账号服务几乎一半的Redis存储都是缓存,因此我们需要对缓存同步做优化。

账号服务的缓存加载与更新模式如下图:

我们优化的方向是在缓存加载时不同步,只有在数据库有更新时才去同步。但是数据更新这个流程里不能再使用delete操作,这样做有可能使缓存出现脏数据,比如下面这个例子:

我们对这个问题的解决办法是用set(若key不存在则添加,否则覆盖)代替delete,而缓存的加载用add(若key不存在则添加,否则不修改),这样能保证缓存更新时的强一致性却不需要增加额外存储。考虑到账号修改的入口比较多,我们希望缓存更新的逻辑能拎出来单独处理减少耦合,最后发现公司内部数据同步组件Databus非常适用于该场景,其主要功能是把数据库的变更日志以消息的形式发出来。于是优化后的缓存模式如下图:

从理论变为工程实现的时候还有些需要注意的地方,比如同步消息没发出去、数据收到后写失败了。因此我们还需要一个方法来检测数据不一致的数量,为了做到这点,我们新建了一个定时任务去scan两地的数据做对比统计,如果发现有不一致的还能及时修复掉。

项目上线后,我们也取得一些成果,首先性能提升非常明显,异地的调用平均耗时和TP99、TP999均至少下降80%,并且在一次线上专线故障期间,账号读服务对外的可用性并没有受影响,避免了更大范围的损失。

总结

服务的高可用需要持续性的投入与维护,比如我们会每月做一次容灾演练。高可用也不止体现在某一两个重点项目上,更多的体现在每个业务开发同学的日常工作里。任何一个小Bug都可能引起一次大的故障,让你前期所有的努力都付之东流,因此我们的每一行代码,每一个方案,每一次线上改动都应该是仔细推敲过的。高可用应该成为一种思维方式。最后希望我们能在服务高可用的道路上越走越远。

团队简介

账号团队拥有一群朝气蓬勃的成员:堂堂、德鑫、杨正、可可、徐升、艳豪,虽然他们之中有些刚毕业不久,但技术上都锐意进取,在讨论技术方案时观点鲜明,大家都充分地享受着思想碰撞的火花,这个年轻的团队在一起推进着高可用项目的进行,共同撑起了账号服务的平稳运行及业务发展。

招聘信息

  • 如果你觉得我们的高可用仍有提升空间,欢迎来大众点评基础平台研发组。
  • 如果你想更深入学习高可用的技术细节,欢迎来大众点评基础平台研发组。
  • 如果你想遇到一群志同道合的技术开发,欢迎来大众点评基础平台研发组。
  • 简历传送门:tangtang.sha#dianping.com。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/478818.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 493. 翻转对(归并排序)

1. 题目 给定一个数组 nums &#xff0c;如果 i < j 且 nums[i] > 2*nums[j] 我们就将 (i, j) 称作一个重要翻转对。 你需要返回给定数组中的重要翻转对的数量。 输入: [1,3,2,3,1] 输出: 2输入: [2,4,3,5,1] 输出: 3来源&#xff1a;力扣&#xff08;LeetCode&#x…

论文浅尝 - ICML2020 | 通过关系图上的贝叶斯元学习进行少样本关系提取

论文笔记整理&#xff1a;申时荣&#xff0c;东南大学博士生。来源&#xff1a;ICML 2020链接&#xff1a;http://arxiv.org/abs/2007.02387一、介绍本文研究了少样本关系提取&#xff0c;旨在通过训练每个关系少量带有标记示例的句子来预测句子中一对实体的关系。为了更有效地…

美团外卖客户端高可用建设体系

背景 美团外卖从2013年11月开始起步&#xff0c;经过数年的高速发展&#xff0c;一直在不断地刷新着记录。2018年5月19日&#xff0c;日订单量峰值突破2000万单&#xff0c;已经成为全球规模最大的外卖平台。业务的快速发展对系统稳定性提出了更高的要求&#xff0c;如何为线上…

我哭了,工业界AI项目落地有多难?

文 | 皮特潘源 | CVer人工智能是近几年最火热的技术名词&#xff0c;如果不谈人工智能相当于落伍&#xff0c;但当真正进入人工智能领域时才发现&#xff0c;一开始以为“拦路虎”是算法&#xff0c;后面发现落地是一个巨大的难题。本文从作者的经历和经验教训展开&#xff0c;…

LeetCode 646. 最长数对链(区间 贪心)

1. 题目 给出 n 个数对。 在每一个数对中&#xff0c;第一个数字总是比第二个数字小。 现在&#xff0c;我们定义一种跟随关系&#xff0c;当且仅当 b < c 时&#xff0c;数对(c, d) 才可以跟在 (a, b) 后面。我们用这种形式来构造一个数对链。 给定一个对数集合&#xf…

以太网和路由设置,内网和外网同时上

第一步&#xff0c;查看自己内网的地址&#xff0c;网络与internet设置&#xff0c;更改适配器选项&#xff0c;出现下面的页面 点击内网&#xff0c;右击WLan&#xff0c;点击状态 点击详细信息&#xff1a; 记录网关信息&#xff1a; 第二步&#xff1a;查找路由器设置 …

论文浅尝 - AAAI2020 | 通过知识库问答改善知识感知对话生成

论文笔记整理&#xff1a;胡楠&#xff0c;东南大学博士。来源&#xff1a;AAAI 2020动机现在的将外部知识整合到对话系统中的研究仍然存在一定缺陷。首先&#xff0c;先前的方法难以处理某些语句的主语和关系&#xff0c;比如当语句中的相关实体彼此相距较远时。其次&#xff…

互联网企业数据安全体系建设

一、背景 Facebook数据泄露事件一度成为互联网行业的焦点&#xff0c;几百亿美元市值瞬间蒸发&#xff0c;这个代价足以在地球上养活一支绝对庞大的安全团队&#xff0c;甚至可以直接收购几家规模比较大的安全公司了。 虽然媒体上发表了很多谴责的言论&#xff0c;但实事求是地…

NLP研究者必备的语言学书籍!

文 | Serena Gao知乎首先&#xff0c;做nlp不一定要很懂语言学&#xff0c;也不一定要跟语言学扯上关系。nlp可以仅是data mining&#xff0c;features engineering, 也的确有很多work目前在用文本或者对话做为数据集&#xff0c;然后用统计学方法实现目的&#xff0c;比如deep…

LeetCode 334. 递增的三元子序列

1. 题目 给定一个未排序的数组&#xff0c;判断这个数组中是否存在长度为 3 的递增子序列。 数学表达式如下: 如果存在这样的 i, j, k, 且满足 0 ≤ i < j < k ≤ n-1&#xff0c; 使得 arr[i] < arr[j] < arr[k] &#xff0c;返回 true ; 否则返回 false 。 说…

论文小综 | Neuro-Symbolic Reasoning in NLP

本文作者&#xff1a;邓淑敏&#xff0c;浙江大学在读博士&#xff0c;研究方向为低资源条件下知识图谱自动化构建关键技术研究。深度学习的高速发展使得模型的表达能力逐步完善&#xff0c;在一些感知任务&#xff08;例如动作识别和事件检测&#xff09;上取得了显著成果。但…

实时数据产品实践——美团大交通战场沙盘

背景 大数据时代&#xff0c;数据的重要性不言而喻&#xff0c;尤其对于互联网公司&#xff0c;随着业务的快速变化&#xff0c;商业模式的不断创新、用户体验个性化、实时化需求日益突出&#xff0c;海量数据实时处理在商业方面的需求越来越大。如何通过数据快速分析出用户的行…

谁才是Transformer家族中的最强王者?谷歌告诉你答案

文 | Sherry自从17年Attention is all you need发出&#xff0c;继而18年BERT刷新各大榜单&#xff0c;大型预训练Transformer似乎已经成为自然语言处理的标准基准模型&#xff0c;甚至进一步渗透到图像领域。各路大神基于Transformer提出了海量改进方法。这些改变是否对大多数…

LeetCode 652. 寻找重复的子树(DFS)

1. 题目 给定一棵二叉树&#xff0c;返回所有重复的子树。对于同一类的重复子树&#xff0c;你只需要返回其中任意一棵的根结点即可。 两棵树重复是指它们具有相同的结构以及相同的结点值。 示例 1&#xff1a;1/ \2 3/ / \4 2 4/4 下面是两个重复的子树&#xff1a…

论文浅尝 - CIKM2020 | Relation Reflection Entity Alignment

论文笔记整理&#xff1a;谭亦鸣&#xff0c;东南大学博士生。来源&#xff1a;CIKM 2020链接&#xff1a;https://arxiv.org/pdf/2008.07962.pdf研究背景与任务描述:实体对齐旨在基于已有对齐实体标注的情况下&#xff0c;确定不同KG中未知的对等实体&#xff0c;其本质是mult…

SQL解析在美团的应用

数据库作为核心的基础组件&#xff0c;是需要重点保护的对象。任何一个线上的不慎操作&#xff0c;都有可能给数据库带来严重的故障&#xff0c;从而给业务造成巨大的损失。为了避免这种损失&#xff0c;一般会在管理上下功夫。比如为研发人员制定数据库开发规范&#xff1b;新…

无内鬼,来点ICML/ACL审稿人笑话

文 | Sheryc_王苏最近&#xff0c;如果你的小伙伴突然没时间陪你出来玩了&#xff0c;请不要担心&#xff0c;ta可能正在与ICML/IJCAI/ACL的审稿人斗智斗勇。过去的一周里&#xff0c;机器学习顶会ICML、人工智能顶会IJCAI和NLP顶会ACL扎堆放出审稿人意见&#xff0c;有人欢喜有…

Docx:docx.opc.exceptions.PackageNotFoundError: Package not found at

Docx:docx.opc.exceptions.PackageNotFoundError: Package not found at&#xff1a;https://blog.csdn.net/python__reported/article/details/106318330 Docx:docx.opc.exceptions.PackageNotFoundError: Package not found at 一、报错内容二、解决方法 一、报错内容 报错&a…

LeetCode 148. 排序链表(归并排序、快速排序)

文章目录1. 题目2. 解题2.1 归并排序2.2 快速排序1. 题目 在 O(n log n) 时间复杂度和常数级空间复杂度下&#xff0c;对链表进行排序。 示例 1:输入: 4->2->1->3 输出: 1->2->3->4 示例 2:输入: -1->5->3->4->0 输出: -1->0->3->4-&…

论文浅尝 | 基于对抗学习的弱监督知识图谱对齐

论文笔记整理&#xff1a;郭凌冰&#xff0c;浙江大学研究助理&#xff0c;研究方向为知识图谱的表示学习。绝大部分现有的知识图谱对齐方法都要求足够的已对齐三元组作为监督数据&#xff0c;但在现实世界中&#xff0c;获取大量的对齐三元组的代价十分高昂。本文提出一种同时…