[Redis]Spring Boot中Redis Template集群配置 天天滚动
1、问题背景
在一个Spring boot项目中,需要使用redis作为缓存,于是将使用spring-boot-starter-data-redis,具体依赖如下:
org.springframework.boot spring-boot-starter-data-redis 2.0.4.RELEASE
在测试环境中,功能测试,压力测试,都没有发现问题,原因是测试环境中redis自行搭建,没有设置密码,但是上线后,Redis使用的是A***的Pass服务的集群,并设置密码,使用过程中发现如下问题:
redis负载高;redis异常,错误信息:com.lambdaworks.redis.RedisException: java.lang.IllegalArgumentException: Connection to XXX.XX.XXX.XXX:15000 not allowed. This connection point is not known in the cluster viewjava.lang.IllegalArgumentException: Connection to XXX.XX.XXX.XXX:15000 not allowed. This connection point is not known in the cluster viewConnection to XXX.XX.XXX.XXX:15000 not allowed. This connection point is not known in the cluster view
2、问题分析+解决方法
2.1、redis负载过高问题
2.1.1、问题原因
原本打算看一下是否是代码逻辑问题导致redis负载过高,于是登录redis服务器使用monitor命令观察命令执行的频率,发现每执行一次命令都执行一次Auth password
命令,说明连接池未正确使用导致执行一次命令创建一次连接,导致负载高 ,并且代码执行效率低 。
(资料图片仅供参考)
2.1.2、解决方法
然后对比了使用JedisCluster的项目没有此类问题,因此怀疑是spring-boot-starter-data-redis的RedisTemplate的问题,查看源码后发现spring-data-redis的驱动包在某个版本之后替换为 Lettuce,在启用集群后jedis的连接池无效。错误配置如下:
# 错误配置# Redis配置spring.redis.cluster.nodes=127.0.0.1:6379### 连接超时时间(毫秒)spring.redis.timeout=60000spring.redis.password=xxxxxxx# 连接池最大连接数(使用负值表示没有限制)spring.redis.jedis.pool.max-active=8##连接池最大阻塞等待时间,若使用负值表示没有限制spring.redis.jedis.pool.max-wait=-1##连接池中的最大空闲连接spring.redis.jedis.pool.max-idle=8# 连接池中的最小空闲连接spring.redis.jedis.pool.min-idle=0
需要改成正确的配置,修改之后无此现象,具体配置如下:
单机版:
# 单机版# Redis配置spring.redis.host=127.0.0.1spring.redis.port=6379### 连接超时时间(毫秒)spring.redis.timeout=60000spring.redis.password=xxxxxxx# 连接池最大连接数(使用负值表示没有限制)spring.redis.jedis.pool.max-active=8##连接池最大阻塞等待时间,若使用负值表示没有限制spring.redis.jedis.pool.max-wait=-1##连接池中的最大空闲连接spring.redis.jedis.pool.max-idle=8# 连接池中的最小空闲连接spring.redis.jedis.pool.min-idle=0
集群版:
#集群版 # Redis配置spring.redis.cluster.nodes=127.0.0.1:6379### 连接超时时间(毫秒)spring.redis.timeout=60000spring.redis.password=xxxxxxx# 连接池最大连接数(使用负值表示没有限制)spring.redis.lettuce.pool.max-active=8##连接池最大阻塞等待时间,若使用负值表示没有限制spring.redis.lettuce.pool.max-wait=-1##连接池中的最大空闲连接spring.redis.lettuce.pool.max-idle=8# 连接池中的最小空闲连接spring.redis.lettuce.pool.min-idle=0
注意:启用集群版,需要额外添加如下依赖
org.apache.commons commons-pool2 2.8.0
2.2、redis异常 Connection to XXX.XX.XXX.XXX:15000 not allowed 问题
2.2.1、问题原因
网上搜索了一下,发现项目github上已有此问题的反馈以及解决办法github.com/lettuce-io/…,原因是由于Lettuce其中有个配置项validateClusterNodeMembership
默认是true导致;
2.2.2、解决办法
由于spring boot未能直接通过配置文件直接修改此配置,因此需要自定义Redis配置,具体代码如下: MylettuceConnectionFactory.java
package com.quison.test.config;import io.lettuce.core.AbstractRedisClient;import io.lettuce.core.cluster.ClusterClientOptions;import io.lettuce.core.cluster.ClusterTopologyRefreshOptions;import io.lettuce.core.cluster.RedisClusterClient;import org.springframework.beans.DirectFieldAccessor;import org.springframework.data.redis.connection.RedisClusterConfiguration;import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;import java.util.concurrent.TimeUnit;public class MyLettuceConnectionFactory extends LettuceConnectionFactory { public MyLettuceConnectionFactory() { } public MyLettuceConnectionFactory(RedisClusterConfiguration redisClusterConfiguration, LettuceClientConfiguration lettuceClientConfiguration) { super(redisClusterConfiguration, lettuceClientConfiguration); } @Override public void afterPropertiesSet() { super.afterPropertiesSet(); DirectFieldAccessor accessor = new DirectFieldAccessor(this); AbstractRedisClient client = (AbstractRedisClient) accessor.getPropertyValue("client"); if(client instanceof RedisClusterClient){ RedisClusterClient clusterClient = (RedisClusterClient) client; ClusterTopologyRefreshOptions topologyRefreshOptions = ClusterTopologyRefreshOptions.builder() .enablePeriodicRefresh(10, TimeUnit.MINUTES) .enableAllAdaptiveRefreshTriggers() .build(); ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder() // 注意此配置项设置为false .validateClusterNodeMembership(false) .topologyRefreshOptions(topologyRefreshOptions) .build(); clusterClient.setOptions(clusterClientOptions); } }}
由于配置后,连接池也需要自行设置,因此Redis的配置文件修改为如下设置 RedisConfig.java
package com.quison.test.config;import org.apache.commons.pool2.impl.GenericObjectPoolConfig;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;import org.springframework.boot.autoconfigure.data.redis.RedisProperties;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Primary;import org.springframework.data.redis.connection.*;import org.springframework.data.redis.connection.lettuce.DefaultLettucePool;import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.serializer.RedisSerializer;import org.springframework.data.redis.serializer.StringRedisSerializer;import java.time.Duration;import java.util.Arrays;import java.util.HashSet;import java.util.Set;@Configurationpublic class RedisConfig { @Value("${spring.redis.cluster.nodes}") private String clusterNodes; @Value("${spring.redis.password}") private String password; @Value("${spring.redis.lettuce.pool.max-idle}") private Integer maxIdle; @Value("${spring.redis.lettuce.pool.max-active}") private Integer maxActive; @Value("${spring.redis.cluster.max-redirects}") private Integer maxRedirects; @Bean public RedisConnectionFactory myRedisConnectionFactory() { RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration(); String[] serverArray = clusterNodes.split(","); Set nodes = new HashSet(); for (String ipPort : serverArray) { String[] ipAndPort = ipPort.split(":"); nodes.add(new RedisNode(ipAndPort[0].trim(), Integer.valueOf(ipAndPort[1]))); } redisClusterConfiguration.setPassword(RedisPassword.of(password)); redisClusterConfiguration.setClusterNodes(nodes); redisClusterConfiguration.setMaxRedirects(maxRedirects); GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig(); genericObjectPoolConfig.setMaxIdle(maxIdle); genericObjectPoolConfig.setMinIdle(8); genericObjectPoolConfig.setMaxTotal(maxActive); genericObjectPoolConfig.setMaxWaitMillis(10000); LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder() .commandTimeout(Duration.ofMillis(10000)) .poolConfig(genericObjectPoolConfig) .build(); return new MyLettuceConnectionFactory(redisClusterConfiguration, clientConfig); } /** * redis模板,存储关键字是字符串,值是Jdk序列化 * * @param myRedisConnectionFactory * @return * @Description: */ @Bean @ConditionalOnMissingBean(name = "redisTemplate") @Primary public RedisTemplate, ?> redisTemplate(RedisConnectionFactory myRedisConnectionFactory) { RedisTemplate, ?> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(myRedisConnectionFactory); //key序列化方式;但是如果方法上有Long等非String类型的话,会报类型转换错误; RedisSerializer redisSerializer = new StringRedisSerializer(); redisTemplate.setKeySerializer(redisSerializer); redisTemplate.setHashKeySerializer(redisSerializer); //默认使用JdkSerializationRedisSerializer序列化方式;会出现乱码,改成StringRedisSerializer StringRedisSerializer stringSerializer = new StringRedisSerializer(); redisTemplate.setKeySerializer(stringSerializer); redisTemplate.setValueSerializer(stringSerializer); redisTemplate.setHashKeySerializer(stringSerializer); redisTemplate.setHashValueSerializer(stringSerializer); return redisTemplate; }}
3、总结
吃一堑、长一智,总结如下:
开发+测试环境尽量与线上一致,可提前发现问题;使用新技术需要多多测试再投入生产使用;标签:
推荐
- [Redis]Spring Boot中Redis Template集群配置 天天滚动
- 上海交通大学附属中学招聘教师|世界观速讯
- 株洲市初中历史统编教材教学竞赛在天元中学举行
- 宁波职工养老保险缴费比例是多少? 世界热推荐
- 9种口味可选 宏绿自热煲仔饭6.7元/盒 每日热议
- 95568一直打电话干嘛_95568一直打电话
- 黄山、峨眉山预约额度有变!我国首枚2克纪念金币确定发行!
- 信用卡透支要利息吗现在_信用卡透支要利息吗
- 全球观察:强信心·开新局|新疆莎车:牛羊巴扎里的乡村振兴新图景
- 全球观天下!他今天结婚,全网祝福!
- 环球观速讯丨晋江兴泰制罐有限公司_对于晋江兴泰制罐有限公司简单介绍
- 强化运动氛围 新款大众Atlas新车图解-全球速讯
- 【新规】“头”等大事!又一国家标准发布实施!
- 观速讯丨中华狼青犬价格是多少_中华狼青犬价格
- 世界聚焦:警企共管构建新格局 协作并进助推新发展
- 全国唯一超3000万城市!成都去年航空旅客吞吐量3109万
- 春风送岗暖人心-高楼乡举办2023年“春风行动”暨就业援助月活动|世界新要闻
- 河洛大鼓李逵夺鱼_山东快书李逵夺鱼 焦点热门
- ck手表什么档次_ck手表怎么样_世界快看
- 当AI科技照进现实 安全问题不容忽视|环球时讯
- 环球观察:中国将全面恢复自澳大利亚煤炭进口?商务部回应
- 报告:近半数受访者每晚平均睡不足8小时 东北地区睡眠指数最高_世界速递
- 城管来了!一声声童真叫喊的背后,是城管对文明执法的误解 最新资讯
- 广告缝里看内容 关闭按钮“躲猫猫”|当前热点
- 环球快消息!电脑如何连接手机蓝牙_电脑如何连接手机
- 唯科科技:3月16日融资买入115.4万元,融资融券余额5006.68万元|最新快讯
- 第八次全国少代会主题_第八次全国少代会 每日短讯
- 世界热推荐:汉钟精机(002158):3月16日北向资金增持41.96万股
- 环球信息:英雄儿女主题曲原唱曲谱_英雄儿女主题曲原唱
- [快讯]舒华体育公布2022年年度分红方案
- 当前视讯!生物疫苗ETF: 关于鹏华国证疫苗与生物科技交易型开放式指数证券投资基金增加部分证券公司为申购赎回代理券商的公告
- 人间丨82岁山东老人获感动中国“银发知播”奖 要与时俱进把电工课上下去
- 电视广播再度暴跌10%,自高点股价腰斩,公司再遭第三大股东减持
- 美国学者:中国成功抵御风暴实现增长 大量需求待释放丨两会·世界观
- 招商轮船盘中异动 股价大幅振动4.92% 跌6.94% 报7.37元 今日看点
- 一个妈妈的反校园暴力“战斗” 具体详细内容是什么
- 热资讯!秋名山车神是什么电影
- 三国小镇怎么得灵宠_三国小镇怎么捕捉灵兽
- 合资车杀手来了!比亚迪汉EV冠军版/唐DM-i冠军版正式官宣
- 天天快看:mpp管是什么管
- “钱取出来了”:创投人自述硅谷银行倒闭72小时
- 瑞纳智能3月15日快速反弹
- 女性气血不足吃什么好_女性气血不足可以吃什么
- 慢性肾病分期的标准是什么_慢性肾病分期的标准 今日看点
- 全球最新:在线pdf转换成jpg图片?文件转图片教学
- 世界要闻:中文在线(300364):3月14日北向资金增持126.58万股
- 绍兴市卫生局领导_绍兴市卫生局
- 陌生的反义词是什么_陌生的意思
- 南通洲际梦幻岛医护人员免票吗?
- 熊出没探险日记第三部_熊出没之探险日记3季什么时候出播 全球播报
- 成都乙肝疫苗接种点
- 世界视点!实验室硫酸的用途_硫酸的用途
- 75%酒精棉片可以擦iphone屏幕吗?
- 成年人晚上看的网站_成年人看的4级网站
- 【发现春之美】康平卧龙湖:百万候鸟大迁徙启幕-世界视点
- 全英赛首轮即将开打!不是冤家不聚首,国羽男单组仅石宇奇稍轻松
- 贵州省康复医院2023年公开招聘合同制岗位有哪些? 今头条
- 南阳市不动产怎么查询?附网上查询入口
- 科济药业-B:并未在SVB持有现金存款或信贷额度,与SVB亦无其他业务关系 天天快资讯
- 哈维:巴萨在比分领先时表现欠佳 为球队的拼搏精神感到骄傲
- 印度IT部长:将会晤创业公司 协调硅谷银行破产影响|环球热点评
- 义的作文结尾(通用80篇)_观焦点
- 恩平开展义务植树活动,同绘绿画卷!
- 浙江东日: 浙江东日股份有限公司董事会关于前次募集资金存放与实际使用情况的专项报告 当前热文
- 环球今头条!计算机网络技术学什么好_计算机网络技术学什么
- 2023卫生健康预算支出持续增加 超出多个省份1年GDP
- 即时看!a计划演员表1983_a计划演员表
- 动态:杭州翔赞车业有限公司_关于杭州翔赞车业有限公司简述
- 车的部首的近义词_天天热议
- 每日头条!2022百战直播年度榜单出炉 生态建设已初具规模
- 焗饭的做法烤箱视频_焗饭的做法烤箱几分钟-世界短讯
- 环球看点!孙子“随母姓”,大爷怒将80万房产送侄子,儿媳发飙:真是老顽固
- iapo 环球关注
- 深市民营上市公司经营稳中向好 高质量发展动能澎湃
- 天齐锂业(002466)股东成都天齐实业(集团)有限公司质押630万股,占总股本0.38%
- 天天速讯:国美零售:预期2022年亏损将在人民币170亿元-190亿元之间
- 松针油能清除血管里的斑块吗_松针油|天天新视野
- 从“搭积木”到“做积木” 湖南最大规模钢结构制造基地投产-今日聚焦
- 无公害蔬菜基地名字大全_无公害蔬菜基地 精选
- meyu_全球新资讯
- 财政部拟发行880亿元2年期国债 手续费为承销面值的0.04%|快讯
- 天天快看点丨郑爽又出事了 ? 工作室被执行 7000 余万系合同纠纷案
- 林家宅事件真相_林家宅-实时
- 吴易昺拿下海外大师赛首胜
- 近期河北将有两次大风降温沙尘天气
- 当前报道:心情烦躁焦虑易怒失眠怎么办_心情烦躁失眠怎么缓解
- 焦点资讯:校园修神录3.96攻略_校园修神录3 0攻略
- 公办幼儿园教师张某多次申报职称未果_公办幼儿园-当前头条
- 「天眼关注」贵州疾控发布提示:有毒!这些野果和种子不能吃
- 小米新品发布会视频直播_小米6X发布会直播地址_官网视频直播网址
- 林哥哥首破红楼奥义,重建红学新秩序_环球通讯
- 天天观点:上海半程马拉松时隔两年活力回归,即日起启动报名工作
- 【世界新视野】一个连多少人一个营多少人一个团(一个连多少人)
- 当面付怎么对接网站_当面付
- 世界快资讯丨签署七个合作协议 川渝贸促系统协同发展联席会议成功举行
- 如何评价奔驰的新电动SUV EQC和多少是大众旅行车?
- 观天下!经济日报:煤炭消费占比微升并非开倒车
- 全球快讯:微信怎么加更多的人聊天_微信怎么加更多的人
- 生牛乳和鲜牛奶哪个更好(生牛乳和鲜牛奶的区别) 环球快播
- 火箭内线新星已经得到了对手的认可,可是塞拉斯却对此表示怀疑? 全球快讯
X 关闭
行业规章
X 关闭