案例二:POI缓存设计与实现

背景

2014年Q4,数据库中关于POI(这里可以简单理解为外卖的门店)相关的数据的读流量急剧上升,虽然说加入从库节点可以解决一部分问题,但是毕竟节点的增加是会达到极限的,达到极限后主从复制会达到瓶颈,可能会造成数据不一致。所以此时,急需引入一种新的技术方案来分担数据库的压力,降低数据库POI相关数据的读流量。另外,任何场景都考虑加DB从库的做法,会对资源造成一定的浪费。

实现方案

基于已有的经过考验的技术方案,我选择Tair来作为缓存的存储方案,来帮DB分担来自于各应用端的POI数据的读流量的压力。理由主要是从可用性、高性能、可扩展性、是否经过线上大规模数据和高并发流量的考验、是否有专业运维团队、是否有成熟工具等几个方面综合考量决定。

详细设计

第一版设计

缓存的更新策略,根据业务的特点、已有的技术方案和实现成本,选择了用MQ来接收POI改变的消息来触发缓存的更新,但是这个过程有可能失败;同时启用了key的过期策略,并且调用端会先判断是否过期,如过期,会从后端DB加载数据并回设到缓存,再返回。通过两个方面双保险确保了缓存数据的可用。

第二版设计

第一版设计运行到一段时间以后,我们发现了两个问题:

  • 某些情况下不能保证数据的实时一致(比如技术人员手动改动DB数据、利用MQ更新缓存失败),这个时候只能等待5分钟的过期时间,有的业务是不允许的。
  • 加入了过期时间导致另外一个问题:Tair在缓存不命中的那一刻,会尝试从硬盘中Load数据,如果硬盘没有再去DB中Load数据。这无疑会进一步延长Tair的响应时间,这样不仅使得业务的超时比率加大,而且会导致Tair的性能进一步变差。

为了解决上述问题,我们从美团点评负责基础架构的同事那里了解到Databus可以解决缓存数据在某些情况下不一致的问题,并且可以去掉过期时间机制,从而提高查询效率,避免tair在内存不命中时查询硬盘。而且为了防止DataBus单点出现故障影响我们的业务,我们保留了之前接MQ消息更新缓存的方案,作了切换开关,利用这个方案作容错,整体架构如下:

上线后效果

上线后,通过持续地监控数据发现,随着调用量的上升,到DB的流量有了明显地减少,极大地减轻了DB的压力。同时这些数据接口的响应时间也有了明显地减少。缓存更新的双重保障机制,也基本保证了缓存数据的可用。见下图:

案例来源:美团技术团队