首页 » 软件优化 » 面向失败的设计之播控系统(缓存失败设计系统面向)

面向失败的设计之播控系统(缓存失败设计系统面向)

admin 2024-11-03 02:53:41 0

扫一扫用手机浏览

文章目录 [+]

责编 | 屠敏

谈面向失败的设计

1、什么是面向失败的设计?

面向失败的设计之播控系统(缓存失败设计系统面向) 软件优化
(图片来自网络侵删)

面向失败的设计,就是以“失败”为对象,天然为了失败而存在的设计思想,在一开始的系统设计阶段就考虑到各种失败场景,把面向失败当成是系统设计的一部分,准备好从失败中恢复的策略。

2、为什么要面向失败设计?

因为无所不在的失败场景,比如硬件问题,软件bug,配置变更错误,系统恶化,超预期流量,外部攻击,依赖库问题,依赖服务问题。

并且,这些一旦失败,轻则出现业务不可用,影响用户体验和企业声誉;重则导致数据永久丢失、业务再无恢复可能。
例如,911事故发生前,约有350家企业在世贸大厦工作。
事故后,有200家企业由于重要系统被破坏,关键数据丢失而倒闭。

3、怎么面向失败设计?

在软件的整个生命周期中,不同的阶段面对失败场景有不同的应对规则。
在设计阶段将系统的架构简单化,结构层次分明;在发布阶段尽量做到最小变更原则,小规模,多次迭代;在运维阶段做好周期性压测,最小依赖。

播控是如何实现面向失败设计的

1、播控架构设计

优酷播放控制系统从层级结构上将系统分成3层,对外服务层、基础服务层、数据存储层。

第一层:对外服务层包含播控SDK,播控查询服务,播控变更服务,播控筛选服务

第二层:基础服务层包含播控任务调度,播控数据库服务;

第三层:数据存储层包含分布式缓存,数据库,开放搜索。

从功能上,播控系统共3大核心线路读核心、写核心、筛选服务。

线路一:读核心是整个系统的核心服务,负责优酷、土豆、天猫视频展示、透出能力;

线路二:写核心负责整个系统策略变更核心服务;

线路三:筛选服务提供管理后台多数据源筛选服务。

这样设计的特性如下:

1) 线路上读、写分离,核心与筛选分离(主次分离),单独链路变更失败之后不会影响核心链路的功能;

2) 核心高并发查询服务读取数据库方式从数据库服务隔离开,当压力增加后,无单点瓶颈,可以无限扩展;

3) 任一链路故障,其他链路正常运行,稳定提供服务;

4) 数据库服务遵从容量设计原则,针对查询服务、变更服务相同接口有不同限流策略。

2、数据库不可用兜底设计

数据库兜底设计的目的在于在数据库不可用的极端场景下,保证生产链路不挂,且不会影响到业务方。
实现方式通过全局统一开关,切换核心读链路和写链路使用缓存作为临时的数据持久层,并把数据变更堆积在消息队列中,待数据库可用后再切换回数据库,并消费消息队列。

读链路数据库兜底流程

读链路以查询是否资源是否可播为例,兜底开关打开,则只查询缓存中是否存在该资源。
若缓存中存在资源,则返回查询结果。
若不存在,则判断资源是否在禁播黑名单,根据判断结果返回是否可播。
可见兜底开关打开后,虽然返回的是降级之后的结果,但至少摆脱了对数据库的依赖,整个流程仍能正常进行下去。

写链路数据库兜底流程

写链路以新增资源策略为例,兜底开关打开,则先查询缓存中是否存在该资源策略。
若缓存中存在该资源策略,则流程结束。
若不存在,则更新缓存,并发送消息,用于延时消费,更新数据库。
可以看到思路仍然是以缓存作为临时数据源,降低对数据库的依赖,同时借助了消息队列的异步特性,来解决数据库恢复后,数据库数据与缓存数据的一致性问题。

3、缓存冗余更新和缓存一致性检测设计

高并发的业务场景下,数据库是十分宝贵的资源,也是非常薄弱的环节。
系统设计时不可避免的需要使用缓存作为缓冲。
上一小节针对数据库不可用的极端场景设计了方案,本小节将会提出两种解决缓存与数据不一致问题的方案。

1) 缓存冗余更新

缓存冗余更新是在数据发生变更时,通过同步与异步冗余更新的方式,保证不会出现脏数据,并且保证最终的数据一致性。

缓存更新基本架构

1-2-6-7即为一个常见的旁路缓存更新结构。
但由于业务的复杂性,在播控变更服务执行完数据变更后,需要通过步骤3发消息通知外部系统,外部系统接收到消息后通过步骤4-5进行反查,但由于步骤3和步骤6-7都是异步过程,可能在6-7执行完成之前,3-4-5已经执行,则查询到的是更新之前的脏数据。

缓存冗余更新的思路是,变更服务除了通过消息异步更新缓存之外,同步的调用播控任务调度,去更新缓存。
同步更新保证缓存数据的准确性,不会出现脏数据,异步更新保证更新链路的高可用,不会因为接口调用失败而导致缓存更新失败,达到最终数据的一致性。

2) 缓存一致性检测

缓存冗余更新是用来确保写入缓存时数据的正确性。
除此之外,我们还提供一种写入缓存后的缓存一致性检测机制,专门检查近期写入缓存的数据是否符合预期,检测到不一致后进行上报和清理。

检测流程如下,利用guava cache设置5s过期机制,在数据变更写入数据库和缓存的5s之后,通过监听器监听guava cache的过期,来触发数据对比的检测,并根据检测结果做出相应的处理。

脏数据检测流程

4、远端/近端调用动态切换设计

播控除了通过RPC调用方式为上游业务提供基础服务,还提供了播控SDK可以供业务方进行近端调用。
近端调用对于业务方来说在降低延时,提高成功率方面都有很好的效果,对于播控来说也能减轻服务器压力,节省资源。
但为了防止出现稳定性问题,也必须面向失败设计,提供降级方案,其中一种降级方案是流量动态切换方案。
当业务方机器能够承受的SDK流量上限超过阈值时,多余的流量会动态分散到播控中心系统;这在实际中是很有效的,在一些单机QPS达到1000甚至更高的场景下,确保SDK不会压垮业务方机器。
极端情况下,所有流量都可以回切到播控中心系统。

总结

一个优秀的架构师往往都是悲观主义者,除了设计好能够支撑业务持续发展的优雅架构,另一个容易被忽略的重要能力在于充分考虑失败场景。
面向失败设计是一种十分重要的设计思路,需要能够防患于未然,在设计阶段考虑到各种失败场景,提前准备好预案,并且做好充分的演练和验证。
只有这样才能够在失败来临时从容应对。

☞11 国股市熔断,“祸及”程序员?!

☞深度解读!
阿里统一应用管理架构升级的教训与实践

☞2.2版本发布!
TensorFlow推出开发者技能证书

☞Soul App 高管被捕,恶意举报导致竞品被下架

☞2020 年最新版 68 道Redis面试题,20000 字干货,赶紧收藏起来备用!

☞最近一个名为 BTCU 的比特币分叉,准备用新分叉解决比特币网络的旧问题

标签:

相关文章