亿级流量挑战下的高可用架构设计与实践——携程门票秒杀系统的设计与实践

如何获得讲师PPT:

扫码关注公众号,后台回复「Q418」即可获得讲师PPT哟~

还能一键订阅后续精彩活动内容~

走出故障迷局的三重奏:逃生、复盘和推演

Q&A环节答疑:

1、这些都要做页面静态化吧?好奇是用ssr还是无头?

我们现在 APP 端的大部分场景下都是静态页面,访问远程接口。我们也有 SSR 场景,与 H5 场景类似。在秒杀时,可能会关掉类似这种场景,但这种情况非常少,以前有过。

 

2、库存扣减 扣减 扣减 Redis成功后写入队列异步写DB,接口响应库存扣减成功是以DB扣减成功为准的吗? 还是Redis扣减成功就算成功?

两个子问题:

(1)这里的队列是本地内存队列还是持久化存储队列(kafka),如果是持久化存储队列写入时存在网络io失败了咋处理的?

(2)如果持久化存储队列这里的队列消费程序是在web应用里面还是说单独部署了1个队列消费程序来处理的,希望把整个异步队列写入和消费了解详细一点

Redis 扣减使用INCRBY原子操作(统一在Master上进行),如果Redis扣减成功,但消息发送失败了,对用户来说是失败,发送失败时会回补Redis中已经扣减成功的库存,如果Redis库存补充失败了(可监控), 最终会出现Redis库存扣了,但是下单没有成功,导致少买。

设计原则:
由于存在多个中间件的数据一致性,保障的所有中间件的一致性成本较高,这个要根据实际情况来设计。门票属于不可超资源,这里的秒杀场景的降级原则是“可以少买不能超买”,所以部分失败的时候对用户返回失败,系统尝试补偿,补偿不成功的监控告警人工介入,实际从监控告警来看暂时没有遇到这种场景。假设出现这种情况,补偿也可以做成自动化的,在一段时间内重试多次,多次不成功的最后再告警出来。

3、如何处理的因为主从延迟可能导致的超卖?主节点库存-1,但是从节点还没有同步,此时主节点发生故障,从节点数据不准确。

我知道这个场景下我们现在确实还未处理。因为目前有两个场景,这个场景有可能存在,但就现状而言,若出现此场景,可能导致客户下单失败。从携程的 redis 高可用性来讲,其可用性非常高,目前好几年都未考虑切换这类问题。加上秒杀场景,此场景概率非常小,暂时未考虑解决此类问题。若一定要解决,因这种场景很小,真正出现问题时,可能导致定前整个交易不可用。例如切换场景,那一瞬间交易场景可能会有性能抖动,但切换过程比较短暂,降级时用户可能会访问下单失败或排队提示话术,切换完后虽有短暂不可用,但会有提示话术来处理以面对用户。

4、(缓存大key)库存key不适用这个,怎么解决?预热分段热点key?

库存缓存搭配时,库存 K 基本不会出现在缓存大坑中。缓存大坑一般是某个整个接口的响应对象或一些产品描述写入特别大的情况。对于此类产品会进行拆分,库存较为结构化,比如一个商品对应一个库存,对于携程门票产品,可能分日期、分日历,一天一个库存或本月库存,不会出现大 K 的场景。
预热分段热点方面,有两种场景会处理热点问题。一是通过访问频次过高,将其识别并升级到本地缓存;二是对于已知的热点,将对应的 K 加到配置中变成本地缓存。目前没有针对分段进行一些操作的保证。

5、在解决 Redis 热点问题时,采用将热 key 放入本地缓存的机制,怎么确保本地缓存与 Redis 缓存的数据一致性?

一致性方面,放入本地缓存的信息可以理解为一致性要求不高的内容,比如产品名称或商品详情等信息。在秒杀场景下,即使发生变更,从后台变更到前端售卖要求在十几秒甚至一分钟内生效即可。秒杀场景下,放入本地缓存的时间很短,可能只放十秒左右。这十秒钟能大大减少秒杀开始瞬间秒级甚至毫秒级对 redis 的访问热点压力,解决前十秒或前几十秒的问题。缓存时间短,也不会影响整体业务感知的一致性效果。

6、如果遇到订单成功,但供应商出单失败,只能事后退单?

之前存在我们的库存与供应商库存未对齐的情况,可能出现我们售卖但供应商那边下载失败的问题。针对这种场景,一是确保库存对齐,二是若供应商无法确认,下单后处于待确认状态,在很短时间内(如两分钟或几分钟)通过接口让供应商确认订单,若确认失败会产生下单失败的问题,这种场景较少,需提前锁定库存。

7、针对海外用户访问性能慢的问题,你们是如何实现数据的本地化部署?是否有考虑使用CDN或边缘计算来进一步减少延迟?

海外访问慢的问题,最初有两种方案,一种是部分海外部署,通过缓存方式解决会员延时问题。目前从携程整体国际化战略来看,已将与信安相关及用户相关信息整体部署在海外,可理解为海外机房与国内机房类似,只是数据存储有所不同,以符合海外信息安全标准。

8、自定义限流没听明白,啥叫能力,机器资源吗?

自定义限流在我们的服务即接口微服务中,常见微服务可能采用应用维度或接口维度限流,但其力度较粗。由于我们每一套预定流程支持秒杀和非秒杀场景,若针对限流可能影响营销正常售卖,所以我们按照商品维度做了限流,每个商品有对应自己的资源池限流池。这样在商品秒杀场景下,达到其限流池时不会影响大盘即整个接口的整个应用承载能力。例如单机承载能力上限假设为 100QPS,若不针对接口限定,在秒杀瞬间可能将单机打满,此时会影响非秒杀正常资源预定。因提前预估资源可能存在偏差,如认为十万人可能会来十五万人,此时扩容机器来不及,会有一到两分钟延时。所以对单机、单接口、单商品维度做对应限流。

9、两级缓存之间数据是怎么保证一致性的?

本地缓存时效性较短,可能只有十多秒钟,但对于商品信息的这种延时,业务端能接受,只要保障在一分钟之内后台修改前端生效即可。

10、对于消息监听的聚合处理,具体怎么做的来避免聚合过程中出现数据丢失?如果聚合过程中出现性能瓶颈,有哪些具体的优化策略?

关于消息的监听和聚合处理以避免数据丢失,有多种方案。在当前场景下,一种是针对聚合直接通过 redis 的 Key 去重,即发过来消费时写到里面,若存在则不写,十秒钟过期;还有一种是将消息直接写入本地队列,队列每隔一定时间去消费一次,这也是一种聚合方式。针对 redis 的聚合方式不存在丢失情况,而对于本单机的聚合,在发生 GC 或重启时可能会丢失,这种丢失可能会有一些影响,在某些对时效性要求不高、一致性要求也不高的场景下,会采用这种方式并进行一些处理。

11、商品库存没有sku的概念吗?库存放在redis里,扣减库存不存在事务问题吗?

现在整个库存已细化到具体的库存单元,一个库存单元可能对应一个具体库存,可能是总库存或日库存。放入库存时按照库存类型,要么放总的,要么放每一天的。使用时,如门票场景,不管是总减总库存还是按日期使用,若按分签,客户对应那一天的库存即可。扣减库存时会有事务问题,除扣减总库存数量外,还需插入一条扣减明细,用于后续追溯整个扣减过程。扣减这两个操作,即更新和插入扣减明细在一个事务中,而扣减实际是异步的。

12、对于 API 性能监控,具体监控哪些指标能够更准确地反映系统的性能问题?如何根据这些指标进行性能优化?

这个问题较大,抽取几个重点说明。在开发过程中,平时遇到问题最多的可能是 API 性能变慢。性能变慢不一定有风险隐患,比如从 100 毫秒变为 120 毫秒可能是因上了新业务新功能。保障系统可用性分为两类,一是针对接口性能,如 KPS 性能、平均耗时、接口 95 线等做定期指标采集,每周采集核心接口性能指标,若有变慢则分析原因并优化,使其回到以前水平。二是隐患相关问题,若接口性能在正常水平如 100 毫秒但偶尔波动为 1 秒或 2 秒,需重点关注分析波动原因,对于导致性能波动的子指标如慢查询、线程波动、redis 的大 K 和热 K 等分成多个运行时子指标,与 API 系统一样做采集监控,每周在周会或 review 系统健康状态时关注优化,识别出有明显风险的隐患并定期治理,使其成为日常工作。稳定性不能仅靠压测时发现风险,要把常见问题总结出的可能导致问题的点监控起来定期优化。

13、海外项目代码和国内是一套代码吗,配置隔离的方式?基础设施的SDK和平台是一套还是两套代码?

我们目前都是一套代码,部署时携程国内和海外虽为不同 group 和机房,国内可能多机房,海外也可能多机房,但各自进行对应的 DR 部署,若一个地方出现故障,另一个地方能承载对应流量。基础设施目前也是一套,会有一些针对环境的适配。

14、优化左移有什么业务场景的例子吗?设计阶段也不好预测上线后发生的问题啊?如何预测风险的?

优化左移常见情况如线程池波动,个别团队可能对线程监控不足。如单核线程在 100 左右为健康水平,但有些应用每周波动大,可能因突增流量或业务代码中执行某段代码时多线程使用不合理,在节假日或秒杀场景下可能导致单机故障,恢复麻烦。在开发和运行过程中,每周对比指标,识别有问题的点。设计阶段有两个常见问题,一是降级场景保障事务一致性,如写数据库失败可能导致两张表数据不一致,生产上此失败场景概率小,但流量大或服务负载不健康时易出现,秒杀场景问题会被放大。预测风险方面较难做到,应提前识别风险隐患并优化,若平时不关注整理则不知有何风险,将问题找出并优化后,在节假日或大量场景下对系统质量更有信心。

15、活动前持续性压测如何做的?

和大家都差不多。主要分为两类,一类是单个应用的压测,对某一系统或模块进行压测,先确定目标,如单机及集群要达到何种水平,因很多场景下涉及集群及数据库容量上限问题,为达到五一、十一等几倍目标,各应用应提前做压测确定水平。单应用压测后进行集成压测,从前端用户视角以入口流量放大倍数往底层压测,目前与其他公司相比某些场景未做到位,如影子库或影子流量隔离场景,部分已做,部分正在进行中,现在压测可能因多个集群和机房,将流量切到另一机房进行安全压测。

16、redis集群选型为什么选用redis cluster?基于什么考虑的?

整个公司的选型,目前已统一按照标准处理。作为业务方共同决策,具体历史背景不太清楚。现在大家使用常见的选型,目前没什么大问题,且比之前的要好很多。

17、redis的集群高可用性携程是如何做的?

现在携程分多个机房,每个机房有一主多从的架构,即一个 master 对应多个 slave,且在多个机房部署。若其中一个机房挂了,访问时会将流量均衡到其他机房。

18、请问因为延迟,海外部署一套集群,redis是两套吗?海外和国内票数不一致吗?

在当前场景下,其他场景中数据是隔离的,如商品信息等可能存在不一致场景时,可通过 DRC 同步。但对于库存场景,目前未进行拆分,扣库存场景仍在国内同一地方进行,不存在数据不一致问题。后续若海外业务与国内业务存在差异,可能会对这块进行拆分。

19、扣减Redis后 写队列的分布式事务也没有针对性处理吗 ?是靠监控来发现异常的吗?

刚提到的扣减及分布式事务,正常消费消息并非分布式事务,扣减后消息发出,消费消息时针对消息进行扣减操作,如扣减库存服务扣减成功,在扣减服务中对数据库表操作有事务处理,要么成功要么失败,若失败会多次重试,仍未成功则靠监控发现并加入监控中。

 

本文来自投稿,不代表TakinTalks稳定性技术交流平台立场,如若转载,请联系原作者。

(1)
上一篇 2024年9月10日 下午3:28

相关推荐

发表评论

邮箱地址不会被公开。