日均20亿流量:携程机票查询系统的架构升级 (5)

A:分布式缓存的关键在于它的键值怎么设定?必须要根据特定的业务场景,比如说我们有的键值里加入了IP地址,也就是我们的Pooling,基于Redis建立了它的队列,所以我们queue当中是把这种请求方的IP作为建设的一部分放了进去,这样就能保证子任务能够知道到哪儿去查询它相应的返回结果。

Q:为什么redis的读写延迟能做到3ms以内呢?

A:我首先要解释一下,所谓读写延时低,其实主要指的是读延时,读延时可以做到三毫秒以内,应该是没有什么问题的。

Q:这个队列是内存队列?还是MQ?

A:互联队列我们是用的Redis实现的,而不是用的消息队列或者内存队列,主要是为了保证它的高可用性。

Q:缓存失效怎么刷新的,这里涉及分布式锁吧?

A:前文提到的缓存失效,并不是指它里边存的数据失效,我主要指的是整个缓存机制失效了。我们不需要分布式锁,因为我们都是单独的key-value存储。

Q:缓存数据一致性怎么保证的?

A:这个是非常难保证的,我们常用的技巧是,首先缓存超过我们预设的阈值的话,我们会强行清除。然后如果有更精确的内容进来,我们是要动态刷新的。比如本来可以存5分钟,但是在第2分钟有一位用户查询并且下单,这时候肯定是要做一次实时查询,顺便把还没有过期的内容也刷新一遍。

Q:热key,大key怎么监控的?

A:其实对我们来说,热区没有那么明显,因为一般来说我们的一个key基本上对应一个点,一个出发地和一个目的地,中间再加上各种渠道引擎的限制。而不像分片那样,你分成16片或者32片,有可能某一分片逻辑设计不合理,导致那一片过热,然后相应的硬件直接到了瓶颈。

Q:老师能详细讲一下Pooling吗?

A:我先讲一下原理:子任务它们所用的时间长短是不一样的,如果完全基于我们的SOA进行动态随机分的话,肯定有的计算节点分到的子任务比较重,有的节点分到的比较轻,加入Pooling,就好像加入了一个排队策略,特别是对于中间还会实时调用离开几秒钟的情况,那么排队策略能够极大的节省我们的计算资源。

Q:监控是怎么做的?

A:监控我们现在是基于原来用了时序数据库,如ClickHouse,和Grafana,然后现在兼容了Promeneus的数据收集和API。

Q:二级缓存采用Redis的哪种数据类型?

A:二级缓存存的是我们的中间结果,应该是分类型的数据类型。

Q;TTL计算应该考虑哪些问题?

A:我们首先最害怕数据出现问题,比如系统总是返回用户一个已经过期的低票价,用户体验肯定会很差,所以这方面我们会牺牲命中率,然后会缩短TTL,只不过TTL控制在5分钟之内,有时候还需要微调一下,所以用了机器学习模型。

Q:IP直连和Pooling没太听明白,是说AGG中,涉及到的计算进行拆分,将中间结果进行存储,其他请求里如果也需要这个中间计算,可以直接获取?

A:IP直连和PoolingIP直连,其实把负载均匀的分到各个节点Pooling,只不过你要计算的子任务加入队列,然后每一个运算节点每次取一个,计算完了再放回去。这样计算的效率更高。中间结果没有共享,中间结果存回去是因为有的子任务需要中间离开,再去查其他的实时系统,所以就相当于把它分成了两个运算子任务,中间的任务要重新放回队列。

Q:下单类似秒杀了吧,发现一瞬间票光了,相应的缓存是怎么更新的?

A:如果我们有第1个用户选择了一个运价,没有通过,我们是要把缓存数据都给杀掉的,然后尽量防止第2个用户还会陷入同样的问题。

Q:多级缓存数据怎么保证一致?

A:因为我们一级缓存存的是最终的结果,二级缓存是中间结果,所以不需要保持一致。

Q:请教一下,一级、二级、三级缓存,请求过来了,怎么提高吞吐量,按理说,每个查询过程需要消耗时间的,吞吐量应该会下降?

A:是这样的,如果你没有这些缓存的话,那几乎所有都要走一遍。实时计算这种情况下,时间长,而且我们部署的集群能够响应的数很有限,然后一、二、三级每一级都能够屏蔽掉很多的请求。我们一级大概能够屏蔽20%,二级可以屏蔽掉差不多40%~50%。然后在这种情况下,同样的集群吞吐量显然是有明显增加。

Q:如何防止缓存过期时刻产生的击穿问题,目前携程是定时任务主动缓存,还是根据用户请求进行被动的缓存?

A:对于缓存清除,我们既有定时任务,也有被动的更新。比如说用户又取了一次或者购票失败这些情况,我们都是会刷新或者清除缓存的。

Q:搜索结果会根据用户特征重新计算运价和票种么?

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsfxww.html