redis集群scan_Redis scan命令的一次坑

Redis作为当前服务架构不可或缺的Cache,其支持丰富多样的数据结构,Redis在使用中其实也有很多坑,本次博主遇到的坑或许说是Java程序员会遇到的多一点,下面就听博主详细道来。

线上服务堵塞

String key = keyOf(appid);

int retryCount = 3;

int socketRetryCount = 3;

Exception ex = null;

while(retryCount > 0 && socketRetryCount > 0) {

try {

return redisDao.getMap(key);

}catch (Exception e) {

}

}

12月2日被告知服务出现异常,查看日志发现其运行到上述代码getMap方法处后日志就没有内容了。

问题分析

"pool-13-thread-6" prio=10 tid=0x00007f754800e800 nid=0x71b5 waiting on condition [0x00007f758f0ee000]

java.lang.Thread.State: WAITING (parking)

at sun.misc.Unsafe.park(Native Method)

- parking to wait for <0x0000000779b75f40> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)

at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)

at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)

at org.apache.commons.pool2.impl.LinkedBlockingDeque.takeFirst(LinkedBlockingDeque.java:583)

at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:442)

at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:363)

at redis.clients.util.Pool.getResource(Pool.java:49)

at redis.clients.jedis.JedisPool.getResource(JedisPool.java:99)

at org.reborndb.reborn.RoundRobinJedisPool.getResource(RoundRobinJedisPool.java:300)

at com.le.smartconnect.adapter.spring.RebornConnectionFactory.getConnection(RebornConnectionFactory.java:43)

at org.springframework.data.redis.core.RedisConnectionUtils.doGetConnection(RedisConnectionUtils.java:128)

at org.springframework.data.redis.core.RedisConnectionUtils.getConnection(RedisConnectionUtils.java:91)

at org.springframework.data.redis.core.RedisConnectionUtils.getConnection(RedisConnectionUtils.java:78)

at xxx.run(xxx.java:80)

at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)

at java.util.concurrent.FutureTask.run(FutureTask.java:262)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)

at java.lang.Thread.run(Thread.java:745)

Locked ownable synchronizers:

- <0x000000074f529b08> (a java.util.concurrent.ThreadPoolExecutor$Worker)

从线程日志可以看出服务堵塞在获取redis连接处.

分析:

代码配置中redis最大连接为3000

redis配置中session_max_timeout为0,即永不断开连接

一次修改分析

从以上两点分析得出,redis连接被耗尽,于是查找代码得知由于重写spring-data-redis中的hscan方面导致,代码如下:

RedisConnection rc = redisTemplate.getConnectionFactory().getConnection();

if (rc instanceof JedisConnection) {

JedisConnection JedisConnection = (JedisConnection) rc;

return new ConvertingCursor, Map.Entry>(

JedisConnection.hScan(rawValue(key), cursor, scanOptions),

new Converter, Map.Entry>() {

@Override

public Entry convert(final Entry source) {

return new Map.Entry() {

@Override

public String getKey() {

return hashKeySerializer.deserialize(source.getKey());

}

@Override

public String getValue() {

return hashValueSerializer.deserialize(source.getValue());

}

@Override

public String setValue(String value) {

throw new UnsupportedOperationException(

"Values cannot be set when scanning through entries.");

}

};

}

});

} else {

return hashOps.scan(key, scanOptions);

}

上述代码返回ConvertingCursor后未释放连接,导出连接被占满。

二次修改分析

于是修改代码为正常释放连接

try {

...

}finally {

RedisConnectionUtils.releaseConnection(rc, factory);

}

代码经过上线,再次跑程序查看线上日志发现报了大量的Connection time out.

于是博主就思考是不是由于重写代码不对,尝试使用spring-data-redis的原生代码,即直接调用hashOps.scan(key, scanOptions)方法,再次上线。

上线后观察日志:发现这次不是报Connection time out,日志中大量报Unknown reply:错误。

分析如下:

由于代码是在多线程环境下运行,有几百个线程去调用hscan操作,spring-data-redis原生的代码执行完一次hscan操作后就会关闭连接并返回一个迭代器Cursor,但是遍历Cursor时在本次count后会再次根据游标重新使用该连接进行查询,可是连接却已经被关闭,这时会使用新的连接是可以正常迭代的,但是一旦复用到其他线程使用的连接则会导致报错Unknown reply.

三次修改分析

经过思考后得出结论,redis在执行scan操作时一旦连接被释放,那么scan操作将不会进行下去,则报Connection time out.

查阅官方文档得出结论,redis的scan操作需要full iteration,即最优方式是一个连接将以此scan任务执行完全后释放该连接。

redis-scan-doc

修改代码如下:

RedisConnectionFactory factory = redisTemplate.getConnectionFactory();

RedisConnection rc = factory.getConnection();

if (rc instanceof JedisConnection) {

JedisConnection JedisConnection = (JedisConnection) rc;

Cursor> cursorResult = new ConvertingCursor, Map.Entry>(

JedisConnection.hScan(rawValue(key), cursor, scanOptions),

new Converter, Map.Entry>() {

...

});

return new ScanResult>(cursorResult, factory, rc);}

public void releaseConnection() throws IOException{

IOException ex = null;

if(cursor != null) {

try {

cursor.close();

} catch (IOException e) {

ex = e;

}

}

try {

RedisConnectionUtils.releaseConnection(rc, factory);

} catch (Exception e) {

}

if(ex != null) {

throw ex;

}

}

将连接返回给业务代码,并在业务代码执行完毕后将连接释放,问题解决。

总结

连接一旦开启就必须释放,否则造成内存泄漏或服务堵塞不可用

重写代码时需要谨记仔细查阅官方文档给出的方案并实施

多线程下使用redis的scan操作需要使用一个连接遍历完Cursor,而不能复用连接,否则导致报错Unknown reply.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/349094.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

jbpm小项目测试_尝试使用jBPM Console NG(测试版)

jbpm小项目测试大家好&#xff01; 这是有关jBPM Console NG的另一篇文章。 经过6个月的辛苦工作&#xff0c;我很高兴为开发人员社区撰写这篇文章&#xff0c;以进行尝试。 在这篇文章中&#xff0c;我将解释如何从源代码构建应用程序。 这背后的主要思想是知道如何在测试过程…

hashmap 扩容是元素还是数组_HashMap 中的容量与扩容实现

总有人心里有火炬&#xff0c;而且彼此能看见。高手过招&#xff0c;招招致命JDK1.8 中 HashMap 的底层实现&#xff0c;我相信大家都能说上来个 一二&#xff0c;底层数据结构 数组 链表(或红黑树) &#xff0c;源码如下/*** 数组*/transient Node[] table;/*** 链表结构*/st…

用友数据库服务器如何修改,用友u8数据库服务器怎么设置

用友u8数据库服务器怎么设置 内容精选换一换本章介绍如何在管理控制台购买GaussDB(for openGauss)实例&#xff0c;并通过内网使用弹性云服务器连接GaussDB(for openGauss)实例。GaussDB(for openGauss)提供gsql工具帮助您在命令行下连接数据库&#xff0c;您需要提前创建一台弹…

红米路由器ac2100怎样设置ipv6_Redmi路由器AC2100开箱:六天线简单直接,功能丰富对玩家友好...

原标题&#xff1a;Redmi路由器AC2100开箱&#xff1a;六天线简单直接&#xff0c;功能丰富对玩家友好Redmi K30系列旗舰新品发布会期间&#xff0c;Redmi红米发布了Redmi路由器AC2100。这一命名让人不禁想起小米路由器AC2100。但就像同期发布的Redmi小爱音箱Play与小米小爱音箱…

hibernate批量查询_使用Hibernate批量获取

hibernate批量查询如果需要从Java处理大型数据库结果集&#xff0c;则可以选择JDBC&#xff0c;以提供所需的低级控制。 另一方面&#xff0c;如果您已在应用程序中使用ORM&#xff0c;则回退到JDBC可能会带来一些额外的麻烦。 在导航域模型时&#xff0c;您将失去诸如乐观锁定…

word2003流程图变成图片_Word中流程图怎么画 手把手教你制作!

步骤三&#xff1a;绘制流程图框架接下来我们开始绘制流程图的框架。所谓框架就是画出图形、把图形大致布局并在其中输入文字。在这里大家可以体会到&#xff0c;如果已经作好了草图&#xff0c;这里的操作将是比较轻松的&#xff0c;如果在这里边想边画&#xff0c;可能会耽搁…

cmakelists语法_CMakeList语法知识

在写这篇文章之前开始是想一些shell脚本与Makefile的一些基础语法知识。但是又觉得太过基础。关于Liunx shell脚本可以看看教程http://c.biancheng.net/linux_tutorial/ CMake是一种跨平台编译工具&#xff0c;CMake主要是编写CMakeLists.txt文件&#xff0c;然后通过cmake命令…

spring pom设置_Spring社交Twitter设置

spring pom设置在本系列的第一部分中 &#xff0c;我们研究了如何使用StackExchange REST API来检索其主要问题。 第二部分将重点设置使用Spring Social Twitter项目与Twitter REST API交互所需的支持。 最终目标是能够在多个帐户上每天发送两个问题&#xff0c;每个帐户集中讨…

apache mediawiki 安装_如何在CentOS 7上安装MediaWiki

如果您想构建自己的wiki网站&#xff0c;可以使用MediaWiki轻松完成&#xff0c; MediaWiki是一个最初为WikiPedia创建的PHP开源应用程序。 由于为此应用程序开发的第三方扩展&#xff0c;其功能可以轻松扩展。在本文中&#xff0c;我们将讨论如何使用LAMP (Linux&#xff0c;A…

Java 9迁移指南:七个最常见的挑战

我确定您已经听说过更新到Java 9并不是一件容易的事&#xff0c;甚至可能是不兼容的更新&#xff0c;而且对于大型代码库而言&#xff0c;迁移毫无意义。 这样做之后&#xff0c;我迁移了一个相当大的旧代码库&#xff0c;我可以告诉你&#xff0c;这还不错。 比碰到Java 8确实…

nuxt sass 全局变量的问题_Sass入门教程

SASS(Syntactically Awesome Stylesheet)是一个CSS预处理器&#xff0c;有助于减少CSS的重复&#xff0c;节省时间。 它是更稳定和强大的CSS扩展语言描述文档的风格结构。sass中文网而且Sass算是CSS的超集&#xff0c;它100%兼容CSS的语法&#xff0c;所有在 CSS 中正常工作的代…

javascript对象包含哪些要素_javascript有哪几种对象?

JavaScript中支持3种对象&#xff1a;内置对象(原生对象)&#xff0c;浏览器对象&#xff0c;自定义对象。下面本篇文章就来给大家介绍一下&#xff0c;希望对大家有所帮助。对象包含两个要素&#xff1a;1、用来描述对象特性的一组数据&#xff0c;也就是若干变量&#xff0c;…

用C语言实现优先级排序和MATLABsort函数的比较

为了实现对两个数组进行优先级排序,用c语言有两种实现方法, 一是需要对两个数组进行排序,然后对排序后的坐标再排序,(求最小值是我自己需要) 二是直接寻找数组排序后的元素坐标,调用qsort函数进行排序,排序后的数组会存放在原数组中,那么就有两种寻找坐标,一是寻找…

造成内存泄漏_如何造成内存泄漏

造成内存泄漏这将是一个相当邪恶的职位-当您确实希望使某人的生活陷入困境时&#xff0c;您将在谷歌上搜索。 在Java开发领域&#xff0c;内存泄漏只是您在这种情况下会引入的错误类型。 为您的受害者保证几天甚至几周的办公室不眠之夜。 我们将在这篇文章中描述两次泄漏。 两…

寄存器分配图着色_寄存器分配

寄存器分配&#xff0c;是通过将程序变量尽可能地分配到寄存器&#xff0c;从而提高程序执行速度的一种方法。寄存器是编译器优化中最为重要的问题之一(好的寄存器分配能够提高程序执行速度超过250%)&#xff1b;也是编译器理论中最热点的研究领域之一(研究界已经提出来大量寄存…

通过Java,Spring Boot应用程序将Gmail用作SMTP服务器

Gmail用户可以使用Gmail的SMTP服务器smtp.gmail.com从其Spring Boot应用程序发送电子邮件。 为此&#xff0c;让我们在应用程序中进行一些设置&#xff1a; 在application.properties文件中提供SMTP连接属性&#xff1a; spring.mail.hostsmtp.gmail.com spring.mail.username…

在建工地扬尘在线监控系统推荐_配电室为何需要安装蓄电池在线监控系统?保定钰鑫电气...

配电室蓄电池在线监控系统提高了蓄电池运行质量、增强了电力系统的安全运行、保障蓄电池运行环境的可靠&#xff0c;打造无人值守配电室、智能化运维模式&#xff0c;减少蓄电池损耗、浪费&#xff0c;降低了维护成本&#xff0c;为何需要安装一套配电室蓄电池在线监测系统&…

最好的Java开发人员测试和集成工具

通过从应用程序中学习企业APM产品&#xff0c;发现更快&#xff0c;更高效的性能监控。 参加AppDynamics APM导览&#xff01; 无论您是刚开始还是已经使用了一段时间&#xff0c;使用正确的工具进行编程都可以对项目的成功产生巨大的影响。 适当的工具使您可以编写更好的代码…

最速下降法matlab全局最小值_梯度下降概念

1、梯度概念(1)从几何意义上讲&#xff0c;就是函数变化最快的地方。在单变量的函数中&#xff0c;梯度只是导数&#xff0c;其实就是函数在某个给定点的切线的斜率&#xff1b;在多变量函数中&#xff0c;梯度是一个向量&#xff0c;向量有方向&#xff0c;梯度的方向就指出了…

jpa querydsl_JPA – Querydsl投影

jpa querydsl在我的上一篇文章中&#xff1a; JPA –基本投影 –我提到了构建JPA投影的两种基本可能性。 这篇文章为您带来了更多示例&#xff0c;这次基于Querydsl框架。 注意&#xff0c;这里我指的是Querydsl版本3.1.1。 重塑构造函数表达式 看下面的代码&#xff1a; ...…