摘要
接着上一篇文章《Cassandra数据同步到redis缓存实战之一 数据同步》所介绍的数据同步操作。本文将介绍针对这种操作过程中,出现的各种异常和错误的处理方法。
异常的种类
Cassandra读取异常:
这种异常包括Cassandra服务器节点挂掉、Cassandra连接不上、Cassandra读取超时等,所有这些情况都会导致读取Cassandra的子任务发生异常,进而导致整个任务执行失败。
Flink分配任务异常:
Flink 由于无可用的slot导致任务长时间在队列中等待直到超时:会导致任务完全得不到执行,任务执行失败。
Flink 集群中资源不够无法正常响应Job Manager的资源请求导致的异常:会导致某个子任务得不到执行,使得整个任务执行失败。
包括Flink Task Manager心跳超时:一般是由于task manager服务器资源不够,在运行任务的过程中长时间没有响应心跳,job manager会认为该子任务挂了,异常退出。所以这个错误会导致某个子任务执行到一半异常退出,经常发生在join等需要大量计算资源的子任务中。
redis写入异常:
包括redis集群挂掉、redis连接错误、redis写入错误等。这些异常会导致写入redis的子任务中途失败。导致整个任务失败。
异常的处理:
幂等性!幂等性!幂等性!
异常发生的频率极高,面向失败设计思想的一个重要的最佳实践,就是保证数据幂等性。允许失败的时候进行重试。所以在设计redis key的时候,需要重点考虑这个问题。从cassandra中提取到的同一条数据,在写入到redis的时候,必须拥有一个唯一的键,保证无论这个数据被重复写入多少次,redis中永远只有一个记录。
幂等性的实现可以参考以下文章 https://blog.youkuaiyun.com/marlinlm/article/details/107286326
重试机制
介绍了幂等性,就必须说重试机制了。
- Flink的重试机制
通过Flink的重试机制,可以在发省Cassandra读取超时、Cassandra节点丢失等异常、redis集群异常时,等待一定的时间,让服务自动恢复正常之后重试。
final ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
env.setRestartStrategy(RestartStrategies.fixedDelayRestart(5, Time.seconds(30)));
- Flink job的重新提交
在本案例中,需要把整个数据同步过程,分成几十个Flink任务。主要原因是,Cassandra数据源以日期作为partition key保存数据。因此每次请求只能拿1天的数据输出到redis,而我们的需求是要同步一年的数据,所以整个过程要产生365个data sink。而flink的规定是,一个job不能超过64个sink,因此必须分成几个任务来提交。本案例的实现是通过shell脚本的方式提交任务的,为了减少cassandra数据库和redis的压力,在等到前一个任务执行完成之后,再提交下一个任务。
某个任务如果由于各种原因执行失败了,那么任务将会重新提交,直到任务成功或者超过重试次数。shell脚本判断任务失败重新提交任务的脚本如下:
#!/bin/bash
#第一个参数是重试次数(必传)
retry=$1
#第二个参数是日志的名称(可选)
if [ ! -n "$2" ];then
logName=$((`date "+%s"`*1000+`date "+%N"`/1000000))
else
logName=$2
fi
continue=1
while [ "$continue" -ne "0" -a $retry -gt 0 ]
do
echo retry is $retry
#触发命令并写日志
`./triggerTask.sh >> $logName.log`
#获取命令执行结果
continue=$?
echo the result of the last command is $continue
retry=$(($retry - 1))
echo wait 300 secs before retry...
sleep 300
done
通过Flink实现Cassandra数据同步到redis缓存实战系列文章电梯:
一:数据同步任务的实现
二:Flink任务的定时提交
三:异常处理
四:幂等性!幂等性!幂等性!Redis缓存数据幂等性设计