如何应对Spark-Redis行海量数据插入、查询作业时碰到的问题
摘要:由于redis是基于内存的数据库,稳定性并不是很高,尤其是standalone模式下的redis。于是工作中在使用Spark-Redis时也会碰到很多问题,尤其是执行海量数据插入与查询的场景中。
海量数据查询
Redis是基于内存读取的数据库,相比其它的数据库,Redis的读取速度会更快。但是当我们要查询上千万条的海量数据时,即使是Redis也需要花费较长时间。这时候如果我们想要终止select作业的执行,我们希望的是所有的running task立即killed。
Spark是有作业调度机制的。SparkContext是Spark的入口,相当于应用程序的main函数。SparkContext中的cancelJobGroup函数可以取消正在运行的job。
/**
* Cancel active jobs for the specified group. See `org.apache.spark.SparkContext.setJobGroup`
* for more information.
*/
def cancelJobGroup(groupId: String) {
assertNotStopped()
dagScheduler.cancelJobGroup(groupId)
}
按理说取消job之后,job下的所有task应该也终止。而且当我们取消select作业时,executor会throw TaskKilledException,而这个时候负责task作业的TaskContext在捕获到该异常之后,会执行killTaskIfInterrupted。
// If this task has been killed before we deserialized it, let's quit now. Otherwise,
// continue executing the task.
val killReason = reasonIfKilled
if (killReason.isDefined) {
// Throw an exception rather than returning, because returning within a try{} block
// causes a NonLocalReturnControl exception to be thrown. The NonLocalReturnControl
// exception will be caught by the catch block, leading to an incorrect ExceptionFailure
// for the task.
throw new TaskKilledException(killReason.get)
}
/**
* If the task is interrupted, throws TaskKilledException with the reason for the interrupt.
*/
private[spark] def killTaskIfInterrupted(): Unit
但是Spark-Redis中还是会出现终止作业但是task仍然running。因为task的计算逻辑最终是在RedisRDD中实现的,RedisRDD的compute会从Jedis中取获取keys。所以说要解决这个问题,应该在RedisRDD中取消正在running的task。这里有两种方法:
方法一:参考Spark的JDBCRDD,定义close(),结合InterruptibleIterator。
def close() {
if (closed) return
try {
if (null != rs) {
rs.close()
}
} catch {
case e: Exception => logWarning("Exception closing resultset", e)
}
try {
if (null != stmt) {
stmt.close()
}
} catch {
case e: Exception => logWarning("Exception closing statement", e)
}
try {
if (null != conn) {
if (!conn.isClosed && !conn.getAutoCommit) {
try {
conn.commit()
} catch {
case NonFatal(e) => logWarning("Exception committing transaction", e)
}
}
conn.close()
}
logInfo("closed connection")
} catch {
case e: Exception => logWarning("Exception closing connection", e)
}
closed = true
}
context.addTaskCompletionListener{ context => close() }
CompletionIterator[InternalRow, Iterator[InternalRow]](
new InterruptibleIterator(context, rowsIterator), close())
方法二:异步线程执行compute,主线程中判断task isInterrupted
try{
val thread = new Thread() {
override def run(): Unit = {
try {
keys = doCall
} catch {
case e =>
logWarning(s"execute http require failed.")
}
isRequestFinished = true
}
}
// control the http request for quite if user interrupt the job
thread.start()
while (!context.isInterrupted() && !isRequestFinished) {
Thread.sleep(GetKeysWaitInterval)
}
if (context.isInterrupted() && !isRequestFinished) {
logInfo(s"try to kill task ${context.getKillReason()}")
context.killTaskIfInterrupted()
}
thread.join()
CompletionIterator[T, Iterator[T]](
new InterruptibleIterator(context, keys), close)
我们可以异步线程来执行compute,然后在另外的线程中判断是否task isInterrupted,如果是的话就执行TaskContext的killTaskIfInterrupted。防止killTaskIfInterrupted无法杀掉task,再结合InterruptibleIterator:一种迭代器,以提供任务终止功能。通过检查[TaskContext]中的中断标志来工作。
海量数据插入
我们都已经redis的数据是保存在内存中的。当然Redis也支持持久化,可以将数据备份到硬盘中。当插入海量数据时,如果Redis的内存不够的话,很显然会丢失部分数据。这里让使用者困惑的点在于: 当Redis已使用内存大于最大可用内存时,Redis会报错:command not allowed when used memory > ‘maxmemory’。但是当insert job的数据大于Redis的可用内存时,部分数据丢失了,并且还没有任何报错。
因为不管是Jedis客户端还是Redis服务器,当插入数据时内存不够,不会插入成功,但也不会返回任何response。所以目前能想到的解决办法就是当insert数据丢失时,扩大Redis内存。
总结
Spark-Redis是一个应用还不是很广泛的开源项目,不像Spark JDBC那样已经商业化。所以Spark-Redis还是存在很多问题。相信随着commiter的努力,Spark-Redis也会越来越强大。
如何应对Spark-Redis行海量数据插入、查询作业时碰到的问题的更多相关文章
- PHP5: mysqli 插入, 查询, 更新和删除 Insert Update Delete Using mysqli (CRUD)
原文: PHP5: mysqli 插入, 查询, 更新和删除 Insert Update Delete Using mysqli (CRUD) PHP 5 及以上版本建议使用以下方式连接 MySQL ...
- 使用Apache Spark 对 mysql 调优 查询速度提升10倍以上
在这篇文章中我们将讨论如何利用 Apache Spark 来提升 MySQL 的查询性能. 介绍 在我的前一篇文章Apache Spark with MySQL 中介绍了如何利用 Apache Spa ...
- SQLite -插入查询
SQLite -插入查询 SQLite插入语句是用来添加新行数据到数据库中的一个表. 语法: 有两种基本的插入语句的语法如下: INSERT INTO TABLE_NAME (column1, co ...
- 如何分析redis中的慢查询
慢查询的两个参数配置 慢查询只记录命令执行时间,并不包括命令排队和网络传输时间.因此客户端执行命令的时间会大于命令实际执行时间.因为命令执行排队机制,慢查询会导致其他命令级联阻塞,因此当客户端出现请求 ...
- Sql Server的艺术(六) SQL 子查询,创建使用返回多行的子查询,子查询创建视图
子查询或内部查询或嵌套查询在另一个SQL查询的查询和嵌入式WHERE子句中. 子查询用于返回将被用于在主查询作为条件的数据,以进一步限制要检索的数据. 子查询可以在SELECT,INSERT,UPDA ...
- Redis 如何分析慢查询操作?
什么是慢查询 和mysql的慢SQL日志分析一样,redis也有类似的功能,来帮助定位一些慢查询操作. Redis slowlog是Redis用来记录查询执行时间的日志系统. 查询执行时间指的是不包括 ...
- JAVA中通过Jedis操作Redis连接与插入简单库
一.简述 JAVA中通过Jedis操作Redis连接与插入简单库 二.依赖 <!-- https://mvnrepository.com/artifact/redis.clients/jedis ...
- mysql命令行批量插入100条数据命令
先介绍一个关键字的使用: delimiter 定好结束符为"$$",(定义的时候需要加上一个空格) 然后最后又定义为";", MYSQL的默认结束符为" ...
- CDH spark 命令行测试
一. 参考 https://www.cnblogs.com/bovenson/p/5801536.html [root@node- test]# chown hdfs:hdfs /root/test/ ...
- MySQL查询时记录行号rownum MySQL查询显示行号MySQL查询显示行号MySQL流水号自MySQL自增行号
MySQL查询时记录行号rownum MySQL查询显示行号MySQL查询显示行号MySQL流水号自MySQL自增行号 一.前言 Oracle中有rownum,实现查询的时候记录行号,MySQL中没有 ...
随机推荐
- 入手react的 第一坑
npm verb cli /usr/local/bin/node /usr/local/bin/npm npm info using npm@9.8.1 npm info using node@v18 ...
- 推荐一款“自学编程”的宝藏网站!详解版~(在线编程练习,项目实战,免费Gpt等)
云端源想学习平台,一站式编程服务网站云端源想官网传送门 精品课程:由项目实战为导向的视频课程,知识点讲解配套编程练习,让初学者有方向有目标. 课程阶段:每门课程都分多个阶段进行,由浅入深,很适合零基础 ...
- Acwing周赛102
倍增 这是一道简单数论题 using namespace std; typedef long long LL; const int N = 1e5 + 10; int a[N], n; int div ...
- Mybatis-plus 生成代码
引入依赖 <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-g ...
- 【iOS开发】iOS App的加固保护原理:使用ipaguard混淆加固
摘要 在开发iOS应用时,保护应用程序的安全是非常重要的.本文将介绍一种使用ipaguard混淆加固的方法来保护iOS应用的安全.通过字符串混淆.类名和方法名混淆.程序结构混淆加密以及反调试.反注 ...
- 【GIT】学习day04 | 将本地代码推送到码云仓库中进行管理【外包杯】
仓库代码页 将本能仓库和码云仓库进行关联 代码组成 git remote add origin 加上下面的地址 将本地仓库的代码推送到码云仓库上 git push -u origin master 之 ...
- VScode 中利用virtualenv建立 Python 虚拟环境
! https://zhuanlan.zhihu.com/p/638114885 VScode 建立 Python 虚拟环境 主要目的:创建一个与默认 python 版本不同的 python 虚拟环境 ...
- N100低功耗win11安装wsl2当入门nas
前言 最近入了一台16gb+512gb的N100,想着用来存些资源,当个nas,偶尔要用用windows系统,所以想直接在这上面搞个虚拟机算了,WSL2似乎是一个不错的选择,下面介绍捣鼓的教程. 没用 ...
- NLP项目实战02:英文文本识别
简介: 欢迎来到本篇文章!今天我们将讨论一个新的自然语言处理任务--英文短文识别.具体而言,即通过分析输入的英文文本来判断其是比较消极的还是比较积极的. 展示: 1.项目界面 如下所示是项目启动后用户 ...
- AI助力软件工程师高效工作:8款神器助你优化工作流程
随着人工智能技术的不断发展,AI工具在软件工程领域展现出强大的应用潜力.善用 AI 工具可以消除繁琐事务带来的倦怠,帮助软件工程师更好地传达想法,完成更高质量的工作.我们可以将 AI 以各种方式应用于 ...