文章目录
引言
云Redis数据库服务是目前广泛应用的模式,其数据持久化方案是现在研究的热点内容,数据持久化操作主要由参数设置自动触发或命令触发。RDB(Redis DataBase)持久化和AOF(Append Only File)持久化,这两种持久化方式可以单独使用,也可以同时使用,以提供更高的数据持久化安全性。但无论是RDB持久化还是AOF持久化,都会涉及到文件写入操作。
云数据库实例大多使用云盘存储模式,是指将数据存储在云服务提供商的服务器上,而不是存储在本地设备上。云盘存储可以通过网络远程随时访问,也具有更好的可扩展性,可以动态扩缩容。
因此,云Redis数据库普遍存在单一资源池内单集群或多集群上所有数据库实例均挂载同一云盘服务的场景。此时成百上千个数据库实例,如果通过传统参数设置自动触发或命令触发的方式管控实例的数据持久化,极易出现多数据库实例同时进行持久化的情形,瞬时产生大量写操作,远超云盘服务的性能基线,可能致使云盘服务夯住,从而诱发一系列数据库实例的报障告警。
一、背景介绍
针对这类共性问题,定时任务和持久化管控组件应运而生,通过定时任务的动态规划和数据持久化的管控分发,尽可能减少某一时刻持久化任务密集的情况,从而确保云盘服务的稳定性。
本文将从源码设计层面通过问答的形式分析移动云Redis产品定时任务与持久化管控组件的设计思路。整体流程图如下:
二、具体实现
1、多副本容灾功能
我们基于K8s的lease选主机制,通过pod自管实现定时任务和持久化管控的唯一性,仅主pod中运行业务流程,其余pod作为容灾备选项。
Pod自管是指,在某pod在获得lease租约时,会给自身添加一个特殊label,区别于其余的pod,并且程序内部的全局选主标志位也会被置为true。该选主标志位用作程序内部决定是否开启定时任务与持久化管控功能的判断条件,确保该组件负责的业务流程仅在主pod内执行。而特殊label则是用于Service对外暴露服务,需在配置Service时,设置nodeSelector为主pod的特殊label,以此来实现新的定时任务请求均会由主pod处理。
在主pod无法续约lease,丢失了主的身份时,同样会通过自管模式,去除自身的特殊label,修改全局选主标志位为false,将内部正在执行的定时任务停止清空,留待新的主pod来继续处理。主备切换流程耗时较短,并不会出现定时任务丢失的情况。
2、主备切换后任务断点续做功能
首先我们的定时任务逻辑是根据24h,每一小时段设置了一个定时控制器,每个控制器负责处理某一个小时内的全部定时任务,其余时段的定时任务不受其管控。另设一个总定时任务控制器,负责管控24个小时制定时控制器,在当前小时40分时,开始初始化下一个小时段的定时控制器,将数据库表中记录的定时任务注册在其中。之所以如此设置这么多的定时控制器,而不是通过一个定时控制器管控所有的定时任务,是基于云Redis产品线上实例成百上千的现状,极易出现某一时间段设置的定时任务数较多,如果同时执行,会对后端组件和云盘服务造成巨大的压力。因此根据小时段划分任务,便于统计,在定时任务集中且频繁时,动态规划其在一定时间范围内完成,而不是并行处理。
然后基于特殊的定时任务管控逻辑,在pod成为主时,除了正常初始化总定时任务控制器外,需要初始化一个起始定时器,该定时器用以实现定时任务的断点续做。其实定时器会根据当前的时间,决定初始化注册哪个时段的定时任务,如果当前分钟小于40,仅注册当前小时段的定时任务;如果当前分钟大于等于40,则需要注册当前小时段和下个小时段的定时任务。这是由小时制定时控制器的特性决定的。
与上述定时任务断点续做逻辑不同,持久化管控任务的断点续做是依赖redis缓存来实现的。在初始化待做持久化实例列表时,会将这些实例ID以集合的形式存储在redis中,设置过期时间为一天,因为持久化管控任务是每天需要对全资源池所有实例分发持久化命令,做一次数据备份。获取到实例列表后,会对其轮询处理,给实例分发持久化命令,执行成功后,会将该实例的ID从redis缓存中去除。
基于此逻辑,在pod重启或主备切换后,首先会从redis缓存中查询特殊Key,如果存在该Key,说明持久化管控任务因异常中断过;如果没有该Key,则表示任务完成或未开始。
3、持久化管控编排功能
持久化管控功能设计初衷就是为了尽可能减少同资源池多实例同时数据持久化对云盘服务的性能影响。具体实现分为两步,首先需要修改线上redis实例的配置文件,将save参数置空,如此实例本身便不会自动触发数据持久化,仅由前端页面设置定时任务和持久化管控两种方式触发。然后便是设置定时任务,每天零点开始进行持久化管控任务,从数据库表中获取最新的活跃实例列表,然后将实例ID以数组形式存储。遍历数组,根据实例ID查询实例数据pod的IP和密码信息,连接实例的数据pod,查询内存使用量,根据内存的实际使用量来预估该实例完成一次数据持久化的所需时间,等待该实例完成持久化之后,再进行下一个实例的数据持久化。通过这种管控组件分发持久化命令的方法,来避免多实例同时持久化的场景,尽可能减少云盘服务的压力。
三、总结
定时任务与持久化管控组件基于K8s的选主机制,通过pod自管的方式实现了多副本容灾功能,并且确保定时任务和实例持久化在设定时间只会执行一次,有效避免多副本多次执行同一任务的情形,确保了云盘服务的稳定性,减少了云上数据库实例的告警报障。
作者
数据库产品部-非关系型数据库组-刘许