我使用了Spark结构化的流式消费kafka消息,并将数据保存到Redis。通过扩展ForeachWriter [org.apache.spark.sql.Row],我使用了redis接收器来保存数据。该代码运行良好,但是每秒仅将100多个数据保存到redis。有没有更好的方法来加快此过程?虽然下面的代码将在每个mico批次中连接和断开与Redis服务器的连接,但是有什么方法可以只连接一次并保持连接以最小化连接成本,我认为这是浪费时间的主要原因? 我尝试播放jedis广播,但是jedis和jedispool都无法序列化,因此无法正常工作。
我的接收器代码如下:
class StreamDataSink extends ForeachWriter[org.apache.spark.sql.Row]{
var jedis:Jedis = _
override def open(partitionId:Long,version:Long):Boolean={
if(null == jedis){
jedis = FPCRedisUtils.getPool.getResource
}
true
}
override def process(record: Row): Unit = {
if(0 == record(3)){
jedis.select(Constants.REDIS_DATABASE_INDEX)
if(jedis.exists("counter")){
jedis.incr("counter")
}else{
jedis.set("counter",1.toString)
}
}
}
override def close(errorOrNull: Throwable): Unit = {
if(null != jedis){
jedis.close()
jedis.disconnect()
}
}
任何建议将不胜感激。
答案 0 :(得分:0)
请勿执行jedis.disconnect()
。实际上,这将关闭套接字,并在下一次强制建立新连接。仅使用jedis.close()
,它将把连接返回到池中。
在不存在的键上调用INCR时,它会自动创建,默认为零,然后递增,从而产生值为1的新键。
这将if-else简化为jedis.incr("counter")
。
有了这个,你有:
jedis.select(Constants.REDIS_DATABASE_INDEX)
jedis.incr("counter")
查看您是否确实需要Update UI components with NavigationUI。这是每个连接,所有连接默认为DB0。如果共享同一个Jedis池的所有工作负载都在使用DB 0,则无需调用select。
如果您同时需要select和incr,请SELECT:
Pipeline pipelined = jedis.pipelined()
pipelined.select(Constants.REDIS_DATABASE_INDEX)
pipelined.incr("counter")
pipelined.sync()
这将在一条网络消息中发送两个命令,从而进一步提高性能。