网易视频云:分布式转码服务高可用浅析

分布式视频处理系统中的worker、razer、sdk等模块以无状态方式设计,即worker应用停止服务或节点宕机均不会影响整个系统对于视频的处理。比如有worker-N应用正在处理转码,到了99%的时候,却很不幸的应用崩溃,显然该转码任务失败,那么我们该怎么来保证该转码任务能正常结束,让用户不吐槽?我们的节点管理中心即Node Manager应此而生,它全程监控转码任务的状态,如碰到系统因素引起的失败,进行任务回收,其他worker应用重新进行转码。

  节点管理中心最基本核心的功能为各个节点服务器的状态管理,此外还包括用户管理(包括鉴权)、任务的跟踪统计、节点状态变更通知、资源监控、全局配置信息获取、及自身的HA等功能,如下图所示。

  

  在设计之初,各个任务节点能独立运行不依赖与管理中心,即管理中心是单点运行状态。但是随着功能的不断完善及设计的不断优化,我们发现单点状态已经连最起码的功能完整性都保证不了了,比如统计数据混乱、dashbord平台无法使用、监控报警失效,节点失效通知不及时等等,因此我们对Node Manager提出了高可用性的需求,也就是本文的初衷。

  众所周知,在分布式高可用性系统模型方面无非就是中心化和去中心化两种设计方式。中心化的设计例如mysql的MSS单主双从、MongDB Master、HDFS NameNode、MapReduce JobTracker等,有1个或几个节点充当整个系统的核心元数据及节点管理工作,其他节点都和中心节点交互。这种方式的好处显而易见,数据和管理高度统一集中在一个地方,容易聚合,就像领导者一样,其他人都服从就好,简单可行。但是缺点是模块高度集中,容易形成性能瓶颈,并且如果出现异常,就像群龙无首一样。无中心化的设计,例如cassandra、zookeeper,系统中不存在一个领导者,节点彼此通信并且彼此合作完成任务。好处在于如果出现异常,不会影响整体系统,仅仅局部不可用。缺点是比较协议复杂,而且需要各个节点间同步信息。

  节点管理中心由于不涉及到用户(2C)的相关操作操作,访问量及并发量都较为有限,所以我们总结出了JDBC Store active/standby的中心化高可用实现方案,通过JDBC的方式与database交互,使用database的表级排它锁来实现多节点争抢主机节点,另外还包括节点状态转变(active/standby切换)和客户端的failover机制。以下分别通过elect leader、status change和client failover分别进行阐述。

  elect leader词汇据我所知是从zookeeper里来的,保证集群中Master的可用性和唯一性。我们的高可用性方案是active/standby,但是因为我的肤浅实在想不出更好的名词来表达这个争抢主机这个过程,本文中涉及于此,都会以elect leader来进行描述。

  两个节点管理应用同时启动,我们需要确定一个唯一的应用来服务于其他业务节点,在这之前我们需要创建csserver_ha表用于保存主机节点的信息,elect leader的主要流程如下:

  

  √Lock csserver_ha。

  √查询csserver_ha中ha_status = ‘active’的记录数。

  √若结果为0说明首次启动,则往csserver_ha新增一条记录包括该应用所在的IP、port、心跳时间(当前时间),状态为active,然后setActive(this),也就是说把该节点应用设置为主机。

  √若结果大于0,说明之前已存在过active的节点应用,此时获取状态为active的记录,判断当前和该记录中的心跳时间(hb_time)的差值。

  √若小于预设值的timeout时间,说明之前存在的active应用尚未失效,则seStandby(this),也就是设置该节点应用为备机。

  √若大于等于 timeout时间,说明之前存在的active应用已经失效,那么设置该节点应用为主机,即setActive (this)。更新csserver_ha 中active记录的ip、port、hb_time为当前应用信息和当前时间。

  √Unlock csserver_ha。

  Status change表示节点应用的内部状态转变,分别为dead、active、standby,dead表示节点处于宕机或者应用实例未启动,active表示应用实例为主机,standby表示应用实例为备机。

  √当主机转变为active时,其他任务单元方能与之正确通信,并且自启动心跳日志记录任务和脑裂检测任务。定时写心跳日志到表csserver_hb中,表示该节点应用尚浅存活。如果集群单元发生“脑裂”,那么可想而知会发生存在两个主机节点的情况,其他任务单元提交的数据也被割裂,得不到完整性的保障。在我们的系统中,如果active节点和数据库之间发生网络中断,standby检测到active不可用(假死或者宕机),立即接管服务,转变为active,显然这个时候有2个active了,那怎么去保证呢?也就是前文所说的脑裂检测任务,active节点不断的去询问standby节点“你是谁?”,standby节点如果回答“I am active”,那么active节点降级成standby节点。或者active节点和standby节点也发生网络中断了,这种情况下,双active很有可能会出现,为了保证系统对于节点管理中心的唯一性,active节点降级转变成standby节点。

  √当主机转变为standby时,其他节点与之通信返回“服务不可用”的错误码。standby节点启动针对active节点的健康检测,主要是不断的读取active记录中的心跳时间hb_time,如果和当前时间的差值超出预先设置的timeout时间,则表示active节点不可用,至此standby节点切换成active状态。Standby扮演着try get the active的角色。

  √如果active和standby节点与数据库的网络均处于中断状态,那么意味着节点管理中心集群崩溃。

  Client failover任务单元访问节点管理中心时需遵循failover:{ip1:port1;ip2:port2}的协议,client端轮询访问ip1和ip2,不需要去区分active和standby,若返回“服务不可用”的状态码或者网络连接超时就去重试访问另外一个,如果ip1和ip2均不可用,则说明节点管理中心集群崩溃。

  本文仅限于讨论小众范畴的通过MySql共享存储方式实现高可用方案,其他的例如Keepalived、Zookeeper等实现及文中所涉及的高可用、脑裂、网络分区等概念,读者可自行Google。

你可能感兴趣的:(ffmpeg)